EA 23.283 Nightly
March 4, 2026
36 files modified. 3 new files created.
Important Changes
Possible breaking changes. Click the filename to view the chunk.
Map (1)
public void SetBridge(int x, int z, int height = 0, int idMat = 0, int idBridge = 0, int dir = 0)
public void SetBridge(int x, int z, int height = 0, int idMat = 0, int idBridge = 0, int dir = 0, byte idPillar = 0) ModManager (9)
private void HandleResults(UgcQuery query)
public void LoadLoadOrder() public IEnumerator RefreshMods(Action onComplete, bool syncMods)
public void ImportSourceLocalizations(string lang) public void SaveLoadOrder()
public void ImportModDialogs() public void LoadLoadOrder()
public IEnumerator RefreshMods(Action onComplete, bool syncMods) public override void ParseExtra(DirectoryInfo dir, BaseModPackage package)
public void LoadCustomPackage() public void UpdateDialogs(DirectoryInfo dir, string dirTemp) public void UpdateTalks(DirectoryInfo dir, string dirTemp) public void UpdateExcelBook(FileInfo f, string dirTemp, bool updateOnlyText)
public void InitPackagesMeta() public int UpdateExcelSheet(ISheet destSheet, ISheet oldSheet, bool updateOnlytext)
public void ActivatePackages() ModUtil (1)
public static void Test() Party (1)
public void ModExpPartySkill(int ele, int a)
public void ModExp(int ele, int a) AI_PlayMusic
public override IEnumerable<Status> Run()
idSong = "violin_furusato";
break;
default:
idSong = "violin_chaconne";
idSong = ((EClass.Sound.GetData("Instrument/" + tool.id) is BGMData) ? tool.id : "violin_chaconne");
break;
}
if (owner.IsPC && EClass.player.knownSongs.ContainsKey(idSong))public override IEnumerable<Status> Run()
EClass.player.playingSong = playing;
}
}
if (owner.IsPC)
if (owner.IsPC && EClass.Sound.GetData("Instrument/" + idSong) is BGMData bGMData)
{
(EClass.Sound.GetData("Instrument/" + idSong) as BGMData).song.index = playing.index;
bGMData.song.index = playing.index;
}
if (Application.isEditor && owner.IsPC)
{AM_Adv
public override void _OnUpdateInput()
}
switch (EInput.action)
{
case EAction.Console:
EClass.ui.AddLayer<LayerConsole>();
break;
case EAction.Chat:
Dialog.InputName("", "", delegate(bool cancel, string text)
{
if (!cancel && !text.IsEmpty())
{
Chara chara = EClass.pc;
if ((text[0] == '@' || text[0] == '@') && text.Length > 1 && int.TryParse(text[1].ToString().Normalize(NormalizationForm.FormKC), out var result))
{
text = text.Substring(2);
chara = EClass.pc.party.members.TryGet(result);
}
if (text.StartsWith('@'))
{
text = text.Substring(1);
}
chara.SayRaw(text);
Msg.SetColor("ono");
string text2 = text;
if (!text.StartsWith('*') && !text.StartsWith('(') && !text.StartsWith('('))
string[] array = text.SplitByNewline();
foreach (string obj in array)
{
text = text.Bracket();
}
Msg.Say(text, chara);
if (text2 == "nyan")
{
Msg.SetColor("save");
Msg.Say("*" + EClass.player.stats.lastChuryu + " nyan*");
Chara chara = EClass.pc;
string text2 = obj;
if ((text2[0] == '@' || text2[0] == '@') && text2.Length > 1 && int.TryParse(text2[1].ToString().Normalize(NormalizationForm.FormKC), out var result))
{
text2 = text2.Substring(2);
chara = EClass.pc.party.members.TryGet(result);
}
if (text2.StartsWith('@'))
{
text2 = text2.Substring(1);
}
chara.SayRaw(text2);
string text3 = text2;
Msg.SetColor("ono");
if (!text2.StartsWith('*') && !text2.StartsWith('(') && !text2.StartsWith('('))
{
text2 = text2.Bracket();
}
Msg.Say(text2.RemoveAllTags(), chara);
OnEnterChat(text3);
}
}
}, Dialog.InputType.None);
}, Dialog.InputType.Chat);
break;
case EAction.Search:
EClass.ui.widgets.Toggle("Search")?.SoundActivate();public override void _OnUpdateInput()
}
}
public virtual void OnEnterChat(string text)
{
if (text == "nyan")
{
Msg.SetColor("save");
Msg.Say("*" + EClass.player.stats.lastChuryu + " nyan*");
}
}
public void ShowAllAction()
{
planAll.Update(mouseTarget);Card
public void ModExp(int ele, int a)
}
}
public void ModExpParty(int ele, int a)
{
if (isChara)
{
if (Chara.party == null)
{
elements.ModExp(ele, a);
}
else
{
Chara.party.ModExp(ele, a);
}
}
}
public bool IsChildOf(Card c)
{
return GetRootCard() == c;private void _OnDeserialized(StreamingContext context)
{
isDestroyed = true;
}
if (version >= 5)
{
return;
}
if (version < 3 && isChara && HasElement(1210))
{
elements.ModBase(960, -5 * Evalue(1210));
}
if (version < 4 && isChara && HasElement(1210))
{
elements.ModBase(423, Evalue(1210));
}
if (version < 5)
{
if (isChara && Chara.race.id == "horse" && Chara.body.GetSlot(30, onlyEmpty: false) == null)
if (version < 3 && isChara && HasElement(1210))
{
Chara.body.AddBodyPart(30);
Chara.body.RefreshBodyParts();
elements.ModBase(960, -5 * Evalue(1210));
}
if (isChara && Chara.race.id == "bike" && id != "bike_cub")
if (version < 4 && isChara && HasElement(1210))
{
Rand.SetSeed(uid);
Chara.body.AddBodyPart(33);
Chara.SetFeat(1423, 1 + EClass.rnd(10));
Rand.SetSeed();
elements.ModBase(423, Evalue(1210));
}
if (version < 5)
{
if (isChara && Chara.race.id == "horse" && Chara.body.GetSlot(30, onlyEmpty: false) == null)
{
Chara.body.AddBodyPart(30);
Chara.body.RefreshBodyParts();
}
if (isChara && Chara.race.id == "bike" && id != "bike_cub")
{
Rand.SetSeed(uid);
Chara.body.AddBodyPart(33);
Chara.SetFeat(1423, 1 + EClass.rnd(10));
Rand.SetSeed();
}
}
version = 5;
}
version = 5;
BaseModManager.PublishEvent(isChara ? "elin.chara_created" : "elin.thing_created", this);
}
protected virtual void OnDeserialized()public void Create(string _id, int _idMat = -1, int genLv = -1)
SetHidden();
}
isFloating = Pref.Float;
BaseModManager.PublishEvent(isChara ? "elin.chara_created" : "elin.thing_created", this);
}
public virtual void OnBeforeCreate()CardRenderer
public override void Draw(RenderParam p, ref Vector3 v, bool drawShadow)
SourceChara.Row row = EClass.sources.charas.map.TryGetValue(owner.c_idRefCard) ?? EClass.sources.charas.map["putty"];
renderData = row.renderData;
pref = row.pref;
int matColor = traitFigure.GetMatColor();
drawShadow = traitFigure.ShowShadow;
if (row._tiles.Length == 0 || data.pass == null)
{
renderData = owner.sourceCard.renderData;
pref = owner.sourceCard.pref;
}
else
{
if (EClass.core.config.game.antiSpider && row.skinAntiSpider != 0)
if (traitFigure.extraRenderer == null)
{
traitFigure.extraRenderer = new CharaRenderer();
traitFigure.extraRenderer.SetOwner(CharaGen.Create(row.id));
}
if (matColor >= -3)
{
owner.refVal = row.skinAntiSpider;
if (matColor == -3)
{
MatColors matColors = EClass.core.Colors.matColors["ether"];
p.matColor = BaseTileMap.GetColorInt(ref matColors.main, 100) * -1;
}
}
p.tile = row._tiles[owner.refVal % row._tiles.Length] * ((owner.dir % 2 == 0) ? 1 : (-1));
p.matColor = traitFigure.GetMatColor();
drawShadow = traitFigure.ShowShadow;
pref = row.pref;
else
{
p.matColor = matColor;
}
traitFigure.extraRenderer.Draw(p, ref v, drawShadow);
return;
}
if (EClass.core.config.game.antiSpider && row.skinAntiSpider != 0)
{
owner.refVal = row.skinAntiSpider;
}
p.tile = row._tiles[owner.refVal % row._tiles.Length] * ((owner.dir % 2 == 0) ? 1 : (-1));
p.matColor = matColor;
pref = row.pref;
p.x += pref.x * (float)((owner.dir % 2 == 0) ? 1 : (-1));
p.y += pref.y;
p.z += pref.z;Chara
{
flag = false;
}
if (flag && File.Exists(CorePath.DramaData + id + ".xlsx"))
if (flag && File.Exists(PackageIterator.GetFiles("Dialog/Drama/" + id + ".xlsx").LastOrDefault()?.FullName ?? (CorePath.DramaData + id + ".xlsx")))
{
ShowDialog(id);
} if (base.c_love != null)
{
base.c_love.dateMarriage = 0;
base.c_love.dateWedding = 0;
SetFeat(1275, 0);
EClass.player.stats.divorced++;
}ContentConfigInput
public override void OnInstantiate()
uIList.Add(keys.mute);
uIList.Add(keys.meditate);
uIList.Add(keys.chat);
uIList.Add(keys.console);
}
};
_refreshList();Core
public void SetLang(string langCode, bool force = false)
game.Kill();
}
config.OnSetLang();
BaseModManager.PublishEvent("elin.source.lang_set", langCode);
}
}public static int GetElement(string id)
{
sourceElement.Init();
}
if (!sourceElement.alias.TryGetValue(id ?? "_void", out var value))
if (!sourceElement.alias.TryGetValue(id ?? (id = "_void"), out var value))
{
Debug.LogError("exception:" + id);
value = sourceElement.rows[0];
if (sourceElement.fuzzyAlias.TryGetValue(id, out var value2))
{
Debug.Log("#element lookup: " + id + " -> " + value2);
value = sourceElement.alias[value2];
}
else
{
Debug.LogError("#element not found: " + id);
value = sourceElement.rows[0];
}
}
return value.id;
}CoreDebug
}
if (Input.GetKeyDown(KeyCode.F3))
{
for (int i = 0; i < 10; i++)
Thing thing = EClass._map.things.First((Thing _t) => _t.id == "cloud");
if (thing != null)
{
Thing thing = ThingGen.Create("egg_fertilized");
thing.TryMakeRandomItem(40);
thing.SetEncLv(200);
EClass.pc.Pick(thing);
Debug.Log(EClass.sources.cards.map["cloud"].pref == thing.Pref);
Debug.Log(EClass.sources.cards.map["cloud"].pref == thing.renderer.GetPref());
}
foreach (Chara deadChara in EClass._map.deadCharas)
{
Debug.Log(deadChara);
}
EClass.core.steam.CheckUpdate();
EClass.player.flags.loytelMartLv++;
Msg.Say("loytelmart:" + EClass.player.flags.loytelMartLv);
Guild.Fighter.relation.rank = 20;
Guild.Mage.relation.rank = 20;
Guild.Thief.relation.rank = 20;
Guild.Merchant.relation.rank = 20;
if (EClass.Branch != null)
{
EClass.Branch.ModExp(EClass.Branch.GetNextExp());
}
foreach (Chara item in EClass._map.charas.ToList())
{
item.AddExp(item.ExpToNext);
item.Vomit();
}
EClass.pc.PlayEffect("boost");
EClass.pc.PlaySound("boost");
EClass.pc.elements.SetBase(306, 100);
EClass.pc.elements.SetBase(85, 100);
EClass.pc.feat += 10;
EClass.player.totalFeat += 10;
return;
}
if (Input.GetKeyDown(KeyCode.F4)) if (Input.GetKey(KeyCode.F9))
{
EClass.scene.paused = false;
for (int j = 0; j < advanceMin; j++)
for (int i = 0; i < advanceMin; i++)
{
EClass.game.updater.FixedUpdate();
} {
if (Input.GetMouseButtonDown(0))
{
foreach (Card item2 in list)
foreach (Card item in list)
{
Debug.Log(item2.Name + "/" + item2.dir + "/" + item2.flipX + "/" + item2.angle);
Debug.Log(item.Name + "/" + item.dir + "/" + item.flipX + "/" + item.angle);
}
}
if (Input.GetMouseButtonDown(1)) }
if (key)
{
foreach (Card item3 in EClass._map.Roaming.all)
foreach (Card item2 in EClass._map.Roaming.all)
{
EClass._zone.RemoveCard(item3);
EClass._zone.RemoveCard(item2);
}
}
else if (hitPoint.detail != null) {
break;
}
foreach (Card item4 in hitPoint.ListCards())
foreach (Card item3 in hitPoint.ListCards())
{
item4.renderer.PlayAnime(num5.ToEnum<AnimeID>());
item3.renderer.PlayAnime(num5.ToEnum<AnimeID>());
}
Debug.Log(num5.ToEnum<AnimeID>());
break;public static string Spawn(string id, int num = 1, string aliasMat = "", int obj
EClass._zone.AddCard(thing, EClass.pc.pos);
return "Spawned " + thing.Name;
}
_ = EClass.sources.charas.map;
if (EClass.sources.charas.map.ContainsKey(id))
{
Chara chara = CharaGen.Create(id);public static string Spawn(string id, int num = 1, string aliasMat = "", int obj
return "'" + id + "' does not exist in the database.";
}
[ConsoleCommand("")]
public static string SpawnFigure(string id)
{
if (!CheatEnabled())
{
return EnableCheat;
}
if (!EClass.sources.charas.map.ContainsKey(id))
{
return "'" + id + "' does not exist in the database.";
}
Thing thing = ThingGen.Create("figure");
Thing thing2 = ThingGen.Create("figure3");
string c_idRefCard = (thing2.c_idRefCard = id);
thing.c_idRefCard = c_idRefCard;
EClass.pc.DropThing(thing);
EClass.pc.DropThing(thing2);
return "Spawned figures for '" + id + "'";
}
[ConsoleCommand("")]
public static string TestSpawn(int lv, int num, int lvRange = -1)
{public static string FlyMode()
[ConsoleCommand("")]
public static string ChangeRace(string id = "?")
{
if (!CheatEnabled())
{
return EnableCheat;
}
if (EClass.sources.races.map.ContainsKey(id))
{
Thing thing = null;public static string ResetAchievement(ID_Achievement id)
[ConsoleCommand("")]
public static string ChangeJob(string id = "?")
{
if (!CheatEnabled())
{
return EnableCheat;
}
if (EClass.sources.jobs.map.ContainsKey(id))
{
EClass.pc.ChangeJob(id);Dialog
Default,
Password,
Item,
DistributionFilter
DistributionFilter,
Chat
}
public Text textConfetti; }
}
public override bool OnBack()
{
if (keymap != null && (!EInput.rightMouse.pressing || EInput.rightMouse.usedKey))
{
return false;
}
return base.OnBack();
}
public override void OnUpdateInput()
{
if ((bool)input && option.canClose && (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter)) && keymap == null)public static Dialog InputName(string langDetail, string text, Action<bool, stri
d.note.AddText(langDetail.lang()).text1.alignment = TextAnchor.MiddleCenter;
switch (inputType)
{
case InputType.Chat:
d.input.field.characterLimit = 500;
break;
case InputType.DistributionFilter:
d.input.field.characterLimit = 100;
break;DramaCustomSequence
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;public string GetRumor(Chara c)
public bool HasTopic(string idSheet, string idTopic)
{
string path = CorePath.CorePackage.TextDialog + "dialog.xlsx";
if (!File.Exists(path))
{
return false;
}
ExcelData excelData = new ExcelData();
excelData.path = path;
excelData.BuildMap(idSheet);
return excelData.sheets[idSheet].map.ContainsKey(idTopic);
return Lang.GetDialogSheet(idSheet).map.ContainsKey(idTopic);
}
public string GetText(Chara c, string idSheet, string idTopic)DramaManager
public class DramaManager : EMono
private string lastIF2;
private SoundSource lastSound;
public DramaEventTalk lastTalk;
public bool enableTone; sequence.AddActor("tg", tg);
}
sequence.AddActor("pc", new Person(EMono.pc));
string text = CorePath.DramaData + setup.book + ".xlsx";
string text = PackageIterator.GetFiles("Dialog/Drama/" + setup.book + ".xlsx").LastOrDefault()?.FullName ?? (CorePath.DramaData + setup.book + ".xlsx");
ExcelData excelData = dictCache.TryGetValue(text);
if (excelData != null && excelData.IsModified())
{ foreach (Dictionary<string, string> item in new ExcelData
{
maxEmptyRows = 10,
path = CorePath.DramaDataLocal + setup.book + ".xlsx"
path = (PackageIterator.GetFiles("Dialog/Drama/" + setup.book + ".xlsx").LastOrDefault()?.FullName ?? (CorePath.DramaDataLocal + setup.book + ".xlsx"))
}.BuildList(setup.sheet))
{
string text2 = item["id"];
if (!text2.IsEmpty() && !item["text"].IsEmpty())
if (!text2.IsEmpty())
{
dictLocalize.Add(text2, item["text"]);
string text3 = item.TryGetValue("text_" + Lang.langCode) ?? item["text"];
if (!dictLocalize.TryAdd(text2, text3))
{
string text4 = dictLocalize[text2];
dictLocalize[text2] = ("[DUPLICATE ID '" + text2 + "']\n").TagColor(Color.red) + text4;
Debug.LogError("#drama duplicate id '" + text2 + "' at " + text + "\n" + text4 + " -> " + text3);
}
}
}
}public void ParseLine(Dictionary<string, string> item)
{
SoundManager.current.MuteBGMFor(float.Parse(p3, CultureInfo.InvariantCulture));
}
EMono.Sound.Play(p2);
lastSound?.Stop();
lastSound = EMono.Sound.Play(p2);
});
break;
case "haltPlaylist":public void ParseLine(Dictionary<string, string> item)
});
break;
default:
{
EVENT.ElinDramaParseActionEventArgs elinDramaParseActionEventArgs = new EVENT.ElinDramaParseActionEventArgs
{
dm = this,
line = item
};
elinDramaParseActionEventArgs.SetData(action);
BaseModManager.PublishEvent("elin.drama.parse_action", elinDramaParseActionEventArgs);
if (elinDramaParseActionEventArgs.IsUsed)
{
return;
}
if (!flag)
{
break;public void ParseLine(Dictionary<string, string> item)
})) as DramaEventTalk;
lastTalk.center = p2 == "center";
break;
}
case "new":
case "saveBGM":
case "checkAffinity":+EVENT
File Created
using System.Collections.Generic;
public static class EVENT
{
public class ElinEventArgs<T>
{
public bool IsUsed { get; private set; }
public T data { get; private set; }
public virtual void SetData(T newData)
{
data = newData;
}
public virtual void Use()
{
IsUsed = true;
}
}
public class ElinFeatApplyEventArgs : ElinEventArgs<int>
{
public Feat feat;
public ElementContainer owner;
public bool hint;
}
public class ElinDramaParseActionEventArgs : ElinEventArgs<string>
{
public DramaManager dm;
public Dictionary<string, string> line;
}
public const string Undefined = "undefined";
public const string ModsActivated = "elin.mods.activated";
public const string SourceImporting = "elin.source.importing";
public const string SourceImported = "elin.source.imported";
public const string SourceLangSet = "elin.source.lang_set";
public const string PreSave = "elin.game.pre_save";
public const string PostSave = "elin.game.post_save";
public const string PreLoad = "elin.game.pre_load";
public const string PostLoad = "elin.game.post_load";
public const string NewGame = "elin.game.start_new";
public const string PreSceneInit = "elin.scene.pre_init";
public const string PostSceneInit = "elin.scene.post_init";
public const string FeatApply = "elin.feat.apply";
public const string DramaParseAction = "elin.drama.parse_action";
public const string CharaCreated = "elin.chara_created";
public const string ThingCreated = "elin.thing_created";
}FEAT
public List<string> Apply(int a, ElementContainer owner, bool hint = false)
{
hints.Clear();
}
EVENT.ElinFeatApplyEventArgs elinFeatApplyEventArgs = new EVENT.ElinFeatApplyEventArgs
{
feat = this,
owner = owner,
hint = hint
};
elinFeatApplyEventArgs.SetData(a);
BaseModManager.PublishEvent("elin.feat.apply", elinFeatApplyEventArgs);
a = elinFeatApplyEventArgs.data;
int value = base.Value;
int A = Mathf.Abs(a);
int invert = ((a >= 0) ? 1 : (-1));Game
public static void Load(string id, bool cloud)
EClass.game.Kill();
}
OnBeforeInstantiate();
GameIOContext data = new GameIOContext(text);
BaseModManager.PublishEvent("elin.game.pre_load", data);
EClass.core.game = GameIO.LoadGame(id, text, cloud);
EClass.game.isCloud = cloud;
EClass.game.isLoading = true;public static void Load(string id, bool cloud)
WidgetSideScreen.Instance.OnChangeResolution();
}
EClass.game.isLoading = false;
BaseModManager.PublishEvent("elin.game.post_load", data);
}
public void OnLoad() AddAdventurers();
player.OnStartNewGame();
EClass.scene.Init(Scene.Mode.StartGame);
GameIOContext data = new GameIOContext((isCloud ? CorePath.RootSaveCloud : CorePath.RootSave) + id);
BaseModManager.PublishEvent("elin.game.start_new", data);
}
public void AddAdventurers()public bool Save(bool isAutoSave = false, bool silent = false)
GameIndex gameIndex = null;
try
{
GameIOContext data = new GameIOContext(GameIO.pathCurrentSave);
BaseModManager.PublishEvent("elin.game.pre_save", data);
OnBeforeSave();
gameIndex = GameIO.SaveGame();
BaseModManager.PublishEvent("elin.game.post_save", data);
}
catch (Exception ex)
{GrowSystem
public void PopHarvest(Chara c, Thing t = null, int num = -1)
}
ApplySeed(t);
PlantData plantData = EClass._map.TryGetPlant(cell);
bool flag = false;
if (plantData != null && plantData.size > 0)
{
t.c_weight = t.SelfWeight * (80 + plantData.size * plantData.size * 100) / 100;
t.SetBool(115, enable: true);
t.isWeightChanged = true;
flag = true;
}
t.SetBlessedState(BlessedState.Normal);
if (source._growth.Length > 4)public void PopHarvest(Chara c, Thing t = null, int num = -1)
t.SetNum(num);
}
TryPick(cell, t, c);
if (flag)
{
c.ModExpParty(207, Mathf.Min(t.c_weight / 100, 500));
}
}
public void ApplySeed(Thing t)Hobby
{
public int id;
public SourceHobby.Row source => EClass.sources.hobbies.map[id];
public SourceHobby.Row source => EClass.sources.hobbies.map.TryGetValue(id) ?? EClass.sources.hobbies.alias["Walk"];
public string Name => source.GetName();ID_Achievement
LARNNEIRE2,
CHURYU2,
NINO,
CHURYU3
CHURYU3,
DEMITAS,
KETTLE
}LayerConsole
public override void OnAfterInit()
public override void OnUpdateInput()
{
if (Input.GetKeyDown(KeyCode.Escape))
if (Input.GetKeyDown(KeyCode.Escape) || EInput.action == EAction.Console)
{
Close();
}Map
public void SetFloor(int x, int z, int idMat, int idFloor, int dir)
RefreshNeighborTiles(x, z);
}
public void SetBridge(int x, int z, int height = 0, int idMat = 0, int idBridge = 0, int dir = 0)
public void SetBridge(int x, int z, int height = 0, int idMat = 0, int idBridge = 0, int dir = 0, byte idPillar = 0)
{
Cell cell = cells[x, z];
cell.bridgeHeight = (byte)height;
cell._bridgeMat = (byte)idMat;
cell._bridge = (byte)idBridge;
cell.bridgePillar = 0;
cell.bridgePillar = idPillar;
cell.floorDir = dir;
if (cell.room != null)
{public void MineFloor(Point point, Chara c = null, bool recoverBlock = false, bo
if (point.cell.HasBridge && removePlatform)
{
DropBlockComponent(EClass.pc.pos, point.sourceBridge, point.matBridge, recoverBlock, isPlatform: true, c);
EClass._map.SetBridge(point.x, point.z);
EClass._map.SetBridge(point.x, point.z, 0, 0, 0, 0, 0);
if (point.IsSky)
{
EClass.pc.Kick(point, ignoreSelf: true);ModManager
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using HeathenEngineering.SteamworksIntegration;
using HeathenEngineering.SteamworksIntegration.API;
using IniParser.Model;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Newtonsoft.Json;
using Steamworks;
using UnityEngine;
[Serializable]
public class ModManager : BaseModManager
public class ModManager : ModManagerCore
{
public struct SheetIndex
{
public int dest;
public int old;
}
public static List<object> ListPluginObject = new List<object>();
public static bool disableMod = false;
public static bool disableMod;
private LoadingScreen _loading;
public List<FileInfo> replaceFiles = new List<FileInfo>();
private Action ImportModGodTalks;
public static List<string> ListChainLoad => BaseModManager.listChainLoad;
public static DirectoryInfo DirWorkshop => BaseModManager.Instance.dirWorkshop;
public static DirectoryInfo DirWorkshop => Instance.dirWorkshop;
public new static ModManager Instance => (ModManager)BaseModManager.Instance;
public static bool IsInitialized => BaseModManager.isInitialized;
public override void Init(string path, string defaultPackage = "_Elona")
{
base.Init(path, defaultPackage);
IniData elinIni = Core.GetElinIni();
Debug.Log("IsOffline:" + BaseCore.IsOffline);
IniData elinIni = Core.GetElinIni();
if (elinIni != null)
{
if (BaseCore.IsOffline)public override void Init(string path, string defaultPackage = "_Elona")
}
else
{
DirectoryInfo parent = new DirectoryInfo(App.Client.GetAppInstallDirectory(SteamSettings.behaviour.settings.applicationId)).Parent.Parent;
dirWorkshop = new DirectoryInfo(parent.FullName + "/workshop/content/2135150");
elinIni.Global["path_workshop"] = dirWorkshop.FullName ?? "";
string path2 = Path.Combine(App.Client.GetAppInstallDirectory(SteamSettings.behaviour.settings.applicationId), "../../workshop/content/2135150");
dirWorkshop = new DirectoryInfo(path2);
elinIni.Global["path_workshop"] = dirWorkshop.FullName;
Core.SaveElinIni(elinIni);
}
}
if (dirWorkshop != null && !dirWorkshop.Exists)
if (!dirWorkshop.Exists)
{
dirWorkshop = null;
}
Debug.Log("dirWorkshop:" + dirWorkshop);
Debug.Log("Mod Init:" + BaseModManager.rootDefaultPacakge);
packages.Clear();
DirectoryInfo[] directories = new DirectoryInfo(BaseModManager.rootMod).GetDirectories();
Array.Reverse(directories);
DirectoryInfo[] array = directories;
foreach (DirectoryInfo directoryInfo in array)
Debug.Log("Workshop:" + dirWorkshop);
Debug.Log("Packages:" + BaseModManager.rootMod);
Debug.Log("Core Mod:" + BaseModManager.rootDefaultPacakge);
BaseModManager.SubscribeEvent("elin.source.lang_set", delegate(object lang)
{
if (!EClass.debug.skipMod || !Application.isEditor || !(directoryInfo.Name != "_Elona"))
if (ModManagerCore.useLocalizations)
{
AddPackage(directoryInfo, isInPackages: true);
ImportSourceLocalizations(lang as string);
}
}
DirectoryInfo[] directories2 = new DirectoryInfo(CorePath.custom).GetDirectories();
ModPackage package = new ModPackage();
array = directories2;
foreach (DirectoryInfo dir in array)
ImportModDialogs();
});
}
public void SaveLoadOrder()
{
if (!disableMod)
{
ParseExtra(dir, package);
List<string> contents = (from p in packages
where !p.builtin && p.dirInfo.Exists
select $"{p.dirInfo.FullName},{(p.willActivate ? 1 : 0)}").ToList();
File.WriteAllLines(CorePath.rootExe + "loadorder.txt", contents);
}
}
private void HandleResults(UgcQuery query)
public void LoadLoadOrder()
{
foreach (WorkshopItem results in query.ResultsList)
string path = CorePath.rootExe + "loadorder.txt";
if (!File.Exists(path))
{
return;
}
Dictionary<string, BaseModPackage> dictionary = new Dictionary<string, BaseModPackage>();
foreach (BaseModPackage package in packages)
{
if (results.IsSubscribed)
if (!package.builtin)
{
AddWorkshopPackage(results);
dictionary[package.dirInfo.FullName] = package;
}
}
int num = 0;
string[] array = File.ReadAllLines(path);
for (int i = 0; i < array.Length; i++)
{
string[] array2 = array[i].Split(',');
if (dictionary.TryGetValue(array2[0], out var value))
{
value.loadPriority = num;
value.willActivate = array2[1] == "1";
}
num++;
}
}
public IEnumerator RefreshMods(Action onComplete, bool syncMods)
public void ImportSourceLocalizations(string lang)
{
bool sync = !BaseCore.IsOffline && syncMods && UserGeneratedContent.Client.GetNumSubscribedItems() != 0;
LoadingScreen loading = (sync ? Util.Instantiate<LoadingScreen>("LoadingScreen") : null);
if (!disableMod && (!EClass.debug.skipMod || !Application.isEditor))
string text = lang + "/SourceLocalization.json";
(FileInfo file, EMod package)[] filesEx = PackageIterator.GetFilesEx(text);
SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>();
Dictionary<string, SortedDictionary<string, string>> dictionary = new Dictionary<string, SortedDictionary<string, string>>();
(FileInfo, EMod)[] array = filesEx;
string key;
string value;
for (int i = 0; i < array.Length; i++)
{
if (sync)
var (fileInfo, eMod) = array[i];
try
{
UgcQuery activeQuery = UgcQuery.GetSubscribed(withLongDescription: false, withMetadata: false, withKeyValueTags: false, withAdditionalPreviews: false, 0u);
activeQuery.Execute(HandleResults);
loading?.Log("Fetching subscribed Mods...(Hit ESC to cancel)");
while (activeQuery.handle != UGCQueryHandle_t.Invalid && !UnityEngine.Input.GetKey(KeyCode.Escape))
SortedDictionary<string, string> sortedDictionary2 = IO.LoadFile<SortedDictionary<string, string>>(fileInfo.FullName);
foreach (KeyValuePair<string, string> item in sortedDictionary2)
{
yield return new WaitForEndOfFrame();
item.Deconstruct(out key, out value);
string key2 = key;
string value2 = value;
sortedDictionary[key2] = value2;
}
dictionary[eMod.id] = sortedDictionary2;
}
else
catch (Exception arg)
{
loading?.Log("Fetching offline Mods.");
if (dirWorkshop != null)
{
DirectoryInfo[] directories = dirWorkshop.GetDirectories();
foreach (DirectoryInfo dir in directories)
{
AddPackage(dir);
}
}
Debug.LogError($"#source localization failed to load {fileInfo.ShortPath()}\n{arg}");
}
}
if (sync)
JsonSerializerSettings setting = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.None,
NullValueHandling = NullValueHandling.Ignore
};
foreach (EMod value4 in base.MappedPackages.Values)
{
bool valid = false;
while (!valid)
if (!(value4 is ModPackage modPackage) || value4.builtin || !value4.activated)
{
valid = true;
foreach (BaseModPackage package in packages)
{
WorkshopItem workshopItem = package.item as WorkshopItem;
if (!package.installed && workshopItem != null && !workshopItem.IsBanned)
{
valid = false;
string text = "Downloading " + workshopItem.Title + ": ";
if (!package.progressText)
{
package.progressText = loading.Log(text);
}
if (package.downloadStarted && workshopItem.DownloadCompletion >= 1f)
{
package.progressText.text = text + "Done!";
package.installed = true;
}
else if (workshopItem.IsDownloading || workshopItem.IsDownloadPending)
{
package.progressText.text = text + (int)(workshopItem.DownloadCompletion * 100f) + "%";
}
else if (!package.downloadStarted)
{
package.downloadStarted = true;
workshopItem.DownloadItem(highPriority: true);
Debug.Log("start downloading:" + workshopItem.Title + "/" + workshopItem.IsInstalled + "/" + package.installed + "/" + workshopItem.IsDownloading + "/" + workshopItem.IsDownloadPending + "/" + workshopItem.DownloadCompletion);
}
}
}
if (!valid && UnityEngine.Input.GetKey(KeyCode.Escape))
{
break;
}
yield return new WaitForEndOfFrame();
continue;
}
}
foreach (BaseModPackage package2 in packages)
{
package2.Init();
Debug.Log(package2.title + "/" + package2.id + "/" + package2.installed + "/" + package2.dirInfo.FullName);
}
LoadLoadOrder();
packages.Sort((BaseModPackage a, BaseModPackage b) => a.loadPriority - b.loadPriority);
foreach (BaseModPackage package3 in packages)
{
if (package3.isInPackages || !package3.willActivate)
HashSet<SourceData.BaseRow> sourceRows = value4.sourceRows;
if (sourceRows == null || sourceRows.Count <= 0)
{
continue;
}
modPackage.ImportSourceLocalizations(sortedDictionary);
if (!ModManagerCore.generateLocalizations || (!modPackage.isInPackages && !Application.isEditor))
{
continue;
}
foreach (BaseModPackage package4 in packages)
if (Lang.IsBuiltin(modPackage.Mapping.SourceLangMod) && Lang.IsBuiltin(lang))
{
break;
}
try
{
if (package4.isInPackages && package3.id == package4.id)
SortedDictionary<string, string> sortedDictionary3 = dictionary.GetValueOrDefault(modPackage.id) ?? new SortedDictionary<string, string>();
SortedDictionary<string, string> sortedDictionary4 = modPackage.ExportSourceLocalizations();
SortedDictionary<string, string> final = new SortedDictionary<string, string>();
foreach (KeyValuePair<string, string> item2 in sortedDictionary4)
{
package4.hasPublishedPackage = true;
item2.Deconstruct(out value, out key);
string key3 = value;
string defaultValue = key;
final[key3] = sortedDictionary3.GetValueOrDefault(key3, defaultValue);
}
if (sortedDictionary3.Count != final.Count || sortedDictionary3.Any((KeyValuePair<string, string> kv) => !final.TryGetValue(kv.Key, out var value3) || value3 != kv.Value))
{
IO.SaveFile(Path.Combine(modPackage.dirInfo.FullName, "LangMod", text), final, compress: false, setting);
Debug.Log($"#source localization updated {text} / {modPackage}");
}
}
catch (Exception arg2)
{
Debug.LogError($"#source localization failed to generate {modPackage}\n{arg2}");
}
}
loading?.Log("Total number of Mods:" + packages.Count);
if ((bool)loading)
{
loading.Log("Activating Mods...");
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
}
BaseModManager.listChainLoad.Clear();
ListPluginObject.Clear();
foreach (BaseModPackage package5 in packages)
}
public void ImportAllModSourceSheets()
{
try
{
if (package5.IsValidVersion() && (!disableMod || package5.builtin))
SourceImporter.HotInit(new SourceData[2]
{
EClass.sources.elements,
EClass.sources.materials
});
List<string> list = new List<string>();
foreach (EMod value in base.MappedPackages.Values)
{
package5.Activate();
if (package5.activated)
if (value.builtin || !value.activated)
{
continue;
}
foreach (FileInfo sourceSheet in value.Mapping.SourceSheets)
{
BaseModManager.listChainLoad.Add(package5.dirInfo.FullName);
if (!sourceSheet.Name.StartsWith(".") && !sourceSheet.Name.Contains("~"))
{
ModUtil.sourceImporter.fileProviders[sourceSheet.FullName] = value;
list.Add(sourceSheet.FullName);
}
}
}
ModUtil.sourceImporter.ImportFilesCached(list);
}
ModUtil.OnModsActivated();
ModUtil.LoadTypeFallback();
BaseModManager.isInitialized = true;
yield return new WaitForEndOfFrame();
onComplete?.Invoke();
if ((bool)loading)
catch (Exception message)
{
UnityEngine.Object.Destroy(loading.gameObject);
Debug.LogError(message);
}
yield return null;
Debug.Log("#source finished importing workbooks");
}
public void SaveLoadOrder()
public void ImportModDialogs()
{
Lang.extraExcelDialogs = new HashSet<string>(PathComparer.Default);
Lang.excelDialog = null;
FileInfo[] files = PackageIterator.GetFiles("Dialog/dialog.xlsx");
foreach (FileInfo fileInfo in files)
{
Lang.extraExcelDialogs.Add(fileInfo.FullName);
Debug.Log("#dialog loaded " + fileInfo.ShortPath());
}
}
public void ImportAllModGodTalks()
{
if (disableMod)
if (Lang.setting?.dir == null)
{
return;
}
List<string> list = new List<string>();
foreach (BaseModPackage package in packages)
Dictionary<string, Dictionary<string, string>> map = EClass.sources.dataGodTalk.sheets["_default"].map;
foreach (ExcelData item in from f in PackageIterator.GetFiles("Data/god_talk.xlsx")
select new ExcelData(f.FullName, 3))
{
if (!package.builtin && Directory.Exists(package.dirInfo.FullName))
foreach (KeyValuePair<string, Dictionary<string, string>> item2 in map)
{
string item = package.dirInfo.FullName + "," + (package.willActivate ? 1 : 0);
list.Add(item);
item2.Deconstruct(out var key, out var _);
string text = key;
if (text.IsEmpty())
{
continue;
}
Dictionary<string, string> valueOrDefault = item.sheets["_default"].map.GetValueOrDefault(text);
if (valueOrDefault == null)
{
continue;
}
foreach (KeyValuePair<string, string> item3 in valueOrDefault)
{
item3.Deconstruct(out key, out var value2);
string text2 = key;
string value3 = value2;
if (text2 != "id")
{
map[text][text2] = value3;
}
}
}
Debug.Log("#dialog loaded " + item.path.ShortPath());
}
File.WriteAllLines(CorePath.rootExe + "loadorder.txt", list);
}
public void LoadLoadOrder()
public IEnumerator RefreshMods(Action onComplete, bool syncMods)
{
string path = CorePath.rootExe + "loadorder.txt";
if (!File.Exists(path))
{
return;
}
Dictionary<string, BaseModPackage> dictionary = new Dictionary<string, BaseModPackage>();
foreach (BaseModPackage package in packages)
bool flag = !BaseCore.IsOffline && syncMods && UserGeneratedContent.Client.GetNumSubscribedItems() != 0;
_loading = Util.Instantiate<LoadingScreen>("LoadingScreen");
WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
packages.Clear();
disableMod |= Application.isEditor && EClass.debug.skipMod;
LoadLocalPackages();
LoadCustomPackage();
if (!disableMod)
{
if (!package.builtin)
_loading.Log("Loading workshop contents...");
if (flag)
{
dictionary[package.dirInfo.FullName] = package;
yield return LoadWorkshopPackages();
}
else if (dirWorkshop != null)
{
DirectoryInfo[] directories = dirWorkshop.GetDirectories();
foreach (DirectoryInfo dir in directories)
{
AddPackage(dir);
}
}
}
int num = 0;
string[] array = File.ReadAllLines(path);
for (int i = 0; i < array.Length; i++)
InitPackagesMeta();
LoadLoadOrder();
packages.Sort((BaseModPackage a, BaseModPackage b) => a.loadPriority - b.loadPriority);
foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.isInPackages && p.willActivate))
{
string[] array2 = array[i].Split(',');
if (dictionary.ContainsKey(array2[0]))
if (mappedPackages.TryGetValue(item.id, out var value) && value.isInPackages)
{
BaseModPackage baseModPackage = dictionary[array2[0]];
baseModPackage.loadPriority = num;
baseModPackage.willActivate = array2[1] == "1";
value.hasPublishedPackage = true;
mappedPackages[item.id] = item as ModPackage;
}
num++;
}
packages.RemoveAll((BaseModPackage p) => p.hasPublishedPackage);
_loading.Log($"Total number of mods:{packages.Count}");
_loading.Log("Activating Mods...");
yield return awaiter;
ActivatePackages();
BaseModManager.isInitialized = true;
yield return awaiter;
onComplete?.Invoke();
if ((bool)_loading)
{
UnityEngine.Object.Destroy(_loading.gameObject);
}
yield return null;
}
public ModPackage AddPackage(DirectoryInfo dir, bool isInPackages = false)public ModPackage AddPackage(DirectoryInfo dir, bool isInPackages = false)
ModPackage modPackage = new ModPackage
{
dirInfo = dir,
installed = true
installed = true,
isInPackages = isInPackages,
loadPriority = priorityIndex,
Mapping = new FileMapping(dir)
};
packages.Add(modPackage);
modPackage.isInPackages = isInPackages;
modPackage.loadPriority = priorityIndex;
priorityIndex++;
return modPackage;
}
public ModPackage AddWorkshopPackage(WorkshopItem item, bool isInPackages = false)
{
UserGeneratedContent.Client.GetItemInstallInfo(item.FileId, out var _, out var folderPath, out var _);
DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
ModPackage modPackage = new ModPackage
{
item = item,
dirInfo = directoryInfo,
installed = directoryInfo.Exists,
banned = item.IsBanned
};
packages.Add(modPackage);
modPackage.isInPackages = isInPackages;
modPackage.loadPriority = priorityIndex;
priorityIndex++;
ulong sizeOnDisk;
string folderPath;
DateTime timeStamp;
bool itemInstallInfo = UserGeneratedContent.Client.GetItemInstallInfo(item.FileId, out sizeOnDisk, out folderPath, out timeStamp);
DirectoryInfo dir = new DirectoryInfo(folderPath);
ModPackage modPackage = AddPackage(dir, isInPackages);
modPackage.installed = itemInstallInfo;
modPackage.banned = item.IsBanned;
return modPackage;
}
public int CountUserMod()
{
int num = 0;
foreach (BaseModPackage package in packages)
return packages.Count((BaseModPackage p) => !p.builtin);
}
public void LoadLocalPackages()
{
_loading.Log("Loading local Package...");
DirectoryInfo[] directories = new DirectoryInfo(BaseModManager.rootMod).GetDirectories();
Array.Reverse(directories);
DirectoryInfo[] array = directories;
foreach (DirectoryInfo directoryInfo in array)
{
if (!package.builtin)
if (!disableMod || !(directoryInfo.Name != "_Elona") || !(directoryInfo.Name != "_Lang_Chinese"))
{
num++;
AddPackage(directoryInfo, isInPackages: true);
}
}
return num;
}
public override void ParseExtra(DirectoryInfo dir, BaseModPackage package)
public void LoadCustomPackage()
{
switch (dir.Name)
{
case "TalkText":
_loading.Log("Loading user Custom...");
DirectoryInfo[] directories = new DirectoryInfo(CorePath.custom).GetDirectories();
ModPackage package = new ModPackage();
DirectoryInfo[] array = directories;
foreach (DirectoryInfo dir in array)
{
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo in files)
{
if (fileInfo.Name.EndsWith(".xlsx"))
{
TalkText.modList.Add(new ExcelData(fileInfo.FullName));
}
}
break;
ParseExtra(dir, package);
}
case "Map":
}
public IEnumerator LoadWorkshopPackages()
{
WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
UgcQuery activeQuery = UgcQuery.GetSubscribed(withLongDescription: false, withMetadata: false, withKeyValueTags: false, withAdditionalPreviews: false, 0u);
activeQuery.Execute(HandleWorkshopQuery);
_loading.Log("Fetching subscriptions...(Hit ESC to cancel)");
while (activeQuery.handle != UGCQueryHandle_t.Invalid && !UnityEngine.Input.GetKey(KeyCode.Escape))
{
if (package.builtin)
{
break;
}
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo5 in files)
{
if (fileInfo5.Name.EndsWith(".z"))
{
MOD.listMaps.Add(fileInfo5);
}
}
break;
yield return awaiter;
}
case "Map Piece":
yield return UpdateWorkshopPackages();
void HandleWorkshopQuery(UgcQuery query)
{
if (package.builtin)
foreach (WorkshopItem results in query.ResultsList)
{
break;
}
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo3 in files)
{
if (fileInfo3.Name.EndsWith(".mp"))
{
MOD.listPartialMaps.Add(fileInfo3);
}
AddWorkshopPackage(results);
}
break;
}
case "Texture Replace":
}
private IEnumerator UpdateWorkshopPackages()
{
_loading?.Log("Updating subscriptions...");
WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
while (true)
{
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo6 in files)
bool flag = false;
foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.installed))
{
if (fileInfo6.Name.EndsWith(".png"))
if (!(item.item is WorkshopItem { IsBanned: false } workshopItem))
{
replaceFiles.Add(fileInfo6);
continue;
}
}
break;
}
case "Texture":
{
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo4 in files)
{
if (fileInfo4.Name.EndsWith(".png"))
flag = true;
string text = "Downloading " + workshopItem.Title + ": ";
BaseModPackage baseModPackage = item;
if ((object)baseModPackage.progressText == null)
{
SpriteReplacer.dictModItems[fileInfo4.Name.Replace(".png", "")] = fileInfo4.GetFullFileNameWithoutExtension();
baseModPackage.progressText = _loading?.Log(text);
}
}
break;
}
case "Portrait":
{
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo2 in files)
{
if (fileInfo2.Name.EndsWith(".png"))
if (item.downloadStarted && workshopItem.DownloadCompletion >= 1f)
{
if (fileInfo2.Name.StartsWith("BG_"))
{
Portrait.modPortraitBGs.Add(fileInfo2);
}
else if (fileInfo2.Name.StartsWith("BGF_"))
item.installed = true;
if ((bool)item.progressText)
{
Portrait.modPortraitBGFs.Add(fileInfo2);
item.progressText.text = text + "Done!";
}
else if (fileInfo2.Name.EndsWith("-full.png"))
{
Portrait.modFull.Add(fileInfo2);
}
else if (fileInfo2.Name.EndsWith("-overlay.png"))
{
Portrait.modOverlays.Add(fileInfo2);
}
else
{
Portrait.modPortraits.Add(fileInfo2);
}
Portrait.allIds.Add(fileInfo2.Name);
}
}
break;
}
case "Lang":
{
DirectoryInfo[] directories = dir.GetDirectories();
foreach (DirectoryInfo directoryInfo in directories)
{
if (!directoryInfo.Name.StartsWith("_") && !TryAddLang(directoryInfo, isNew: false))
{
EClass.sources.Init();
Debug.Log("Generating Language Mod Contents:" + directoryInfo.FullName);
IO.CopyDir(CorePath.packageCore + "Lang/EN", directoryInfo.FullName);
Directory.CreateDirectory(directoryInfo.FullName + "/Dialog");
IO.CopyDir(CorePath.packageCore + "Lang/_Dialog", directoryInfo.FullName + "/Dialog");
EClass.sources.ExportSourceTexts(directoryInfo.FullName + "/Game");
IO.Copy(CorePath.packageCore + "Lang/lang.ini", directoryInfo.FullName + "/");
TryAddLang(directoryInfo, isNew: true);
}
}
break;
}
}
bool TryAddLang(DirectoryInfo dirLang, bool isNew)
{
string name = dirLang.Name;
FileInfo[] files2 = dirLang.GetFiles();
foreach (FileInfo fileInfo7 in files2)
{
if (fileInfo7.Name == "lang.ini")
else if (workshopItem.IsDownloading || workshopItem.IsDownloadPending)
{
LangSetting langSetting = new LangSetting(fileInfo7.FullName)
int num = Mathf.FloorToInt(workshopItem.DownloadCompletion * 100f);
if ((bool)item.progressText)
{
id = name,
dir = dirLang.FullName + "/"
};
if (isNew)
{
langSetting.SetVersion();
}
else if ((Application.isEditor || Lang.runUpdate) && !Lang.IsBuiltin(dirLang.Name) && langSetting.GetVersion() != EClass.core.version.GetInt())
{
Log.system = "Updated Language Files:" + Environment.NewLine + Environment.NewLine;
Debug.Log("Updating Language:" + langSetting.name + "/" + langSetting.GetVersion() + "/" + EClass.core.version.GetInt());
EClass.sources.Init();
string text = dirLang.FullName + "/Game";
Directory.Move(text, text + "_temp");
EClass.sources.ExportSourceTexts(text);
EClass.sources.UpdateSourceTexts(text);
IO.DeleteDirectory(text + "_temp");
text = dirLang.FullName + "/Dialog";
Directory.Move(text, text + "_temp");
IO.CopyDir(CorePath.packageCore + "Lang/_Dialog", text);
UpdateDialogs(new DirectoryInfo(text), text + "_temp");
IO.DeleteDirectory(text + "_temp");
text = dirLang.FullName + "/Data";
IO.CopyDir(text, text + "_temp");
IO.Copy(CorePath.packageCore + "Lang/EN/Data/god_talk.xlsx", text);
IO.Copy(CorePath.packageCore + "Lang/EN/Data/chara_talk.xlsx", text);
UpdateTalks(new DirectoryInfo(text), text + "_temp");
IO.DeleteDirectory(text + "_temp");
langSetting.SetVersion();
IO.SaveText(dirLang.FullName + "/update.txt", Log.system);
item.progressText.text = text + num + "%";
}
MOD.langs[name] = langSetting;
return true;
}
else if (!item.downloadStarted)
{
item.downloadStarted = true;
workshopItem.DownloadItem(highPriority: true);
Debug.Log("Start downloading: " + workshopItem.Title + " | " + $"Installed={workshopItem.IsInstalled}, " + $"Downloading={workshopItem.IsDownloading}, " + $"Pending={workshopItem.IsDownloadPending}");
}
}
return false;
}
}
public void UpdateDialogs(DirectoryInfo dir, string dirTemp)
{
DirectoryInfo[] directories = dir.GetDirectories();
foreach (DirectoryInfo directoryInfo in directories)
{
UpdateDialogs(directoryInfo, dirTemp + "/" + directoryInfo.Name);
}
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo in files)
{
if (fileInfo.Name.EndsWith("xlsx"))
if (!flag)
{
UpdateExcelBook(fileInfo, dirTemp, updateOnlyText: true);
yield break;
}
}
}
public void UpdateTalks(DirectoryInfo dir, string dirTemp)
{
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo in files)
{
if (fileInfo.Name == "god_talk.xlsx" || fileInfo.Name == "chara_talk.xlsx")
if (UnityEngine.Input.GetKey(KeyCode.Escape))
{
UpdateExcelBook(fileInfo, dirTemp, updateOnlyText: false);
break;
}
yield return awaiter;
}
Debug.Log("Workshop updating cancelled");
}
public void UpdateExcelBook(FileInfo f, string dirTemp, bool updateOnlyText)
public void InitPackagesMeta()
{
string path = dirTemp + "/" + f.Name;
if (!File.Exists(path))
{
return;
}
XSSFWorkbook xSSFWorkbook;
using (FileStream @is = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
xSSFWorkbook = new XSSFWorkbook((Stream)@is);
}
XSSFWorkbook xSSFWorkbook2;
using (FileStream is2 = File.Open(f.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
xSSFWorkbook2 = new XSSFWorkbook((Stream)is2);
}
for (int i = 0; i < xSSFWorkbook2.NumberOfSheets; i++)
foreach (BaseModPackage package in packages)
{
ISheet sheetAt = xSSFWorkbook2.GetSheetAt(i);
ISheet sheet = xSSFWorkbook.GetSheet(sheetAt.SheetName);
if (sheet == null)
try
{
Log.system = Log.system + "Old sheet not found:" + sheetAt.SheetName + Environment.NewLine;
continue;
package.Init();
mappedPackages[package.id] = package as ModPackage;
_loading?.Log(package.ToString());
}
int num = UpdateExcelSheet(sheetAt, sheet, updateOnlyText);
Log.system = Log.system + ((num == 0) ? "(No Changes) " : "(Updated) ") + f.FullName + "(" + sheetAt.SheetName + ")" + Environment.NewLine;
if (num != 0)
catch (Exception ex)
{
Log.system = Log.system + num + Environment.NewLine;
package.willActivate = false;
_loading?.Log("Mod " + package.title + "/" + package.id + " has failed to initialize, reason: " + ex.Message);
}
Log.system += Environment.NewLine;
}
using FileStream stream = new FileStream(f.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
xSSFWorkbook2.Write(stream);
}
public int UpdateExcelSheet(ISheet destSheet, ISheet oldSheet, bool updateOnlytext)
public void ActivatePackages()
{
Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>();
int num = 0;
int num2 = 0;
int num3 = 10;
IRow row2 = destSheet.GetRow(0);
IRow row3 = oldSheet.GetRow(0);
List<SheetIndex> list = new List<SheetIndex>();
int cellnum = FindField(row2, "id");
int cellnum2 = FindField(row3, "id");
for (int i = 0; i < row2.LastCellNum; i++)
BaseModManager.listChainLoad.Clear();
ListPluginObject.Clear();
foreach (ModPackage package in packages)
{
ICell cell = row2.GetCell(i);
if (cell == null)
{
break;
}
string stringCellValue = cell.StringCellValue;
if (stringCellValue == "id" || (updateOnlytext && stringCellValue != "text"))
if ((disableMod && !package.builtin) || !package.IsValidVersion())
{
continue;
}
for (int j = 0; j < row3.LastCellNum; j++)
{
cell = row3.GetCell(j);
if (cell == null)
{
break;
}
if (cell.StringCellValue == stringCellValue)
{
list.Add(new SheetIndex
{
dest = i,
old = j
});
Debug.Log(destSheet.SheetName + "/" + stringCellValue + "/" + i + "/" + j);
break;
}
}
}
for (int k = 2; k <= oldSheet.LastRowNum; k++)
{
IRow row4 = oldSheet.GetRow(k);
if (row4 == null)
try
{
if (num2 >= num3)
package.Activate();
if (package.activated)
{
break;
BaseModManager.listChainLoad.Add(package.dirInfo.FullName);
}
num2++;
continue;
}
num2 = 0;
ICell cell2 = row4.GetCell(cellnum2);
if (cell2 == null)
{
continue;
}
string text = ((cell2.CellType == CellType.Numeric) ? cell2.NumericCellValue.ToString() : cell2.StringCellValue);
if (text.IsEmpty())
{
continue;
}
string[] array = new string[list.Count];
for (int l = 0; l < list.Count; l++)
catch (Exception ex)
{
ICell cell3 = row4.GetCell(list[l].old);
if (cell3 != null)
{
string stringCellValue2 = cell3.StringCellValue;
if (!stringCellValue2.IsEmpty())
{
array[l] = stringCellValue2;
}
}
_loading.Log("Failed to activate mod: " + package.title + ", reason: " + ex.Message);
}
dictionary.Add(text, array);
}
num2 = 0;
for (int m = 2; m <= destSheet.LastRowNum; m++)
ModUtil.OnModsActivated();
ModUtil.LoadTypeFallback();
}
public override void ParseExtra(DirectoryInfo dir, BaseModPackage package)
{
ModPackage modPackage = (ModPackage)package;
switch (dir.Name)
{
IRow row5 = destSheet.GetRow(m);
if (row5 == null)
{
if (num2 >= num3)
{
break;
}
num2++;
continue;
}
num2 = 0;
ICell cell4 = row5.GetCell(cellnum);
if (cell4 == null)
{
continue;
}
string text2 = ((cell4.CellType == CellType.Numeric) ? cell4.NumericCellValue.ToString() : cell4.StringCellValue);
if (text2.IsEmpty() || !dictionary.ContainsKey(text2))
{
continue;
}
string[] array2 = dictionary[text2];
for (int n = 0; n < list.Count; n++)
case "TalkText":
modPackage.ParseTalkText(dir);
break;
case "Map":
if (!package.builtin)
{
ICell cell5 = row5.GetCell(list[n].dest) ?? row5.CreateCell(list[n].dest, CellType.String);
if (cell5 != null)
{
cell5.SetCellValue(array2[n]);
cell5.SetCellType(CellType.String);
cell5.SetAsActiveCell();
num++;
}
modPackage.ParseMap(dir);
}
}
return num;
static int FindField(IRow row, string id)
{
for (int num4 = 0; num4 < row.LastCellNum; num4++)
break;
case "Map Piece":
if (!package.builtin)
{
ICell cell6 = row.GetCell(num4);
if (cell6 == null)
{
break;
}
if (cell6.StringCellValue == id)
{
return num4;
}
modPackage.ParseMapPiece(dir);
}
return -1;
break;
case "Texture Replace":
replaceFiles.AddRange(modPackage.ParseTextureReplace(dir));
break;
case "Texture":
modPackage.ParseTexture(dir);
break;
case "Portrait":
modPackage.ParsePortrait(dir);
break;
case "LangMod":
modPackage.ParseLangMod(dir);
break;
case "Sound":
modPackage.ParseSound(dir);
break;
case "Lang":
modPackage.AddOrUpdateLang(dir);
break;
}
}
}ModPackage
public class ModPackage : BaseModPackage
public class ModPackage : BaseModPackage
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using UnityEngine;
public class ModPackage : EMod
{
public struct SheetIndex
{
public int dest;
public int old;
}
public IReadOnlyList<FileInfo> ParseTalkText(DirectoryInfo dir)
{
List<FileInfo> list = new List<FileInfo>();
FileInfo[] files = dir.GetFiles("*.xlsx", SearchOption.TopDirectoryOnly);
foreach (FileInfo fileInfo in files)
{
ExcelData excelData = new ExcelData(fileInfo.FullName);
TalkText.modList.Add(excelData);
talkTexts.Add(excelData);
list.Add(fileInfo);
}
if (list.Count > 0)
{
Debug.Log($"TalkText: {talkTexts.Count}");
}
return list;
}
public IReadOnlyList<FileInfo> ParseMap(DirectoryInfo dir, bool addToList = true)
{
List<FileInfo> list = new List<FileInfo>();
FileInfo[] files = dir.GetFiles("*.z", SearchOption.TopDirectoryOnly);
foreach (FileInfo fileInfo in files)
{
string key = Path.ChangeExtension(fileInfo.Name, null);
if (addToList)
{
MOD.listMaps.Add(fileInfo);
}
maps[key] = fileInfo;
list.Add(fileInfo);
}
if (list.Count > 0)
{
Debug.Log($"Map: {maps.Count}");
}
return list;
}
public IReadOnlyList<FileInfo> ParseMapPiece(DirectoryInfo dir, bool addToList = true)
{
List<FileInfo> list = new List<FileInfo>();
FileInfo[] files = dir.GetFiles("*.mp", SearchOption.TopDirectoryOnly);
foreach (FileInfo fileInfo in files)
{
string key = Path.ChangeExtension(fileInfo.Name, null);
if (addToList)
{
MOD.listPartialMaps.Add(fileInfo);
}
partialMaps[key] = fileInfo;
list.Add(fileInfo);
}
if (list.Count > 0)
{
Debug.Log($"PartialMap: {partialMaps.Count}");
}
return list;
}
public IReadOnlyList<FileInfo> ParseTextureReplace(DirectoryInfo dir)
{
List<FileInfo> list = new List<FileInfo>();
FileInfo[] files = dir.GetFiles("*.png", SearchOption.TopDirectoryOnly);
foreach (FileInfo fileInfo in files)
{
string key = Path.ChangeExtension(fileInfo.Name, null);
textureReplaces[key] = fileInfo;
list.Add(fileInfo);
}
if (list.Count > 0)
{
Debug.Log($"Texture Replace: {textureReplaces.Count}");
}
return list;
}
public IReadOnlyList<FileInfo> ParseTexture(DirectoryInfo dir)
{
List<FileInfo> list = new List<FileInfo>();
FileInfo[] files = dir.GetFiles("*.png", SearchOption.AllDirectories);
foreach (FileInfo fileInfo in files)
{
string key = Path.ChangeExtension(Path.GetRelativePath(dir.FullName, fileInfo.FullName).NormalizePath(), null);
string text = Path.ChangeExtension(fileInfo.FullName, null);
Dictionary<string, string> dictModItems = SpriteReplacer.dictModItems;
string value = (textures[key] = text);
dictModItems[key] = value;
list.Add(fileInfo);
}
if (list.Count > 0)
{
Debug.Log($"Texture: {textures.Count}");
}
return list;
}
public IReadOnlyList<FileInfo> ParsePortrait(DirectoryInfo dir)
{
List<FileInfo> list = new List<FileInfo>();
FileInfo[] files = dir.GetFiles("*.png", SearchOption.TopDirectoryOnly);
foreach (FileInfo fileInfo in files)
{
string name = fileInfo.Name;
if (name.StartsWith("BG_", StringComparison.Ordinal))
{
Portrait.modPortraitBGs.Add(fileInfo);
}
else if (name.StartsWith("BGF_", StringComparison.Ordinal))
{
Portrait.modPortraitBGFs.Add(fileInfo);
}
else if (name.EndsWith("-full.png", StringComparison.Ordinal))
{
Portrait.modFull.Add(fileInfo);
}
else if (name.EndsWith("-overlay.png", StringComparison.Ordinal))
{
Portrait.modOverlays.Add(fileInfo);
}
else
{
Portrait.modPortraits.Add(fileInfo);
}
Portrait.allIds.Add(name);
portraits[name] = fileInfo;
list.Add(fileInfo);
}
if (list.Count > 0)
{
Debug.Log($"Portrait: {portraits.Count}");
}
return list;
}
public void ParseLangMod(DirectoryInfo dir)
{
if (Mapping == null)
{
Mapping = new FileMapping(dir.Parent);
}
Mapping.RebuildLangModMapping(EClass.core.config?.lang ?? EClass.core.debug.langCode.ToString());
Lang.excelDialog = null;
Debug.Log("LangMod: " + string.Join(", ", Mapping.OrderedLangMods));
if (Mapping.SourceSheets.Count > 0)
{
Debug.Log($"Source Sheets: {Mapping.SourceSheets.Count}, {Mapping.SourceLangMod}");
}
}
public IReadOnlyList<FileInfo> ParseSound(DirectoryInfo dir)
{
List<FileInfo> list = new List<FileInfo>();
FileInfo[] files = dir.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo fileInfo in files)
{
if (ModUtil.GetAudioType(fileInfo.Extension) != 0)
{
string key = Path.ChangeExtension(Path.GetRelativePath(dir.FullName, fileInfo.FullName).NormalizePath(), null);
Dictionary<string, FileInfo> dictionary = MOD.sounds;
FileInfo value = (sounds[key] = fileInfo);
dictionary[key] = value;
list.Add(fileInfo);
}
}
if (list.Count > 0)
{
Debug.Log($"Sound: {sounds.Count}");
}
int num = sounds.Keys.Count((string k) => k.StartsWith("BGM/"));
if (num > 0)
{
Debug.Log($"BGM: {num}");
}
return list;
}
public SortedDictionary<string, string> ExportSourceLocalizations()
{
SortedDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>();
try
{
foreach (SourceData.BaseRow sourceRow in sourceRows)
{
foreach (KeyValuePair<string, string> item in sourceRow.ExportTexts(sourceRow.UseAlias ? "alias" : "id"))
{
item.Deconstruct(out var key, out var value);
string key2 = key;
string value2 = value;
sortedDictionary[key2] = value2;
}
}
}
catch (Exception arg)
{
Debug.LogError($"#source failed to export localization for {title}/{id}\n{arg}");
}
return sortedDictionary;
}
public void ImportSourceLocalizations(IReadOnlyDictionary<string, string> texts)
{
foreach (SourceData.BaseRow sourceRow in sourceRows)
{
sourceRow.ImportTexts(texts, sourceRow.UseAlias ? "alias" : "id");
}
}
public void ClearSourceLocalizations(string lang)
{
Mapping.RebuildLangModMapping(lang);
for (FileInfo fileInfo = Mapping.RelocateFile("SourceLocalization.json"); fileInfo != null; fileInfo = Mapping.RelocateFile("SourceLocalization.json"))
{
fileInfo.Delete();
Debug.Log("#source localization deleted " + fileInfo.ShortPath());
}
Mapping.RebuildLangModMapping(Lang.langCode);
}
public void AddOrUpdateLang(DirectoryInfo dir)
{
Core core = EClass.core;
SourceManager sources = core.sources;
DirectoryInfo[] directories = dir.GetDirectories();
foreach (DirectoryInfo directoryInfo in directories)
{
if (!directoryInfo.Name.StartsWith("_") && !TryAddLang(directoryInfo, isNew: false))
{
Debug.Log("Generating Language Mod Contents:" + directoryInfo.FullName);
IO.CopyDir(CorePath.packageCore + "Lang/EN", directoryInfo.FullName);
Directory.CreateDirectory(directoryInfo.FullName + "/Dialog");
IO.CopyDir(CorePath.packageCore + "Lang/_Dialog", directoryInfo.FullName + "/Dialog");
sources.ExportSourceTexts(directoryInfo.FullName + "/Game");
IO.Copy(CorePath.packageCore + "Lang/lang.ini", directoryInfo.FullName + "/");
TryAddLang(directoryInfo, isNew: true);
}
}
bool TryAddLang(DirectoryInfo dirLang, bool isNew)
{
string name = dirLang.Name;
FileInfo[] files = dirLang.GetFiles();
foreach (FileInfo fileInfo in files)
{
if (fileInfo.Name == "lang.ini")
{
LangSetting langSetting = new LangSetting(fileInfo.FullName)
{
id = name,
dir = dirLang.FullName + "/"
};
if (isNew)
{
langSetting.SetVersion();
}
else if ((Application.isEditor || Lang.runUpdate) && !Lang.IsBuiltin(dirLang.Name) && langSetting.GetVersion() < core.version.GetInt())
{
sources.Init();
Log.system = "Updated Language Files:" + Environment.NewLine + Environment.NewLine;
Debug.Log("Updating Language:" + langSetting.name + "/" + langSetting.GetVersion() + "/" + core.version.GetInt());
string text = dirLang.FullName + "/Game";
Directory.Move(text, text + "_temp");
sources.ExportSourceTexts(text);
sources.UpdateSourceTexts(text);
IO.DeleteDirectory(text + "_temp");
text = dirLang.FullName + "/Dialog";
Directory.Move(text, text + "_temp");
IO.CopyDir(CorePath.packageCore + "Lang/_Dialog", text);
UpdateDialogs(new DirectoryInfo(text), text + "_temp");
IO.DeleteDirectory(text + "_temp");
text = dirLang.FullName + "/Data";
IO.CopyDir(text, text + "_temp");
IO.Copy(CorePath.packageCore + "Lang/EN/Data/god_talk.xlsx", text);
IO.Copy(CorePath.packageCore + "Lang/EN/Data/chara_talk.xlsx", text);
UpdateTalks(new DirectoryInfo(text), text + "_temp");
IO.DeleteDirectory(text + "_temp");
langSetting.SetVersion();
IO.SaveText(dirLang.FullName + "/update.txt", Log.system);
}
MOD.langs[name] = langSetting;
return true;
}
}
return false;
}
}
public void UpdateDialogs(DirectoryInfo dir, string dirTemp)
{
DirectoryInfo[] directories = dir.GetDirectories();
foreach (DirectoryInfo directoryInfo in directories)
{
UpdateDialogs(directoryInfo, dirTemp + "/" + directoryInfo.Name);
}
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo in files)
{
if (fileInfo.Name.EndsWith("xlsx"))
{
UpdateExcelBook(fileInfo, dirTemp, updateOnlyText: true);
}
}
}
public void UpdateTalks(DirectoryInfo dir, string dirTemp)
{
FileInfo[] files = dir.GetFiles();
foreach (FileInfo fileInfo in files)
{
if (fileInfo.Name == "god_talk.xlsx" || fileInfo.Name == "chara_talk.xlsx")
{
UpdateExcelBook(fileInfo, dirTemp, updateOnlyText: false);
}
}
}
public void UpdateExcelBook(FileInfo f, string dirTemp, bool updateOnlyText)
{
string path = dirTemp + "/" + f.Name;
if (!File.Exists(path))
{
return;
}
XSSFWorkbook xSSFWorkbook;
using (FileStream @is = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
xSSFWorkbook = new XSSFWorkbook((Stream)@is);
}
XSSFWorkbook xSSFWorkbook2;
using (FileStream is2 = File.Open(f.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
xSSFWorkbook2 = new XSSFWorkbook((Stream)is2);
}
for (int i = 0; i < xSSFWorkbook2.NumberOfSheets; i++)
{
ISheet sheetAt = xSSFWorkbook2.GetSheetAt(i);
ISheet sheet = xSSFWorkbook.GetSheet(sheetAt.SheetName);
if (sheet == null)
{
Log.system = Log.system + "Old sheet not found:" + sheetAt.SheetName + Environment.NewLine;
continue;
}
int num = UpdateExcelSheet(sheetAt, sheet, updateOnlyText);
Log.system = Log.system + ((num == 0) ? "(No Changes) " : "(Updated) ") + f.FullName + "(" + sheetAt.SheetName + ")" + Environment.NewLine;
if (num != 0)
{
Log.system = Log.system + num + Environment.NewLine;
}
Log.system += Environment.NewLine;
}
using FileStream stream = new FileStream(f.FullName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
xSSFWorkbook2.Write(stream);
}
public int UpdateExcelSheet(ISheet destSheet, ISheet oldSheet, bool updateOnlytext)
{
Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>();
int num = 0;
int num2 = 0;
int num3 = 10;
IRow row2 = destSheet.GetRow(0);
IRow row3 = oldSheet.GetRow(0);
List<SheetIndex> list = new List<SheetIndex>();
int cellnum = FindField(row2, "id");
int cellnum2 = FindField(row3, "id");
for (int i = 0; i < row2.LastCellNum; i++)
{
ICell cell = row2.GetCell(i);
if (cell == null)
{
break;
}
string stringCellValue = cell.StringCellValue;
if (stringCellValue == "id" || (updateOnlytext && stringCellValue != "text"))
{
continue;
}
for (int j = 0; j < row3.LastCellNum; j++)
{
cell = row3.GetCell(j);
if (cell == null)
{
break;
}
if (cell.StringCellValue == stringCellValue)
{
list.Add(new SheetIndex
{
dest = i,
old = j
});
Debug.Log(destSheet.SheetName + "/" + stringCellValue + "/" + i + "/" + j);
break;
}
}
}
for (int k = 2; k <= oldSheet.LastRowNum; k++)
{
IRow row4 = oldSheet.GetRow(k);
if (row4 == null)
{
if (num2 >= num3)
{
break;
}
num2++;
continue;
}
num2 = 0;
ICell cell2 = row4.GetCell(cellnum2);
if (cell2 == null)
{
continue;
}
string text = ((cell2.CellType == CellType.Numeric) ? cell2.NumericCellValue.ToString() : cell2.StringCellValue);
if (text.IsEmpty())
{
continue;
}
string[] array = new string[list.Count];
for (int l = 0; l < list.Count; l++)
{
ICell cell3 = row4.GetCell(list[l].old);
if (cell3 != null)
{
string stringCellValue2 = cell3.StringCellValue;
if (!stringCellValue2.IsEmpty())
{
array[l] = stringCellValue2;
}
}
}
dictionary.Add(text, array);
}
num2 = 0;
for (int m = 2; m <= destSheet.LastRowNum; m++)
{
IRow row5 = destSheet.GetRow(m);
if (row5 == null)
{
if (num2 >= num3)
{
break;
}
num2++;
continue;
}
num2 = 0;
ICell cell4 = row5.GetCell(cellnum);
if (cell4 == null)
{
continue;
}
string text2 = ((cell4.CellType == CellType.Numeric) ? cell4.NumericCellValue.ToString() : cell4.StringCellValue);
if (text2.IsEmpty() || !dictionary.ContainsKey(text2))
{
continue;
}
string[] array2 = dictionary[text2];
for (int n = 0; n < list.Count; n++)
{
ICell cell5 = row5.GetCell(list[n].dest) ?? row5.CreateCell(list[n].dest, CellType.String);
if (cell5 != null)
{
cell5.SetCellValue(array2[n]);
cell5.SetCellType(CellType.String);
cell5.SetAsActiveCell();
num++;
}
}
}
return num;
static int FindField(IRow row, string id)
{
for (int num4 = 0; num4 < row.LastCellNum; num4++)
{
ICell cell6 = row.GetCell(num4);
if (cell6 == null)
{
break;
}
if (cell6.StringCellValue == id)
{
return num4;
}
}
return -1;
}
}
}ModUtil
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using UnityEngine;
using UnityEngine.Networking;
public class ModUtil : EClass
{
public static SourceImporter sourceImporter = new SourceImporter(SourceMapping);
public static Dictionary<string, string> fallbackTypes = new Dictionary<string, string>();
public static void Test()
{
ImportExcel("", "", EClass.sources.charas);
}
public static IReadOnlyDictionary<string, SourceData> SourceMapping => (from f in typeof(SourceManager).GetFields()
where typeof(SourceData).IsAssignableFrom(f.FieldType)
select f).ToDictionary((FieldInfo f) => f.FieldType.Name, (FieldInfo f) => f.GetValue(EClass.sources) as SourceData);
public static void OnModsActivated()
{
SoundManager.current.soundLoaders.Add(LoadSoundData);
BaseModManager.PublishEvent("elin.mods.activated");
}
public static void LoadTypeFallback()public static void RegisterSerializedTypeFallback(string nameAssembly, string na
public static void ImportExcel(string pathToExcelFile, string sheetName, SourceData source)
{
Debug.Log("ImportExcel source:" + source?.ToString() + " Path:" + pathToExcelFile);
UnityEngine.Debug.Log("ImportExcel source:" + source?.ToString() + " Path:" + pathToExcelFile);
using FileStream @is = File.Open(pathToExcelFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
XSSFWorkbook xSSFWorkbook = new XSSFWorkbook((Stream)@is);
for (int i = 0; i < xSSFWorkbook.NumberOfSheets; i++)public static void ImportExcel(string pathToExcelFile, string sheetName, SourceD
{
continue;
}
Debug.Log("Importing Sheet:" + sheetName);
UnityEngine.Debug.Log("Importing Sheet:" + sheetName);
try
{
ExcelParser.path = pathToExcelFile;
if (!source.ImportData(sheetAt, new FileInfo(pathToExcelFile).Name, overwrite: true))
{
Debug.LogError(ERROR.msg);
UnityEngine.Debug.LogError(ERROR.msg);
break;
}
Debug.Log("Imported " + sheetAt.SheetName);
UnityEngine.Debug.Log("Imported " + sheetAt.SheetName);
source.Reset();
}
catch (Exception ex)
{
Debug.LogError("[Error] Skipping import " + sheetAt.SheetName + " :" + ex.Message + "/" + ex.Source + "/" + ex.StackTrace);
UnityEngine.Debug.LogError("[Error] Skipping import " + sheetAt.SheetName + " :" + ex.Message + "/" + ex.Source + "/" + ex.StackTrace);
break;
}
}
}
public static ModPackage FindSourceRowPackage(SourceData.BaseRow row)
{
return ModManagerCore.Instance.MappedPackages.Values.FirstOrDefault((EMod p) => p.sourceRows.Contains(row)) as ModPackage;
}
public static ModPackage GetModPackage(string modId)
{
return ModManagerCore.Instance.MappedPackages.GetValueOrDefault(modId) as ModPackage;
}
public static SerializableSoundData GetSoundMeta(string soundPath)
{
string path = Path.ChangeExtension(soundPath, ".json");
SerializableSoundData serializableSoundData;
if (File.Exists(path))
{
try
{
serializableSoundData = IO.LoadFile<SerializableSoundData>(path);
if (serializableSoundData.dataVersion == SerializableSoundData.SoundDataMetaVersion.V1)
{
return serializableSoundData;
}
}
catch
{
}
}
serializableSoundData = new SerializableSoundData();
if (soundPath.NormalizePath().Contains("/Sound/BGM/"))
{
serializableSoundData.type = SoundData.Type.BGM;
serializableSoundData.bgmDataOptional = new SerializableBGMData();
}
IO.SaveFile(path, serializableSoundData);
return serializableSoundData;
}
public static AudioType GetAudioType(string extension)
{
return extension.ToLowerInvariant().Trim() switch
{
".acc" => AudioType.ACC,
".mp3" => AudioType.MPEG,
".ogg" => AudioType.OGGVORBIS,
".wav" => AudioType.WAV,
_ => AudioType.UNKNOWN,
};
}
public static SoundData LoadSoundData(string soundId)
{
if (!MOD.sounds.TryGetValue(soundId, out var value) || !value.Exists)
{
return null;
}
return LoadSoundData(value);
}
public static SoundData LoadSoundData(FileInfo soundFile)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(soundFile.FullName);
string fullName = soundFile.FullName;
AudioType audioType = GetAudioType(soundFile.Extension);
bool stream = fileNameWithoutExtension.StartsWith("BGM/") && audioType == AudioType.OGGVORBIS;
using UnityWebRequest unityWebRequest = AudioClipStream.GetAudioClip("file://" + fullName, audioType, compressed: false, stream);
unityWebRequest.SendWebRequest();
Stopwatch stopwatch = Stopwatch.StartNew();
while (!unityWebRequest.isDone && stopwatch.ElapsedMilliseconds < 5000)
{
Thread.Sleep(1);
}
if (unityWebRequest.result != UnityWebRequest.Result.Success)
{
UnityEngine.Debug.LogError("#sound '" + fileNameWithoutExtension + "' failed to load: " + unityWebRequest.error.IsEmpty("timeout"));
return null;
}
AudioClip content = DownloadHandlerAudioClip.GetContent(unityWebRequest);
int? num = content?.samples;
if (!num.HasValue || num.GetValueOrDefault() <= 0)
{
UnityEngine.Debug.LogError($"#sound '{fileNameWithoutExtension}' sample is null: {audioType}");
return null;
}
content.name = fileNameWithoutExtension;
SoundData soundData = GetSoundMeta(fullName).ToSoundData();
if (soundData is BGMData bGMData)
{
bGMData._name = Path.GetFileNameWithoutExtension(fullName);
if (bGMData.song == null)
{
bGMData.song = new BGMData.SongData();
bGMData.song.parts.Add(new BGMData.Part());
}
}
soundData.clip = content;
soundData.name = fileNameWithoutExtension;
UnityEngine.Debug.Log($"#sound '{fileNameWithoutExtension}' loaded: {audioType}/{content.length}s");
SoundManager.current.dictData[fileNameWithoutExtension] = soundData;
return soundData;
}
}Msg
public static string GetGameText(string idLang, Card card = null)
{
mainText.Append(mainText.spriteDestroy);
}
if (!row.color.IsEmpty())
if (!row.color.IsEmpty() && colors.colors.TryGetValue(row.color, out var value))
{
SetColor(colors.colors[row.color]);
SetColor(value);
}
if (!row.sound.IsEmpty())
{Party
public Element GetPartySkill(int ele)
return GetBestSkill(ele);
}
public void ModExpPartySkill(int ele, int a)
public void ModExp(int ele, int a)
{
foreach (Chara member in members)
{
member.ModExp(ele, a);
}
}
public Element GetBestSkill(int ele)Recipe
public virtual void Build(Chara chara, Card t, Point pos, int mat, int dir, int
EClass._map.SetFloor(pos.x, pos.z, mat, tileRow.id, dir);
break;
case "Bridge":
{
if (pos.sourceObj.tileType.RemoveOnFloorChange)
{
EClass._map.SetObj(pos.x, pos.z);
}
EClass._map.SetBridge(pos.x, pos.z, Mathf.Clamp(bridgeHeight + altitude, 0, 255), mat, tileRow.id, dir);
byte idPillar = (byte)((tileRow.id == 130) ? 255u : 0u);
EClass._map.SetBridge(pos.x, pos.z, Mathf.Clamp(bridgeHeight + altitude, 0, 255), mat, tileRow.id, dir, idPillar);
break;
}
case "Obj":
EClass._map.SetObj(pos.x, pos.z, mat, tileRow.id, 1, dir, ignoreRandomMat: true);
if (tileType.ChangeBlockDir || pos.growth is GrowSystemTreeSingle)RenderRow
pref = sources.cards.map[aliasPref].pref;
}
}
if (pref == null)
{
pref = new SourcePref();
}
if (!this.renderData.initialized)
{
this.renderData.Init(); {
useAltColor = true;
}
DefaultMaterial = sources.materials.alias[defMat.IsEmpty("granite")];
Dictionary<string, SourceMaterial.Row> alias = sources.materials.alias;
if (!alias.TryGetValue(defMat.IsEmpty("granite"), out var defaultMaterial))
{
defaultMaterial = alias["granite"];
Debug.LogError($"#source failed to set def mat '{defMat}' - {ModUtil.FindSourceRowPackage(this)}");
}
DefaultMaterial = defaultMaterial;
}
public virtual void SetTiles()Scene
public void Init(Mode newMode)
EMono.ui.RemoveLayers();
BuildMenu.Deactivate();
ScreenFlash.Reset();
BaseModManager.PublishEvent("elin.scene.pre_init", newMode);
mode = newMode;
switch (newMode)
{public void Init(Mode newMode)
}
etherBlossom.SetActive(mode == Mode.Zone && EMono._zone is Zone_WindRest);
bubble.SetActive(mode == Mode.Zone && EMono._zone.IsUnderwater);
BaseModManager.PublishEvent("elin.scene.post_init", newMode);
}
public void OnKillGame()SourceCard
using System;
using System.Collections.Generic;
using UnityEngine;public class SourceCard : EClass
public void Init()
{
rows.Clear();
map.Clear();
firstVariations.Clear();
crafters.Clear();
foreach (SourceThing.Row row in EClass.sources.things.rows)
{
AddRow(row);public void AddRow(CardRow row, bool isChara = false)
}
row.origin.isOrigin = true;
}
row.SetRenderData();
rows.Add(row);
map[row.id] = row;
try
{
row.SetRenderData();
rows.Add(row);
map[row.id] = row;
}
catch (Exception arg2)
{
ModPackage arg = ModUtil.FindSourceRowPackage(row);
Debug.LogError($"#source failed to set render data for '{row.id}' - {arg}\n{arg2}");
}
}
}SourceChara
public override string GetAlias => "n";
public SourceRace.Row race_row => _race_row ?? (_race_row = base.sources.races.map[race]);
public SourceRace.Row race_row
{
get
{
SourceRace.Row row = _race_row;
if (row == null)
{
SourceRace.Row obj = base.sources.races.map.TryGetValue(race) ?? base.sources.races.map["norland"];
SourceRace.Row row2 = obj;
_race_row = obj;
row = row2;
}
return row;
}
}
public override string RecipeID => id;SourceElement
public bool IsEncAppliable(SourceCategory.Row cat)
[NonSerialized]
public List<Row> hobbies = new List<Row>();
[NonSerialized]
public Dictionary<string, string> fuzzyAlias = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public override string[] ImportFields => new string[8] { "altname", "textPhase", "textExtra", "textInc", "textDec", "textAlt", "adjective", "levelBonus" };
public override Row CreateRow()public override void SetRow(Row r)
public override void OnInit()
{
hobbies.Clear();
foreach (Row row in rows)
{
if (row.id >= 100 && row.id < 400) row.isSpell = row.categorySub == "spell";
row.isTrait = row.tag.Contains("trait");
}
fuzzyAlias.Clear();
foreach (string key in alias.Keys)
{
fuzzyAlias[key] = key;
}
}
public override void OnAfterImportData()public override void OnAfterImportData()
public void AddRow(Row ele, int id, string idOrg)
{
if (Application.isEditor || !map.ContainsKey(id))
if (map.ContainsKey(id))
{
Row row = EClass.sources.elements.alias[idOrg];
System.Reflection.FieldInfo[] fields = row.GetType().GetFields();
Row row2 = new Row();
System.Reflection.FieldInfo[] array = fields;
foreach (System.Reflection.FieldInfo fieldInfo in array)
{
row2.SetField(fieldInfo.Name, row.GetField<object>(fieldInfo.Name));
}
row2.id = id;
row2.idMold = row.id;
row2.alias = row.alias + ele.alias.Remove(0, 3);
row2.aliasRef = ele.alias;
row2.aliasParent = ele.aliasParent;
row2.chance = row.chance * ele.chance / 100;
row2.LV = row.LV;
row2.OnImportData(EClass.sources.elements);
rows.Add(row2);
return;
}
Row row = EClass.sources.elements.alias[idOrg];
Dictionary<string, System.Reflection.FieldInfo> rowFields = row.GetRowFields();
Row row2 = new Row();
foreach (System.Reflection.FieldInfo value in rowFields.Values)
{
value.SetValue(row2, value.GetValue(row));
}
row2.id = id;
row2.idMold = row.id;
row2.alias = row.alias + ele.alias.Remove(0, 3);
row2.aliasRef = ele.alias;
row2.aliasParent = ele.aliasParent;
row2.chance = row.chance * ele.chance / 100;
row2.LV = row.LV;
row2.OnImportData(EClass.sources.elements);
rows.Add(row2);
}
}+SourceImporter
File Created
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using UnityEngine;
public class SourceImporter : EClass
{
private readonly IReadOnlyDictionary<string, SourceData> _sourceMapping;
public Dictionary<string, EMod> fileProviders = new Dictionary<string, EMod>(PathComparer.Default);
public SourceImporter(IReadOnlyDictionary<string, SourceData> sourceMapping)
{
_sourceMapping = sourceMapping;
}
public SourceData FindSourceByName(string name)
{
string[] array = new string[3]
{
"Source" + name,
"Lang" + name,
name
};
foreach (string key in array)
{
if (_sourceMapping.TryGetValue(key, out var value))
{
return value;
}
}
return null;
}
private (SourceData, SourceData.BaseRow[]) LoadBySheetName(ISheet sheet, string file)
{
string sheetName = sheet.SheetName;
try
{
SourceData sourceData = FindSourceByName(sheetName);
if ((object)sourceData == null)
{
Debug.Log("#source skipping sheet " + sheetName);
return (null, null);
}
IList list;
if (!(sourceData is SourceThingV))
{
list = sourceData.GetField<IList>("rows");
}
else
{
IList rows = EClass.sources.things.rows;
list = rows;
}
IList list2 = list;
int count = list2.Count;
Debug.Log("#source loading sheet " + sheetName);
ExcelParser.path = file;
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
if (!sourceData.ImportData(sheet, fileNameWithoutExtension, overwrite: true))
{
throw new SourceParseException("#source failed to import data " + sourceData.GetType().Name + ":" + fileNameWithoutExtension + "/" + sheetName);
}
SourceData.BaseRow[] item = Array.Empty<SourceData.BaseRow>();
int num = ERROR.msg.Split('/')[^1].ToInt();
if (num > 0)
{
item = list2.OfType<SourceData.BaseRow>().Skip(count).Take(num)
.ToArray();
}
return (sourceData, item);
}
catch (Exception arg)
{
Debug.LogError($"#source failed to load sheet {sheetName}\n{arg}");
}
return (null, null);
}
public IEnumerable<SourceData> ImportFilesCached(IEnumerable<string> imports, bool resetData = true)
{
SourceCache[] array = imports.Select(SourceCache.GetOrCreate).Distinct().ToArray();
Dictionary<SourceCache, (string, ISheet[], ISheet)> dictionary = (from c in array
where c.IsDirtyOrEmpty
select PrefetchWorkbook(c.SheetFile.FullName)).ToArray().ToDictionary(((string file, ISheet[] sheets, ISheet element) p) => SourceCache.GetOrCreate(p.file));
SourceElement elements = EClass.sources.elements;
HashSet<SourceData> hashSet = new HashSet<SourceData> { elements };
SourceCache[] array2 = array;
foreach (SourceCache sourceCache in array2)
{
string arg = sourceCache.SheetFile.ShortPath();
if (fileProviders.TryGetValue(sourceCache.SheetFile.FullName, out var value))
{
sourceCache.SetMod(value);
}
SourceData.BaseRow[] rows;
if (sourceCache.IsDirtyOrEmpty)
{
if (dictionary.TryGetValue(sourceCache, out var value2) && value2.Item3 != null)
{
SourceData.BaseRow[] item = LoadBySheetName(value2.Item3, value2.Item1).Item2;
sourceCache.EmplaceCache("Element", item);
value?.sourceRows.UnionWith(item);
Debug.Log(string.Format("#source workbook {0}:{1}:{2}", arg, "Element", item.Length));
}
}
else if (sourceCache.TryGetCache("Element", out rows))
{
int num = elements.ImportRows(rows);
value?.sourceRows.UnionWith(rows);
Debug.Log(string.Format("#source workbook-cache {0}:{1}:{2}", arg, "Element", num));
}
}
array2 = array;
foreach (SourceCache sourceCache2 in array2)
{
string text = sourceCache2.SheetFile.ShortPath();
if (sourceCache2.IsDirtyOrEmpty)
{
if (!dictionary.TryGetValue(sourceCache2, out var value3) || value3.Item2.Length == 0)
{
continue;
}
Debug.Log("#source workbook " + text);
ISheet[] item2 = value3.Item2;
foreach (ISheet sheet in item2)
{
if (sheet.SheetName == "Element")
{
continue;
}
var (sourceData, array3) = LoadBySheetName(sheet, value3.Item1);
if ((object)sourceData != null)
{
int? num2 = array3?.Length;
if (num2.HasValue && num2.GetValueOrDefault() > 0)
{
sourceCache2.EmplaceCache(sheet.SheetName, array3);
sourceCache2.Mod?.sourceRows.UnionWith(array3);
hashSet.Add(sourceData);
}
}
}
continue;
}
foreach (KeyValuePair<string, SourceData.BaseRow[]> item3 in sourceCache2.Source)
{
item3.Deconstruct(out var key, out var value4);
string text2 = key;
SourceData.BaseRow[] array4 = value4;
SourceData sourceData2 = FindSourceByName(text2);
if (!(sourceData2 is SourceThingV))
{
if (sourceData2 is SourceElement || (object)sourceData2 == null)
{
continue;
}
}
else
{
sourceData2 = EClass.sources.things;
}
if (array4 == null)
{
Debug.Log("#source cached rows are empty " + text + ":" + text2);
continue;
}
int num3 = sourceData2.ImportRows(array4);
sourceCache2.Mod?.sourceRows.UnionWith(array4);
Debug.Log($"#source workbook-cache {text}:{text2}:{num3}");
hashSet.Add(sourceData2);
}
}
SourceCache.FinalizeCache();
SourceCache.ClearDetail();
if (resetData)
{
HotInit(hashSet);
}
return hashSet;
}
public static void HotInit(IEnumerable<SourceData> sourceData)
{
Debug.Log("#source resetting data...");
foreach (SourceData sourceDatum in sourceData)
{
try
{
sourceDatum.Reset();
sourceDatum.Init();
}
catch (Exception arg)
{
Debug.LogError($"#source failed to reset dirty data {sourceDatum.GetType().Name}\n{arg}");
}
}
Debug.Log("#source initialized data");
}
private (string file, ISheet[] sheets, ISheet element) PrefetchWorkbook(string file)
{
using FileStream @is = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
XSSFWorkbook xSSFWorkbook = new XSSFWorkbook((Stream)@is);
List<ISheet> list = new List<ISheet>();
ISheet item = null;
for (int i = 0; i < xSSFWorkbook.NumberOfSheets; i++)
{
ISheet sheetAt = xSSFWorkbook.GetSheetAt(i);
SourceData sourceData = FindSourceByName(sheetAt.SheetName);
if (!(sourceData is SourceElement))
{
if ((object)sourceData != null)
{
list.Add(sheetAt);
}
}
else
{
item = sheetAt;
}
}
Debug.Log("#source workbook-prefetch " + file.ShortPath());
return (file: file, sheets: list.ToArray(), element: item);
}
}SourceManager
using System.Collections.Generic;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class SourceManager : EMono
{
public void Init()
{
Debug.Log("SourceManager Init");
if (initialized)
{
return; list.Add((SourceData)fieldInfo.GetValue(this));
}
}
BaseModManager.PublishEvent("elin.source.importing");
if (ModManagerCore.enableSheetLoading)
{
ModManager.Instance.ImportAllModSourceSheets();
}
elements.Init();
materials.Init();
charas.Init(); keyItems.Init();
ACT.Init();
TimeTable.Init();
Element.ListAttackElements.Clear();
List<SourceElement.Row> listAttackElements = Element.ListAttackElements;
listAttackElements.Clear();
for (int j = 910; j < 927; j++)
{
Element.ListAttackElements.Add(EMono.sources.elements.map[j]);
listAttackElements.Add(EMono.sources.elements.map[j]);
}
BaseModManager.PublishEvent("elin.source.imported");
}
public void Reload()
{
initialized = false;
foreach (SourceData item in list)
{
item.Reset();
}
Init();
}
public void ExportSourceTexts(string path)SourceMaterial
public override void OnImportData(SourceData data)
public void Init()
{
MatColors matColors = Core.Instance.Colors.matColors.TryGetValue(alias);
if (matColors == null)
{
matColors = new MatColors();
string[] array = tag;
foreach (string text in array)
{
if (text.StartsWith("addCol"))
{
if (text.Contains("_Main"))
{
matColors.main = text.ExtractInBetween('(', ')').ToColor();
}
if (text.Contains("_Alt"))
{
matColors.alt = text.ExtractInBetween('(', ')').ToColor();
}
}
}
}
matColor = matColors.main;
altColor = matColors.alt;
SetTiles();SourceThingV
public override void OnAfterImportData()
{
dictionary[row2.id] = row2;
}
System.Reflection.FieldInfo[] fields = EClass.sources.things.rows[0].GetType().GetFields();
Dictionary<string, System.Reflection.FieldInfo> rowFields = new SourceThing.Row().GetRowFields();
foreach (Row row3 in rows)
{
SourceThing.Row row = new SourceThing.Row();
SourceThing.Row o = dictionary[row3._origin];
System.Reflection.FieldInfo[] array = fields;
foreach (System.Reflection.FieldInfo fieldInfo in array)
SourceThing.Row obj = dictionary[row3._origin];
string key;
foreach (KeyValuePair<string, System.Reflection.FieldInfo> item in rowFields)
{
if (!(fieldInfo.Name == "parse"))
item.Deconstruct(out key, out var value);
string text = key;
System.Reflection.FieldInfo fieldInfo = value;
if (!(text == "parse"))
{
row.SetField(fieldInfo.Name, o.GetField<object>(fieldInfo.Name));
fieldInfo.SetValue(row, fieldInfo.GetValue(obj));
}
}
row.id = row3.id;public override void OnAfterImportData()
row.recipeKey = row3.recipeKey;
if (!row3.parse.IsEmpty())
{
switch (row3._origin)
key = row3._origin;
switch (key)
{
case "lamp_ceil2":
case "window":public override void OnAfterImportData()
string[] parse = row3.parse;
for (int i = 0; i < parse.Length; i++)
{
string[] array2 = parse[i].Split('/');
switch (array2[0])
string[] array = parse[i].Split('/');
switch (array[0])
{
case "elec":
row.electricity = array2[1].ToInt();
row.electricity = array[1].ToInt();
break;
case "render":
row._idRenderData = array2[1];
row._idRenderData = array[1];
break;
case "tiletype":
row._tileType = array2[1];
row._tileType = array[1];
break;
case "anime":
row.anime = ((array2.Length <= 4) ? ((array2.Length <= 3) ? new int[2]
row.anime = ((array.Length <= 4) ? ((array.Length <= 3) ? new int[2]
{
array2[1].ToInt(),
array2[2].ToInt()
array[1].ToInt(),
array[2].ToInt()
} : new int[3]
{
array2[1].ToInt(),
array2[2].ToInt(),
array2[3].ToInt()
array[1].ToInt(),
array[2].ToInt(),
array[3].ToInt()
}) : new int[4]
{
array2[1].ToInt(),
array2[2].ToInt(),
array2[3].ToInt(),
array2[4].ToInt()
array[1].ToInt(),
array[2].ToInt(),
array[3].ToInt(),
array[4].ToInt()
});
break;
case "skin":
{
string[] array3 = array2[1].Split('|');
row.skins = new int[array3.Length];
for (int j = 0; j < array3.Length; j++)
string[] array2 = array[1].Split('|');
row.skins = new int[array2.Length];
for (int j = 0; j < array2.Length; j++)
{
row.skins[j] = array3[j].ToInt();
row.skins[j] = array2[j].ToInt();
}
break;
}
case "alt":
row.altTiles = new int[1] { array2[1].ToInt() };
row.altTiles = new int[1] { array[1].ToInt() };
row.ignoreAltFix = true;
break;
case "naming":
row.naming = array2[1];
row.naming = array[1];
break;
case "ex":
row.idActorEx = array2[1];
row.idActorEx = array[1];
break;
case "sound":
row.idSound = array2[1];
row.idSound = array[1];
break;
case "color":
row.colorMod = 100;public override void OnAfterImportData()
{
int[] second = new int[2]
{
Core.GetCurrent().sources.elements.alias[array2[1]].id,
array2[2].ToInt()
Core.GetCurrent().sources.elements.alias[array[1]].id,
array[2].ToInt()
};
row.elements = row.elements.Concat(second).ToArray();
break;Steam
public static bool HasDLC(ID_DLC id)
public static void GetAchievement(ID_Achievement id)
{
if (BaseCore.IsOffline)
{
return;
}
try
{
foreach (AchievementObject achievement in Instance.steamworks.settings.achievements)public static void GetAchievement(ID_Achievement id)
try
{
achievement.Unlock();
achievement.Store();
EClass.ui.Say("sys_acv".lang(achievement.Name), Resources.Load<Sprite>("Media/Graphics/Icon/Achievement/acv_" + id));
SE.Play("achievement");
achievement.Store();
return;
}
catch (Exception ex)TCText
public void Say(string s, float duration = 0f)
{
if (s.IsEmpty())
{
return;
}
PopItem p;
switch (s[0])
{TaskDig
public override void OnProgressComplete()
switch (mode)
{
case Mode.Default:
EClass._map.SetBridge(pos.x, pos.z);
EClass._map.SetBridge(pos.x, pos.z, 0, 0, 0, 0, 0);
break;
case Mode.RemoveFloor:
EClass._map.MineFloor(pos, owner);+TraitDeedLostRing
File Created
public class TraitDeedLostRing : TraitTool
{
public override void TrySetHeldAct(ActPlan p)
{
p.pos.ListCharas().ForEach(delegate(Chara a)
{
if (a.IsMarried)
{
p.TrySetAct("actReissue", delegate
{
EClass.pc.Say("use_whip", a, owner);
a.Talk("death_other");
EClass.pc.PlaySound("whip");
a.PlayAnime(AnimeID.Shiver);
a.PlaySound("dropRewardXmas");
owner.ModNum(-1);
Thing thing = ThingGen.Create("amulet_engagement");
thing.Attune(a);
thing.elements.ModBase(484, 3);
if (thing.rarity < Rarity.Mythical)
{
thing.rarity = Rarity.Mythical;
}
EClass.player.DropReward(thing, silent: true);
thing = ThingGen.Create("ring_engagement");
thing.Attune(a);
thing.elements.ModBase(484, 3);
if (thing.rarity < Rarity.Mythical)
{
thing.rarity = Rarity.Mythical;
}
EClass.player.DropReward(thing);
return false;
}, a);
}
});
}
}TraitFigure
public class TraitFigure : Trait
{
public CardRenderer extraRenderer;
public override bool CanBeHallucinated => false;
public CardRow source => EClass.sources.cards.map.TryGetValue(owner.c_idRefCard);