feat(battle-engine): full Unity/VFX/god-object shims + expanded copy closure (2570 files)
Authored Unity primitive/object-model shim, VFX layer (control-flow-preserving, InstantVfx never invokes its action -- headless suppression), god-object stubs (GameMgr/EffectMgr/UIManager with faithfully-extracted nested enums), View/UI/Touch tree, LitJson+BetterList+Tuple copied, third-party stubs. Discovered Roslyn header-error masking: fixing class-header type errors unmasks body references, so the true copy closure is ~2570 files (was 782 under masking). Errors: masked-25720 -> 268; our shim files compile clean. Remaining: ~50 residual shim/external types, 24 NGUI UI-base overrides, static-type fixes, plus likely 1-2 more unmask waves.
This commit is contained in:
527
SVSim.BattleEngine/Engine/Localization.cs
Normal file
527
SVSim.BattleEngine/Engine/Localization.cs
Normal file
@@ -0,0 +1,527 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public static class Localization
|
||||
{
|
||||
public delegate byte[] LoadFunction(string path);
|
||||
|
||||
public delegate void OnLocalizeNotification();
|
||||
|
||||
public static LoadFunction loadFunction;
|
||||
|
||||
public static OnLocalizeNotification onLocalize;
|
||||
|
||||
public static bool localizationHasBeenSet = false;
|
||||
|
||||
private static string[] mLanguages = null;
|
||||
|
||||
private static Dictionary<string, string> mOldDictionary = new Dictionary<string, string>();
|
||||
|
||||
private static Dictionary<string, string[]> mDictionary = new Dictionary<string, string[]>();
|
||||
|
||||
private static Dictionary<string, string> mReplacement = new Dictionary<string, string>();
|
||||
|
||||
private static int mLanguageIndex = -1;
|
||||
|
||||
private static string mLanguage;
|
||||
|
||||
private static bool mMerging = false;
|
||||
|
||||
public static Dictionary<string, string[]> dictionary
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!localizationHasBeenSet)
|
||||
{
|
||||
LoadDictionary(PlayerPrefs.GetString("Language", "English"));
|
||||
}
|
||||
return mDictionary;
|
||||
}
|
||||
set
|
||||
{
|
||||
localizationHasBeenSet = value != null;
|
||||
mDictionary = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] knownLanguages
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!localizationHasBeenSet)
|
||||
{
|
||||
LoadDictionary(PlayerPrefs.GetString("Language", "English"));
|
||||
}
|
||||
return mLanguages;
|
||||
}
|
||||
}
|
||||
|
||||
public static string language
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(mLanguage))
|
||||
{
|
||||
mLanguage = PlayerPrefs.GetString("Language", "English");
|
||||
LoadAndSelect(mLanguage);
|
||||
}
|
||||
return mLanguage;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (mLanguage != value)
|
||||
{
|
||||
mLanguage = value;
|
||||
LoadAndSelect(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Localization is now always active. You no longer need to check this property.")]
|
||||
public static bool isActive => true;
|
||||
|
||||
private static bool LoadDictionary(string value)
|
||||
{
|
||||
byte[] array = null;
|
||||
if (!localizationHasBeenSet)
|
||||
{
|
||||
if (loadFunction == null)
|
||||
{
|
||||
TextAsset textAsset = Resources.Load<TextAsset>("Localization");
|
||||
if (textAsset != null)
|
||||
{
|
||||
array = textAsset.bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array = loadFunction("Localization");
|
||||
}
|
||||
localizationHasBeenSet = true;
|
||||
}
|
||||
if (LoadCSV(array))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
value = mLanguage;
|
||||
}
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (loadFunction == null)
|
||||
{
|
||||
TextAsset textAsset2 = Resources.Load<TextAsset>(value);
|
||||
if (textAsset2 != null)
|
||||
{
|
||||
array = textAsset2.bytes;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array = loadFunction(value);
|
||||
}
|
||||
if (array != null)
|
||||
{
|
||||
Set(value, array);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool LoadAndSelect(string value)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
if (mDictionary.Count == 0 && !LoadDictionary(value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (SelectLanguage(value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (mOldDictionary.Count > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
mOldDictionary.Clear();
|
||||
mDictionary.Clear();
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
PlayerPrefs.DeleteKey("Language");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void Load(TextAsset asset)
|
||||
{
|
||||
ByteReader byteReader = new ByteReader(asset);
|
||||
Set(asset.name, byteReader.ReadDictionary());
|
||||
}
|
||||
|
||||
public static void Set(string languageName, byte[] bytes)
|
||||
{
|
||||
ByteReader byteReader = new ByteReader(bytes);
|
||||
Set(languageName, byteReader.ReadDictionary());
|
||||
}
|
||||
|
||||
public static void ReplaceKey(string key, string val)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(val))
|
||||
{
|
||||
mReplacement[key] = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
mReplacement.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearReplacements()
|
||||
{
|
||||
mReplacement.Clear();
|
||||
}
|
||||
|
||||
public static bool LoadCSV(TextAsset asset, bool merge = false)
|
||||
{
|
||||
return LoadCSV(asset.bytes, asset, merge);
|
||||
}
|
||||
|
||||
public static bool LoadCSV(byte[] bytes, bool merge = false)
|
||||
{
|
||||
return LoadCSV(bytes, null, merge);
|
||||
}
|
||||
|
||||
private static bool HasLanguage(string languageName)
|
||||
{
|
||||
int i = 0;
|
||||
for (int num = mLanguages.Length; i < num; i++)
|
||||
{
|
||||
if (mLanguages[i] == languageName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool LoadCSV(byte[] bytes, TextAsset asset, bool merge = false)
|
||||
{
|
||||
if (bytes == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ByteReader byteReader = new ByteReader(bytes);
|
||||
BetterList<string> betterList = byteReader.ReadCSV();
|
||||
if (betterList.size < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
betterList.RemoveAt(0);
|
||||
string[] array = null;
|
||||
if (string.IsNullOrEmpty(mLanguage))
|
||||
{
|
||||
localizationHasBeenSet = false;
|
||||
}
|
||||
if (!localizationHasBeenSet || (!merge && !mMerging) || mLanguages == null || mLanguages.Length == 0)
|
||||
{
|
||||
mDictionary.Clear();
|
||||
mLanguages = new string[betterList.size];
|
||||
if (!localizationHasBeenSet)
|
||||
{
|
||||
mLanguage = PlayerPrefs.GetString("Language", betterList[0]);
|
||||
localizationHasBeenSet = true;
|
||||
}
|
||||
for (int i = 0; i < betterList.size; i++)
|
||||
{
|
||||
mLanguages[i] = betterList[i];
|
||||
if (mLanguages[i] == mLanguage)
|
||||
{
|
||||
mLanguageIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array = new string[betterList.size];
|
||||
for (int j = 0; j < betterList.size; j++)
|
||||
{
|
||||
array[j] = betterList[j];
|
||||
}
|
||||
for (int k = 0; k < betterList.size; k++)
|
||||
{
|
||||
if (HasLanguage(betterList[k]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int num = mLanguages.Length + 1;
|
||||
Array.Resize(ref mLanguages, num);
|
||||
mLanguages[num - 1] = betterList[k];
|
||||
Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>();
|
||||
foreach (KeyValuePair<string, string[]> item in mDictionary)
|
||||
{
|
||||
string[] array2 = item.Value;
|
||||
Array.Resize(ref array2, num);
|
||||
array2[num - 1] = array2[0];
|
||||
dictionary.Add(item.Key, array2);
|
||||
}
|
||||
mDictionary = dictionary;
|
||||
}
|
||||
}
|
||||
Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
|
||||
for (int l = 0; l < mLanguages.Length; l++)
|
||||
{
|
||||
dictionary2.Add(mLanguages[l], l);
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
BetterList<string> betterList2 = byteReader.ReadCSV();
|
||||
if (betterList2 == null || betterList2.size == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(betterList2[0]))
|
||||
{
|
||||
AddCSV(betterList2, array, dictionary2);
|
||||
}
|
||||
}
|
||||
if (!mMerging && onLocalize != null)
|
||||
{
|
||||
mMerging = true;
|
||||
OnLocalizeNotification onLocalizeNotification = onLocalize;
|
||||
onLocalize = null;
|
||||
onLocalizeNotification();
|
||||
onLocalize = onLocalizeNotification;
|
||||
mMerging = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void AddCSV(BetterList<string> newValues, string[] newLanguages, Dictionary<string, int> languageIndices)
|
||||
{
|
||||
if (newValues.size < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
string text = newValues[0];
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
string[] value = ExtractStrings(newValues, newLanguages, languageIndices);
|
||||
if (mDictionary.ContainsKey(text))
|
||||
{
|
||||
mDictionary[text] = value;
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
mDictionary.Add(text, value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError("Unable to add '" + text + "' to the Localization dictionary.\n" + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static string[] ExtractStrings(BetterList<string> added, string[] newLanguages, Dictionary<string, int> languageIndices)
|
||||
{
|
||||
if (newLanguages == null)
|
||||
{
|
||||
string[] array = new string[mLanguages.Length];
|
||||
int i = 1;
|
||||
for (int num = Mathf.Min(added.size, array.Length + 1); i < num; i++)
|
||||
{
|
||||
array[i - 1] = added[i];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
string key = added[0];
|
||||
if (!mDictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
value = new string[mLanguages.Length];
|
||||
}
|
||||
int j = 0;
|
||||
for (int num2 = newLanguages.Length; j < num2; j++)
|
||||
{
|
||||
string key2 = newLanguages[j];
|
||||
int num3 = languageIndices[key2];
|
||||
value[num3] = added[j + 1];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static bool SelectLanguage(string language)
|
||||
{
|
||||
mLanguageIndex = -1;
|
||||
if (mDictionary.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int i = 0;
|
||||
for (int num = mLanguages.Length; i < num; i++)
|
||||
{
|
||||
if (mLanguages[i] == language)
|
||||
{
|
||||
mOldDictionary.Clear();
|
||||
mLanguageIndex = i;
|
||||
mLanguage = language;
|
||||
PlayerPrefs.SetString("Language", mLanguage);
|
||||
if (onLocalize != null)
|
||||
{
|
||||
onLocalize();
|
||||
}
|
||||
UIRoot.Broadcast("OnLocalize");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void Set(string languageName, Dictionary<string, string> dictionary)
|
||||
{
|
||||
mLanguage = languageName;
|
||||
PlayerPrefs.SetString("Language", mLanguage);
|
||||
mOldDictionary = dictionary;
|
||||
localizationHasBeenSet = true;
|
||||
mLanguageIndex = -1;
|
||||
mLanguages = new string[1] { languageName };
|
||||
if (onLocalize != null)
|
||||
{
|
||||
onLocalize();
|
||||
}
|
||||
UIRoot.Broadcast("OnLocalize");
|
||||
}
|
||||
|
||||
public static void Set(string key, string value)
|
||||
{
|
||||
if (mOldDictionary.ContainsKey(key))
|
||||
{
|
||||
mOldDictionary[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mOldDictionary.Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Get(string key)
|
||||
{
|
||||
if (!localizationHasBeenSet)
|
||||
{
|
||||
LoadDictionary(PlayerPrefs.GetString("Language", "English"));
|
||||
}
|
||||
if (mLanguages == null)
|
||||
{
|
||||
Debug.LogError("No localization data present");
|
||||
return null;
|
||||
}
|
||||
string text = language;
|
||||
if (mLanguageIndex == -1)
|
||||
{
|
||||
for (int i = 0; i < mLanguages.Length; i++)
|
||||
{
|
||||
if (mLanguages[i] == text)
|
||||
{
|
||||
mLanguageIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mLanguageIndex == -1)
|
||||
{
|
||||
mLanguageIndex = 0;
|
||||
mLanguage = mLanguages[0];
|
||||
}
|
||||
string value;
|
||||
string[] value2;
|
||||
switch (UICamera.currentScheme)
|
||||
{
|
||||
case UICamera.ControlScheme.Touch:
|
||||
{
|
||||
string key3 = key + " Mobile";
|
||||
if (mReplacement.TryGetValue(key3, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
if (mLanguageIndex != -1 && mDictionary.TryGetValue(key3, out value2) && mLanguageIndex < value2.Length)
|
||||
{
|
||||
return value2[mLanguageIndex];
|
||||
}
|
||||
if (mOldDictionary.TryGetValue(key3, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UICamera.ControlScheme.Controller:
|
||||
{
|
||||
string key2 = key + " Controller";
|
||||
if (mReplacement.TryGetValue(key2, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
if (mLanguageIndex != -1 && mDictionary.TryGetValue(key2, out value2) && mLanguageIndex < value2.Length)
|
||||
{
|
||||
return value2[mLanguageIndex];
|
||||
}
|
||||
if (mOldDictionary.TryGetValue(key2, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mReplacement.TryGetValue(key, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
if (mLanguageIndex != -1 && mDictionary.TryGetValue(key, out value2))
|
||||
{
|
||||
if (mLanguageIndex < value2.Length)
|
||||
{
|
||||
string text2 = value2[mLanguageIndex];
|
||||
if (string.IsNullOrEmpty(text2))
|
||||
{
|
||||
text2 = value2[0];
|
||||
}
|
||||
return text2;
|
||||
}
|
||||
return value2[0];
|
||||
}
|
||||
if (mOldDictionary.TryGetValue(key, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
public static string Format(string key, params object[] parameters)
|
||||
{
|
||||
return string.Format(Get(key), parameters);
|
||||
}
|
||||
|
||||
[Obsolete("Use Localization.Get instead")]
|
||||
public static string Localize(string key)
|
||||
{
|
||||
return Get(key);
|
||||
}
|
||||
|
||||
public static bool Exists(string key)
|
||||
{
|
||||
if (!localizationHasBeenSet)
|
||||
{
|
||||
language = PlayerPrefs.GetString("Language", "English");
|
||||
}
|
||||
if (!mDictionary.ContainsKey(key))
|
||||
{
|
||||
return mOldDictionary.ContainsKey(key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user