123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.IO;
- using System.Media;
- using System.Text.RegularExpressions;
- using NTERA.Core;
- using NTERA.EmuEra.Game.EraEmu.Sub;
- // Created by Bartoum.
- // Class that is initialized one time in Constant data.
- // Create a dictionary of dictionary for each *_TR.csv that is there
- namespace NTERA.EmuEra.Game.EraEmu.GameData.Variable
- {
- internal class Translation // JVN: making it internal allows to pass the Emueraconsole by reference here
- {
- public static Dictionary<string, Dictionary<string, string>> nameTlDictionnary;
- public static string[] fileArray;
- private static ArrayList memoryArray;
- private static string lastRet;
- private static int nbrMemory = 20;
- private static bool canLoadParam;
- private static Dictionary<Int64, TRCharaTemplate> TRCharaList; // JVN: A simple dictionary, only needs the character number as a key.
- private static IConsole output; // JVN: Console access is a must, debug is life, debug is <3
- public enum CharaData
- { Name = 0, Callname, Nickname, Mastername, CSTR} // JVN: enums are noice.
- // JVN: Templates are good too. Make it private too, because it's only used interally
- private class TRCharaTemplate
- {
- public Int64 No;
- public string Name;
- public string Callname;
- public string Nickname;
- public string Mastername;
- public Dictionary<Int32, string> CStr;
- // JVN: Construct
- public TRCharaTemplate(Int64 aNo = 0, string aName ="", string aCall ="", string aNick = "", string aMaster = "")
- {
- No = aNo;
- Name = aName;
- Callname = aCall;
- Nickname = aNick;
- Mastername = aMaster;
- CStr = new Dictionary<Int32, string>();
- }
- // JVN: Cloning is important for what we need to do
- public TRCharaTemplate Clone()
- {
- TRCharaTemplate tmp = new TRCharaTemplate(No, Name, Callname, Nickname, Mastername);
- foreach (KeyValuePair<Int32, string> cloneData in CStr)
- {
- tmp.CStr.Add(cloneData.Key, cloneData.Value);
- }
- return tmp;
- }
- }
- //Constructor
- public Translation(string csvDir, ref IConsole console, bool pcanLoadParam)
- {
- output = console; // JVN: Debugging is important, and the console allows for that
- canLoadParam = pcanLoadParam;
- loadTranslationData(csvDir);
- loadCharacterTranslationData(csvDir);
- }
- //JVN: I just wants it
- public static bool isCanLoadParam() { return canLoadParam; }
- private const bool translateCSVAnyways = false; // TODO: make this configurable, somehow, probably via CSV setting?
- //Normal way to translate original is the string of the variable we are working with and name is the file where it lives ex: Talent or Source. It can also be ALL.
- public static string translate(string original, string name, bool tryTranslate){
- string ret;
- ret = original;
- if (name == "Palam" && canLoadParam)
- name = "Param";
-
-
- //Change the original term to the translated one;
- if (original != null){
- if(nameTlDictionnary.ContainsKey(name) && nameTlDictionnary[name].ContainsKey(original)){
- if(tryTranslate || translateCSVAnyways)
- {
- ret = nameTlDictionnary[name][original];
- lastRet = ret;
- }
- else{
- if (memoryArray.IndexOf(original + "," + name) == -1)
- memoryArray.Add(original + "," + name);
- if (memoryArray.Count >= nbrMemory)
- memoryArray.RemoveAt(0);
- }
- }
- }
- return ret;
- }
- // JVN: Character string translation
- public static string translateChara(Int64 character, CharaData varname, string oriString, Int32 index = 0) {
- switch (varname)
- {
- case CharaData.Name: // "NAME","名前"
- if (TRCharaList.ContainsKey(character)) return TRCharaList[character].Name;
- break;
- case CharaData.Callname: // "CALLNAME","呼び名"
- if (TRCharaList.ContainsKey(character)) return TRCharaList[character].Callname;
- break;
- case CharaData.Nickname: // "NICKNAME","あだ名"
- if (TRCharaList.ContainsKey(character)) return TRCharaList[character].Nickname;
- break;
- case CharaData.Mastername: // "MASTERNAME","主人の呼び方"
- if (TRCharaList.ContainsKey(character)) return TRCharaList[character].Mastername;
- break;
- case CharaData.CSTR: // "CSTR"
- if (TRCharaList.ContainsKey(character))
- if (TRCharaList[character].CStr.ContainsKey(index)) return TRCharaList[character].CStr[index];
- break;
- }
- return oriString;
- }
- //The last way to translate something.
- public static string translateALL(string original, string pname ="ALL")
- {
- string ret = original;
- if (!String.IsNullOrEmpty(original))
- {
- bool found = false;
- string[] temp;
- int i = memoryArray.Count - 1;
- if (!String.IsNullOrEmpty(lastRet) && original.Contains(lastRet))
- {
- //output.Print("Did it brah\n");
- found = true;
- }
- while (i >= 0 && !found)
- {
- temp = memoryArray[i].ToString().Split(',');
- // output.Print("Checked: " + original + " against: " + temp[0] + " \\ ");
- if (original.Contains(temp[0]))
- {
- //output.Print("FOUND IT with:" +temp[1]+ " " + temp[0] + " \n");
- ret = original.Replace(temp[0], nameTlDictionnary[temp[1]][temp[0]]);
- found = true;
- //memoryArray.Remove(temp[0] + "," + temp[1]);
- }
- i--;
- }
- //output.Print("\n");
- if (!found)
- {
- if (nameTlDictionnary.ContainsKey(pname))
- {
- //We try to strip all the stuff around the csv variable name
- //Remove all numbers, remove LV and all special characters bellow
- //Parantheses are only remove if only numbers where inside them because some variable name use them
- bool numPresent = true;
- //We remove all the numbers
- while (numPresent)
- {
- if (Regex.Match(original, @"\d+").Value != "")
- {
- original = original.Replace(Regex.Match(original, @"\d+").Value, "");
- }
- else
- {
- numPresent = false;
- }
- }
- //original = original.Replace("-", "");
- //original = original.Replace("()", "");
- original = original.Replace("【", "");
- original = original.Replace("】", "");
- original = original.Replace("[", "");
- original = original.Replace("]", "");
- original = original.Replace("LV", "");
- original = original.Replace("『", "");
- original = original.Replace("』", "");
- /*
- original = original.Replace("1Lv", "");
- original = original.Replace("2Lv", "");
- original = original.Replace("3Lv", "");
- original = original.Replace("4Lv", "");
- original = original.Replace("5Lv", "");
- */
- //output.Print("Did it the old stupid way\n");
- if (nameTlDictionnary[pname].ContainsKey(original))
- {
- ret = ret.Replace(original, nameTlDictionnary[pname][original]);
- //output.Print("Found it the stupid way");
- }
- }
- }
- }
- return ret;
- }
- private void loadTranslationData(string csvDir)
- {
- fileArray = new[] {"Abl", "Talent", "Exp", "Mark", "Palam", "Param", "Item","Train", "Base","Source", "Ex", "EQUIP", "TEQUIP", "Flag", "TFLAG", "Cflag", "Tcvar", "CSTR", "Stain","Cdflag1", "Cdflag2", "Str", "TSTR","SaveStr", "GLOBAL", "GLOBALS","ALL"};
- nameTlDictionnary = new Dictionary<string, Dictionary<string, string> >();
- memoryArray = new ArrayList();
- string temp;
- for (int i = 0; i < fileArray.Length;i++){
- Dictionary<string,string> tempDictionnary = new Dictionary<string,string>();
-
- string csvPath = csvDir + fileArray[i] + "_TR.csv";
- if (!File.Exists(csvPath))
- continue;
-
- EraStreamReader eReader = new EraStreamReader(false);
-
- if (!eReader.Open(csvPath))
- throw new Exception(eReader.Filename + " can't be opened");
- ScriptPosition position = null;
- try
- {
- StringStream st = null;
- while ((st = eReader.ReadEnabledLine()) != null)
- {
- position = new ScriptPosition(eReader.Filename, eReader.LineNo, st.RowString);
- temp = st.Substring();
- if (temp[0] == ';')
- continue;
- if (temp.Contains(";"))
- temp = temp.Substring(0, temp.IndexOf(';'));
- string[] tokens = temp.Split(',');
- //Make it crash with a good message if there's not a ","
- if(tokens.Length != 2)
- throw new Exception("A line must have one \",\" to separate the original from the new string. The line with the problem begins by : " + tokens[0]);
- //Make it crash with a good message if the same key is present two times
- if (tempDictionnary.ContainsKey(tokens[0]))
- throw new Exception("You can only have one occurence of the same key. " + tokens[0] + " is already linked to : " + tempDictionnary[tokens[0]]);
-
- tempDictionnary.Add(tokens[0], tokens[1]);
- }
- nameTlDictionnary.Add(fileArray[i], tempDictionnary);
- }
- catch(Exception e)
- {
- throw new Exception(e.Message);
- }
- finally
- {
- eReader.Close();
- }
- }
- }
- //Receive the line that is being interpreted as a string.
- //if there's a TALENTXXX in this string it will return the XXX
- //if not it will return ALL.
- public static string searchParentFile(string name)
- {
- string ret = "ALL";
- int i = 0;
- bool found = false;
- try
- {
- if (name.Contains("NAME")){
- while (i < fileArray.Length - 1 && !found)
- {
- if (name.Contains(fileArray[i].ToUpper() + "NAME"))
- {
- ret = fileArray[i];
- found = true;
- }
- i++;
- }
- }
-
- }
- catch(Exception e)
- {
- throw new Exception(e.Message);
- }
- return ret;
- }
- // JVN: Loading fuctions for TRCHARA*.CSV
- private void loadCharacterTranslationData(string csvDir, bool useCompatiName = false, bool disp = false)
- {
- if (!Directory.Exists(csvDir))
- return;
- TRCharaList = new Dictionary<long, TRCharaTemplate>();
- // JVN: Search the CSV and subdirectories for TRCHARA files and send that to a function for futher loading
- List<KeyValuePair<string, string>> csvPaths = Config.Config.GetFiles(csvDir, "TRCHARA*.CSV");
- for (int i = 0; i < csvPaths.Count; i++)
- loadTRCharacterDataFile(csvPaths[i].Value, csvPaths[i].Key, disp);
- if (useCompatiName) // check for the compatibility flag, just in case
- {
- foreach (KeyValuePair<Int64, TRCharaTemplate> tmpl in TRCharaList)
- if (string.IsNullOrEmpty(tmpl.Value.Callname))
- tmpl.Value.Callname = tmpl.Value.Name;
- }
- }
- // JVN: Loads individual character files and data
- private void loadTRCharacterDataFile(string csvPath, string csvName, bool disp)
- {
- bool NextCharacter = false;
- EraStreamReader eReader = new EraStreamReader(false);
- if (!eReader.Open(csvPath, csvName))
- {
- output.PrintError("File " + eReader.Filename + " has failed to open");
- return;
- }
- ScriptPosition position = null;
- if (disp)
- output.PrintSystemLine(eReader.Filename + " is being read・・・");
- try
- {
- TRCharaTemplate tmpl = null;
- Int64 index = -1;
- StringStream st = null;
- bool Alive = true;
- while (Alive || NextCharacter)
- {
- Alive = (st = eReader.ReadEnabledLine()) != null;
- if (NextCharacter)
- {
- if (tmpl != null) {
- TRCharaTemplate tmp = tmpl.Clone();
- TRCharaList.Add(index, tmp);
- tmpl = null;
- NextCharacter = false;
- }
- if (!Alive) break;
- }
- position = new ScriptPosition(eReader.Filename, eReader.LineNo, st.RowString);
- string[] tokens = st.Substring().Split(',');
- if (tokens.Length < 2)
- {
- ParserMediator.Warn("\",\" is needed", position, 1);
- continue;
- }
- if (tokens[0].Length == 0)
- {
- ParserMediator.Warn("Begins in \",\"", position, 1);
- continue;
- }
- if ((tokens[0].Equals("NO", Config.Config.SCVariable)) || (tokens[0].Equals("番号", Config.Config.SCVariable)))
- {
- if (tmpl != null)
- {
- ParserMediator.Warn("Character number has been defined twice", position, 1);
- continue;
- }
- if (!Int64.TryParse(tokens[1].TrimEnd(), out index))
- {
- ParserMediator.Warn(tokens[1] + " cannot be changed into an integer", position, 1);
- continue;
- }
- tmpl = new TRCharaTemplate(index);
- continue;
- }
- if (tmpl == null)
- {
- ParserMediator.Warn("Data started before the character number is defined", position, 1);
- continue;
- }
- NextCharacter = toTRCharaTemplate(position, tmpl, tokens);
- }
- }
- catch (Exception e)
- {
- SystemSounds.Hand.Play();
- if (position != null)
- {
- output.PrintError(e.ToString());
- ParserMediator.Warn("An unexpected error has occurred", position, 3);
- }
- else
- {
- output.PrintError("An unexpected error has occurred");
- }
- output.PrintError("");
- }
- finally
- {
- eReader.Dispose();
- }
- }
- // JVN: Copy of the ConstantData's tryTo64
- private bool tryToInt64(string str, out Int64 p)
- {
- p = -1;
- if (string.IsNullOrEmpty(str))
- return false;
- StringStream st = new StringStream(str);
- int sign = 1;
- if (st.Current == '+')
- st.ShiftNext();
- else if (st.Current == '-')
- {
- sign = -1;
- st.ShiftNext();
- }
- //1803beta005 char.IsDigitは全角数字とかまでひろってしまうので・・・
- //if (!char.IsDigit(st.Current))
- // return false;
- switch (st.Current)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break;
- default:
- return false;
- }
- try
- {
- p = LexicalAnalyzer.ReadInt64(st, false);
- p = p * sign;
- }
- catch
- {
- return false;
- }
- return true;
- }
- // JVN: Takes care of each line being read and sends result back. That works too. Returns false if 'ENDCHR' is found.
- private bool toTRCharaTemplate(ScriptPosition position, TRCharaTemplate chara, string[] tokens)
- {
- if (chara == null)
- return true;
- int length = -1;
- Int64 p1 = -1;
- //Int64 p2 = -1;
- //Dictionary<int, Int64> intArray = null;
- Dictionary<int, string> strArray = null;
- Dictionary<string, int> namearray = null;
- string errPos = null;
- string varname = tokens[0].ToUpper();
- switch (varname)
- {
- case "NAME":
- case "名前":
- chara.Name = tokens[1];
- return false;
- case "CALLNAME":
- case "呼び名":
- chara.Callname = tokens[1];
- return false;
- case "NICKNAME":
- case "あだ名":
- chara.Nickname = tokens[1];
- return false;
- case "MASTERNAME":
- case "主人の呼び方":
- chara.Mastername = tokens[1];
- return false;
- case "CSTR":
- strArray = chara.CStr;
- errPos = "cstr.csv";
- break;
- case "ENDCHR":
- case "ENDCHAR":
- return true;
- default:
- ParserMediator.Warn("\"" + tokens[0] + "\" cannot be interpreted", position, 1);
- return false;
- }
- bool p1isNumeric = tryToInt64(tokens[1].TrimEnd(), out p1);
- int index = (int)p1;
- if ((!p1isNumeric) && (namearray != null))
- {
- if (!namearray.TryGetValue(tokens[1], out index))
- {
- ParserMediator.Warn(errPos + ": \"" + tokens[1] + "\" is undefined", position, 1);
- return false;
- }
- if (index >= length)
- {
- ParserMediator.Warn("\"" + tokens[1] + "\" is out of bounds of the array", position, 1);
- return false;
- }
- }
- if (strArray != null)
- {
- if (tokens.Length < 3)
- ParserMediator.Warn("There's no third identifier", position, 1);
- if (strArray.ContainsKey(index))
- ParserMediator.Warn(varname + "'s #" + index + " element is already denied (Overwritting it)", position, 1);
- strArray[index] = tokens[2];
- }
- return false;
- }
- }
- }
|