Skip to content

+EA 23.306 Nightly - Plugin.BaseCore โ€‹

May 14, 2026

7 files modified.

Important Changes โ€‹

None.

ExcelParser โ€‹

using System;

cs
using System;
using System.Collections.Generic; 
using System.Linq; 
using System.Text;
using NPOI.SS.UserModel;
using UnityEngine;

public class ExcelParser

cs

	public static IRow rowDefault;

	public static IRow rowHeader; 
	public static bool IsNull(ICell cell)
	{
		if (cell != null && cell.CellType != CellType.Blank)

public static int GetInt(int id)

cs
	}
	if (!int.TryParse(str, out var result))
	{
		if (float.TryParse(str, out var result2)) 
		{ 
			return (int)result2; 
		} 
		ReportIllFormat<int>(id);
	}
	return result;

public static int[] GetIntArray(int id)

cs
	{
		if (!int.TryParse(array[i], out array2[i]))
		{
			if (float.TryParse(array[i], out var result)) 
			{ 
				array2[i] = (int)result; 
				continue; 
			} 
			ReportIllFormat<int>(id);
			array2[i] = 0;
		}

public static void ReportIllFormat<T>(int id)

cs
	ICell cell = row?.Cells.TryGet(id, returnNull: true);
	IRow obj = row;
	string value = ((obj != null && obj.RowNum >= 3) ? $", default:'{rowDefault?.Cells.TryGet(id, returnNull: true)}'" : ", SourceData begins at the 4th row. 3rd row is the default value row.");
	stringBuilder.AppendLine("$source ill-format file: " + path); 
	stringBuilder.AppendLine("#source ill-format file: " + path); 
	object[] array = new object[5];
	IRow obj2 = row;
	array[0] = ((obj2 != null) ? new int?(obj2.RowNum + 1) : null);

public static void ReportIllFormat<T>(int id)

cs
		array[2] = ToLetterId(id);
		array[3] = name;
		array[4] = cell;
		stringBuilder.Append(string.Format("row#{0}, cell'{1}'/'{2}', expected:'{3}', read:'{4}'", array)); 
		stringBuilder.Append(string.Format("row#{0}, cell#{1}/#{2}, expected:'{3}', read:'{4}'", array)); 
		stringBuilder.AppendLine(value);
		Debug.LogError(stringBuilder); 
		Debug.LogWarning(stringBuilder); 
	} 
	public static string GetRowHeaderDiff(IReadOnlyDictionary<string, int> mapping, IReadOnlyDictionary<string, int> header) 
	{ 
		StringBuilder stringBuilder = new StringBuilder(); 
		List<KeyValuePair<string, int>> list = mapping.OrderBy((KeyValuePair<string, int> c) => c.Value).ToList(); 
		int num = list.Max((KeyValuePair<string, int> c) => c.Key.Length); 
		foreach (KeyValuePair<string, int> item in list) 
		{ 
			item.Deconstruct(out var key, out var value); 
			string text = key; 
			int index = value; 
			int value2; 
			bool num2 = header.TryGetValue(text, out value2); 
			string text2 = ((num2 && value2 != index) ? $"maybe {value2 + 1,2}/{ToLetterId(value2)} {text}" : ""); 
			if (!num2) 
			{ 
				text2 = "<missing>"; 
			} 
			string text3 = header.FirstOrDefault((KeyValuePair<string, int> c) => c.Value == index).Key ?? "<missing>"; 
			text3 = text3.PadRight(num + 3); 
			string text4 = text.PadRight(num); 
			stringBuilder.AppendLine($"{index + 1,2}/{ToLetterId(index),2}: {text4} -> {text3} {text2}"); 
		} 
		return stringBuilder.ToString(); 
	} 
	public static void ClearStaticRows() 
	{ 
		row = null; 
		rowDefault = null; 
		rowHeader = null; 
	}
}

LangGame โ€‹

using System;

cs
using System;
using System.Collections.Generic; 

public class LangGame : SourceLang<LangGame.Row>
{

public class Row : LangRow

cs
		public override string GetAlias => "n";
	}

	public static readonly IReadOnlyDictionary<string, int> RowMapping = new Dictionary<string, int> 
	{ 
		["id"] = 0, 
		["filter"] = 1, 
		["group"] = 2, 
		["color"] = 3, 
		["logColor"] = 4, 
		["sound"] = 5, 
		["effect"] = 6, 
		["text_JP"] = 7, 
		["text"] = 8
	}; 
	public override Row CreateRow()
	{
		return new Row

public override Row CreateRow()

cs
		};
	}

	public override Row CreateRowByMapping(IReadOnlyDictionary<string, int> mapping) 
	{ 
		return new Row
		{ 
			id = SourceData.GetString(mapping["id"]), 
			filter = SourceData.GetString(mapping["filter"]), 
			group = SourceData.GetString(mapping["group"]), 
			color = SourceData.GetString(mapping["color"]), 
			logColor = SourceData.GetString(mapping["logColor"]), 
			sound = SourceData.GetString(mapping["sound"]), 
			effect = SourceData.GetString(mapping["effect"]), 
			text_JP = SourceData.GetString(mapping["text_JP"]), 
			text = SourceData.GetString(mapping["text"]) 
		}; 
	} 
	public override void SetRow(Row r)
	{
		map[r.id] = r;
	}

	public override IReadOnlyDictionary<string, int> GetRowMapping() 
	{ 
		return RowMapping; 
	} 
	public static bool Has(string id)
	{
		return Lang.Game.map.ContainsKey(id);

LangGeneral โ€‹

using System;

cs
using System;
using System.Collections.Generic; 

public class LangGeneral : SourceLang<LangGeneral.Row>
{

public class Row : LangRow

cs
		public override string GetAlias => "n";
	}

	public static readonly IReadOnlyDictionary<string, int> RowMapping = new Dictionary<string, int> 
	{ 
		["id"] = 0, 
		["filter"] = 1, 
		["text_JP"] = 2, 
		["text"] = 3
	}; 
	public override Row CreateRow()
	{
		return new Row

public override Row CreateRow()

cs
		};
	}

	public override Row CreateRowByMapping(IReadOnlyDictionary<string, int> mapping) 
	{ 
		return new Row
		{ 
			id = SourceData.GetString(mapping["id"]), 
			filter = SourceData.GetString(mapping["filter"]), 
			text_JP = SourceData.GetString(mapping["text_JP"]), 
			text = SourceData.GetString(mapping["text"]) 
		}; 
	} 
	public override void SetRow(Row r)
	{
		map[r.id] = r;
	}
	public override IReadOnlyDictionary<string, int> GetRowMapping() 
	{ 
		return RowMapping; 
	} 
}

LangList โ€‹

using System;

cs
using System;
using System.Collections.Generic; 

public class LangList : SourceDataString<LangList.Row>
{

public class Row : BaseRow

cs
		public override string GetAlias => "n";
	}

	public static readonly IReadOnlyDictionary<string, int> RowMapping = new Dictionary<string, int> 
	{ 
		["id"] = 0, 
		["filter"] = 1, 
		["text_JP"] = 2, 
		["text"] = 3
	}; 
	public override bool AllowHotInitialization => true;

	public override Row CreateRow()

public override Row CreateRow()

cs
		};
	}

	public override Row CreateRowByMapping(IReadOnlyDictionary<string, int> mapping) 
	{ 
		return new Row
		{ 
			id = SourceData.GetString(mapping["id"]), 
			filter = SourceData.GetString(mapping["filter"]), 
			text_JP = SourceData.GetStringArray(mapping["text_JP"]), 
			text = SourceData.GetStringArray(mapping["text"]) 
		}; 
	} 
	public override void SetRow(Row r)
	{
		map[r.id] = r;
	}

	public override IReadOnlyDictionary<string, int> GetRowMapping() 
	{ 
		return RowMapping; 
	} 
	public override string[] GetList(string id)
	{
		Row row = map.TryGetValue(id);

LangNote โ€‹

using System;

cs
using System;
using System.Collections.Generic; 

public class LangNote : SourceDataString<LangNote.Row>
{

public class Row : BaseRow

cs
		public override string GetAlias => "n";
	}

	public static readonly IReadOnlyDictionary<string, int> RowMapping = new Dictionary<string, int> 
	{ 
		["id"] = 0, 
		["text_JP"] = 1, 
		["text"] = 2
	}; 
	public override bool AllowHotInitialization => true;

	public override Row CreateRow()

public override Row CreateRow()

cs
		};
	}

	public override Row CreateRowByMapping(IReadOnlyDictionary<string, int> mapping) 
	{ 
		return new Row
		{ 
			id = SourceData.GetString(mapping["id"]), 
			text_JP = SourceData.GetString(mapping["text_JP"]), 
			text = SourceData.GetString(mapping["text"]) 
		}; 
	} 
	public override void SetRow(Row r)
	{
		map[r.id] = r;
	}
	public override IReadOnlyDictionary<string, int> GetRowMapping() 
	{ 
		return RowMapping; 
	} 
}

LangWord โ€‹

using System;

cs
using System;
using System.Collections.Generic; 

public class LangWord : SourceDataInt<LangWord.Row>
{

public class Row : BaseRow

cs
		public override string GetAlias => "n";
	}

	public static readonly IReadOnlyDictionary<string, int> RowMapping = new Dictionary<string, int> 
	{ 
		["id"] = 0, 
		["group"] = 1, 
		["name_JP"] = 2, 
		["name"] = 3
	}; 
	public override bool AllowHotInitialization => true;

	public override Row CreateRow()

public override Row CreateRow()

cs
		};
	}

	public override Row CreateRowByMapping(IReadOnlyDictionary<string, int> mapping) 
	{ 
		return new Row
		{ 
			id = SourceData.GetInt(mapping["id"]), 
			group = SourceData.GetString(mapping["group"]), 
			name_JP = SourceData.GetString(mapping["name_JP"]), 
			name = SourceData.GetString(mapping["name"]) 
		}; 
	} 
	public override void SetRow(Row r)
	{
		map[r.id] = r;
	}

	public override IReadOnlyDictionary<string, int> GetRowMapping() 
	{ 
		return RowMapping; 
	} 
	public override void OnAfterImportData()
	{
		int num = 0;

SourceData โ€‹

using System;

cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq; 
using System.Reflection;
using NPOI.SS.UserModel;
using NPOI.SS.Util;

public override bool ImportData(ISheet sheet, string bookname, bool overwrite =

cs
	isNew = true;
	nameSheet = sheet.SheetName;
	nameBook = bookname;
	SourceData.rowHeader = sheet.GetRow(0); 
	SourceData.rowDefault = sheet.GetRow(2);
	IReadOnlyDictionary<string, int> rowMapping = GetRowMapping(); 
	Dictionary<string, int> dictionary = null; 
	if (rowMapping != null) 
	{ 
		dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); 
		foreach (ICell item in SourceData.rowHeader.Cells.Where((ICell c) => c.ToString() != "0" && !c.ToString().IsEmpty())) 
		{ 
			dictionary[item.ToString().Trim()] = item.ColumnIndex; 
		} 
		if (!rowMapping.Keys.All(dictionary.ContainsKey) || rowMapping.Count > dictionary.Count) 
		{ 
			string[] array = rowMapping.Keys.Except(dictionary.Keys).ToArray(); 
			if (array.Length != 0) 
			{ 
				Debug.LogWarning("#source ill-format file with missing columns, init with empty values\n" + ExcelParser.GetRowHeaderDiff(rowMapping, dictionary)); 
				string[] array2 = array; 
				foreach (string text in array2) 
				{ 
					SourceData.rowHeader.CreateCell(276, CellType.String).SetCellValue(text); 
					dictionary[text] = 276; 
				} 
			} 
			else
			{ 
				Debug.Log("#source ill-format file with reordered columns"); 
			} 
		} 
		else
		{ 
			dictionary = null; 
		} 
	} 
	int num = 0;
	for (int i = 3; i <= sheet.LastRowNum; i++) 
	for (int j = 3; j <= sheet.LastRowNum; j++) 
	{
		SourceData.row = sheet.GetRow(i); 
		if (SourceData.row == null || SourceData.row.GetCell(0) == null || SourceData.row.GetCell(0).ToString().IsEmpty()) 
		SourceData.row = sheet.GetRow(j); 
		if (string.IsNullOrEmpty(SourceData.row?.GetCell(0)?.ToString())) 
		{
			break;
		}
		T val = CreateRow(); 
		T val = ((dictionary != null) ? CreateRowByMapping(dictionary) : CreateRow()); 
		val.OnImportData(this);
		rows.Add(val);
		num++;
	}
	string text = sheet.SheetName + "/" + sheet.LastRowNum + "/" + num; 
	Debug.Log(text); 
	ERROR.msg = text; 
	string text2 = sheet.SheetName + "/" + sheet.LastRowNum + "/" + num; 
	Debug.Log(text2); 
	ERROR.msg = text2; 
	OnAfterImportData();
	initialized = false;
	return true;

public virtual T CreateRow()

cs
		return null;
	}

	public virtual T CreateRowByMapping(IReadOnlyDictionary<string, int> mapping) 
	{ 
		return null; 
	} 
	public override int ImportRows(IEnumerable<BaseRow> sourceRows)
	{
		int num = 0;

public static IRow rowDefault

cs
		}
	}

	public static IRow rowHeader 
	{ 
		get 
		{ 
			return ExcelParser.rowHeader; 
		} 
		set 
		{ 
			ExcelParser.rowHeader = value; 
		} 
	} 
	public void BuildFlags(string rawText, Dictionary<string, bool> map)
	{
		if (!string.IsNullOrEmpty(rawText))

public virtual void ValidateLang()

cs
	{
	}

	public virtual IReadOnlyDictionary<string, int> GetRowMapping() 
	{ 
		return null; 
	} 
	public static bool IsNull(ICell cell)
	{
		if (cell != null && cell.CellType != CellType.Blank)