Skip to content

EA 23.343 Nightly โ€‹

September 5, 2026

13 files modified.

Important Changes โ€‹

Possible breaking changes. Click the filename to view the chunk.

LayerMod (1) โ€‹

cs
private void Move(BaseModPackage p, ItemMod b, int a) 
private void Move(BaseModPackage p, int a) 

ModManager (4) โ€‹

cs
public IEnumerator LoadWorkshopPackages() 
public void InitPackagesMeta() 
cs
private IEnumerator UpdateWorkshopPackages() 
private string UnmetDependency(BaseModPackage p, Dictionary<string, BaseModPackage> loaded, Dictionary<string, BaseModPackage> installed) 
cs
public void InitPackagesMeta() 
private static void RegisterLoaded(BaseModPackage p, Dictionary<string, BaseModPackage> loaded, Dictionary<string, BaseModPackage> claimed) 
cs
public void ActivatePackages() 
private IEnumerator QuerySubscriptions(PublishedFileId_t[] subscribed) 

ActEffect โ€‹

void AddCon<T>(int rate, int p2) where T : Condition

cs
{
	num14 = num15;
}
Debug.Log(num14); 
if (EClass.rnd(100) > num14)
{
	TC.Say("debuff_resist", TC);

Card โ€‹

public Card SetLv(int a)

cs
{
	return this;
}
if (!isScaled && flag && LV >= 50) 
if (LV >= Mathf.Max(50, sourceCard.LV)) 
{
	isScaled = true;
}

Chara โ€‹

public override string GetName(NameStyle style, int num = -1)

cs
{
	num2 = 1;
}
text = (Aka.IsEmpty() ? text.Bracket(num2) : (num2 switch
text = ((Aka.IsEmpty() || !(Aka != text)) ? text.Bracket(num2) : (num2 switch
{
	-1 => "_aka", 
	1 => "_aka3",

public void TickConditions()

cs
	{
		preventRegen = true;
	}
	if (!preventRegen) 
	if (preventRegen) 
	{
		if (EClass.rnd(25) == 0 && base.hp < MaxHP) 
		{ 
			HealHP(EClass.rnd(Evalue(300) / 3 + 1) + 1); 
			elements.ModExp(300, 8f); 
		} 
		if (EClass.rnd(8) == 0 && mana.value < mana.max) 
		{ 
			mana.Mod(EClass.rnd(Evalue(301) / 2 + 1) + 1); 
			elements.ModExp(301, 8f); 
		} 
		if (EClass.rnd(20) == 0 && !IsPC && stamina.value < stamina.max) 
		return; 
	} 
	if (EClass.rnd(25) == 0 && base.hp < MaxHP) 
	{ 
		HealHP(EClass.rnd(Evalue(300) / 3 + 1) + 1); 
		elements.ModExp(300, 8f); 
	} 
	if (EClass.rnd(8) == 0 && mana.value < mana.max) 
	{ 
		mana.Mod(EClass.rnd(Evalue(301) / 2 + 1) + 1); 
		elements.ModExp(301, 8f); 
	} 
	if (EClass.rnd(20) != 0) 
	{ 
		return; 
	} 
	if (IsPC) 
	{ 
		if (EClass.player.staminaRecovery > 0) 
		{
			stamina.Mod(EClass.rnd(5) + 1); 
			EClass.player.RecoverStamina(Evalue(62) / 100 + ((Evalue(62) % 100 > EClass.rnd(100)) ? 1 : 0)); 
		}
	}
	else if (stamina.value < stamina.max) 
	{ 
		stamina.Mod(EClass.rnd(5) + 1); 
	} 
}

public void SyncRide()

public override void Die(Element e = null, Card origin = null, AttackSource attaโ€ฆ)

cs
}
if (IsPC)
{
	EClass.player.staminaRecovery = 0; 
	EClass._zone.isDeathLocation = true;
	string s = ((origin == null) ? text : "dead_by");
	Msg.thirdPerson1.Set(EClass.pc);

public bool UseAbility(Act a, Card tc = null, Point pos = null, bool pt = false)

cs
	elements.ModExp(304, Mathf.Clamp(num6 * 2, 1, 200));
	break;
case Act.CostType.SP:
{ 
	int value = stamina.value; 
	stamina.Mod(-num6);
	if (IsPC && a.HasTag("recovery")) 
	{ 
		EClass.player.staminaRecovery += value - stamina.value; 
	} 
	ignoreSPAbsorb = true;
	break;
}
} 
if (a is Spell && GetCondition<ConSilence>() != null)
{
	Say("cast_silence", this);

public Condition AddCondition(Condition c, bool force = false)

cs
Element defenseAttribute = c.GetDefenseAttribute(this);
if (defenseAttribute != null)
{
	c.power = 100 * c.power / Mathf.Max(100 + defenseAttribute.Value, 1); 
	c.power = MathEx.ClampToInt(100L * (long)c.power / Mathf.Max(100 + defenseAttribute.Value, 1)); 
}
if (c.source.resistance.Length != 0)
{

public void OnSleep(int power, int days = 1, bool isSunLit = false)

cs
}
if (IsPC)
{
	EClass.player.RecoverStamina(EClass.player.staminaRecovery); 
	foreach (BodySlot slot in body.slots)
	{
		if (slot.thing != null) 
		if (slot.thing != null && slot.thing.GetBool(135)) 
		{
			LayerInventory.SetDirty(slot.thing); 
			slot.thing.SetBool(135, enable: false);
		}
	}

CharaBody โ€‹

public bool Equip(Thing thing, BodySlot slot = null, bool msg = true)

cs
thing.c_DNA.Apply(owner, reverse: false);
Msg.Say("equip_relic");
owner.feat -= thing.c_DNA.cost;
if (!EClass.debug.enable) 
if (!EClass.debug.godMode) 
{
	thing.SetBool(135, enable: true);
}

ELEMENT โ€‹

public void _WriteNote(UINote n, Chara c, Act act)

cs
{
	n.AddText("_bullet".lang() + "hintSyncRide".lang());
}
if (EClass.pc.HasElement(1274) && source.tag.Contains("dontForget")) 
if (source.tag.Contains("recovery")) 
{ 
	n.AddText("_bullet".lang() + "hintStaminaRecovery".lang()); 
} 
if (source.tag.Contains("dontForget")) 
{
	n.AddText("_bullet".lang() + "hintDontForget".lang());
}

ElinGameIOPropertyAttribute โ€‹

public override void Register(PropertyInfo property)

cs
	}
	MethodInfo getMethod = property.GetMethod;
	MethodInfo setMethod = property.SetMethod;
	if (!(getMethod == null) && !(setMethod == null) && setMethod.IsStatic) 
	if (!(getMethod == null) && !(setMethod == null) && getMethod.IsStatic && setMethod.IsStatic) 
	{
		Func<object> item = getMethod.CreateDelegate<Func<object>>(); 
		Func<object> item = CreateGetterDelegate(getMethod); 
		Action<object> item2 = CreateSetterDelegate(setMethod);
		Type declaringType = property.DeclaringType;
		_contextVars[declaringType.FullName + ":" + ChunkName] = (property, item, item2);
	}
}

private static Func<object> CreateGetterDelegate(MethodInfo method) 
{ 
	return Expression.Lambda<Func<object>>(Expression.Convert(Expression.Call(method), typeof(object)), Array.Empty<ParameterExpression>()).Compile(); 
} 
private static Action<object> CreateSetterDelegate(MethodInfo method)
{
	Type parameterType = method.GetParameters()[0].ParameterType;

private static void LoadGameIOProperty(GameIOContext context)

cs
	}
	static object CoerceValue(object obj, Type type)
	{
		if (obj == null) 
		{ 
			return type.IsValueType ? Activator.CreateInstance(type) : null; 
		} 
		if (obj is JToken jToken)
		{
			return jToken.ToObject(type);
		}
		if (type.IsInstanceOfType(obj)) 
		{ 
			return obj; 
		} 
		if (obj is IConvertible) 
		if (obj == null) 
		{
			return Convert.ChangeType(obj, type); 
			return type.IsValueType ? Activator.CreateInstance(type) : null; 
		}
		return obj; 
		object result; 
		return DynamicReflection.TryCoerce(obj, type, out result) ? result : obj; 
	}
}

LayerMod โ€‹

using System;

cs
using System; 
using System.Collections.Generic;
using System.IO;
using System.Linq; 
using System.Text; 
using HeathenEngineering.SteamworksIntegration; 
using UnityEngine; 
using UnityEngine.EventSystems; 
using UnityEngine.UI; 

public class LayerMod : ELayer
{
	private sealed class PreviewEntry
	{ 
		public Sprite sprite; 
		public bool ownsTexture; 
		public ModPreview.PreviewType kind; 
	} 
	private sealed class HoverRelay : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler
	{ 
		public Action onEnter; 
		public void OnPointerEnter(PointerEventData eventData) 
		{ 
			onEnter?.Invoke(); 
		} 
	} 
	private const float previewBoxHeight = 240f; 
	private const string urlWorkshopItem = "https://steamcommunity.com/sharedfiles/filedetails/?id="; 
	public static LayerMod Instance;

	public UIList list;

public class LayerMod : ELayer

cs
public UIText textRestart;

public UIText textNoResult; 
public UIButton toggleDisableMods;

public UIButton buttonClearSearch; 
public InputField inputSearch; 
public UIScrollView panelScroll; 
public UIHeader panelHeader; 
public UINote panelNote; 
private UIButton buttonFilter; 
private BaseModPackage panelTarget; 
private float timerSearch; 
private bool wasSearchFocused; 
private string lastSearch = ""; 
private string[] searchTerms = Array.Empty<string>(); 
private ModSearch.Filter filterMode; 
private readonly Dictionary<BaseModPackage, string> searchCache = new Dictionary<BaseModPackage, string>(); 
private readonly Dictionary<BaseModPackage, PreviewEntry> previews = new Dictionary<BaseModPackage, PreviewEntry>(); 
public ModManager manager => ELayer.core.mods;

private void Move(BaseModPackage p, ItemMod b, int a) 
public bool HasFilter 
{ 
	get 
	{ 
		if (searchTerms.Length == 0) 
		{ 
			return filterMode != ModSearch.Filter.All; 
		} 
		return true; 
	} 
} 
private void Move(BaseModPackage p, int a) 
{ 
	List<object> items = list.items; 
	int num = items.IndexOf(p); 
	if (num < 0 || num + a < 0 || num + a >= items.Count) 
	{ 
		SE.BeepSmall(); 
	} 
	else
	{ 
		MoveTo(p, items[num + a] as BaseModPackage); 
	} 
} 
private void MoveTo(BaseModPackage p, BaseModPackage target) 
{
	List<BaseModPackage> packages = ELayer.core.mods.packages; 
	List<BaseModPackage> packages = manager.packages; 
	int num = packages.IndexOf(p);
	if (num + a < 0 || num + a >= packages.Count || packages[num + a].builtin) 
	int num2 = ((target == null) ? (-1) : packages.IndexOf(target)); 
	if (num < 0 || num2 < 0 || num == num2 || target.builtin) 
	{
		SE.BeepSmall();
		return;
	}
	packages.Move(p, a); 
	packages.Move(p, num2 - num); 
	SE.Tab();
	textRestart.SetActive(enable: true);
	ELayer.core.mods.SaveLoadOrder();
	RefreshLists(); 
} 
public void RefreshLists() 
{ 
	list.List();
	list2.List(); 
	if ((bool)textNoResult) 
	{ 
		textNoResult.SetActive(HasFilter && list.items.Count == 0); 
	} 
}

public override void OnInit()

public override void OnInit()

cs
		textRestart.SetActive(enable: true);
	});
	Instance = this;
	foreach (BaseModPackage package in manager.packages) 
	{ 
		package.UpdateMeta(updateOnly: true); 
		searchCache[package] = ModSearch.BuildText(package); 
	} 
	list.dragScrollView = GetComponentInChildren<UIScrollView>();
	list.dragViewport = windows[0].Rect();
	list.dragEdgeSize = 34f; 
	UIList uIList = list; 
	UIList uIList2 = list2; 
	UIList.Callback<ModPackage, ItemMod> obj = new UIList.Callback<ModPackage, ItemMod> 
	list.callbacks = CreateCallbacks(list, builtin: false); 
	list2.callbacks = CreateCallbacks(list2, builtin: true); 
	InitSearchUI(); 
	CreatePresetUI(); 
	panelHeader.SetText("info".lang()); 
	RefreshLists(); 
	ShowInfo(FirstInfoTarget()); 
	list.dragEdgeSize = list.callbacks.GetMold()?.Rect().sizeDelta.y ?? 34f; 
} 
private UIList.Callback<ModPackage, ItemMod> CreateCallbacks(UIList target, bool builtin) 
{ 
	return new UIList.Callback<ModPackage, ItemMod> 
	{
		onClick = delegate
		{
		},
		onInstantiate = delegate(ModPackage a, ItemMod b)
		{
			a.UpdateMeta(updateOnly: true); 
			b.package = a;
			string s = ELayer.core.mods.packages.IndexOf(a) + 1 + ". " + (a.isInPackages ? "[Local] " : "") + a.title; 
			b.buttonActivate.mainText.SetText(s, (!a.IsValidVersion()) ? FontColor.Bad : (a.activated ? FontColor.ButtonGeneral : FontColor.Passive)); 
			string s = ELayer.core.mods.packages.IndexOf(a) + 1 + ". " + (a.isInPackages ? "[Local] " : "") + a.title.IsEmpty(a.dirInfo.Name); 
			b.buttonActivate.mainText.SetText(s, (!a.IsValidVersion() || a.blockedBy != null || !a.langDepError.IsEmpty()) ? FontColor.Bad : (a.activated ? FontColor.ButtonGeneral : FontColor.Passive)); 
			b.buttonActivate.subText.text = a.version;
			b.buttonLock.mainText.text = a.author;
			b.buttonUp.SetActive(!a.builtin);

public override void OnInit()

cs
b.buttonToggle.SetToggle(a.willActivate);
b.buttonUp.SetOnClick(delegate
{
	Move(a, b, -1); 
	Move(a, -1); 
});
b.buttonDown.SetOnClick(delegate
{
	Move(a, b, 1); 
	Move(a, 1); 
});
(b.buttonActivate.GetComponent<HoverRelay>() ?? b.buttonActivate.gameObject.AddComponent<HoverRelay>()).onEnter = delegate
{ 
	ShowInfo(a); 
}; 
UIButton bt = b.buttonToggle;
bt.SetOnClick(delegate
{

public override void OnInit()

cs
{
	Refresh();
	UIContextMenu uIContextMenu = ELayer.ui.CreateContextMenuInteraction();
	if (ELayer.debug.enable || (!BaseCore.IsOffline && a.isInPackages && !a.builtin && !ELayer.core.version.demo)) 
	if (!a.builtin) 
	{
		uIContextMenu.AddButton("mod_publish", delegate
		if (ELayer.debug.enable || (!BaseCore.IsOffline && a.isInPackages && !ELayer.core.version.demo)) 
		{
			Core.TryWarnUpload(delegate
			uIContextMenu.AddButton("mod_publish", delegate 
			{
				Dialog.YesNo("mod_publish_warn".lang(a.title, a.id, a.author), delegate
				Core.TryWarnUpload(delegate 
				{
					ELayer.core.steam.CreateUserContent(a); 
					Dialog.YesNo("mod_publish_warn".lang(a.title, a.id, a.author), delegate
					{ 
						ELayer.core.steam.CreateUserContent(a); 
					}); 
				});
			});
		}); 
	} 
	if (!a.builtin) 
	{ 
		} 
		uIContextMenu.AddButton(a.willActivate ? "mod_deactivate" : "mod_activate", delegate
		{
			SE.Click();
			a.willActivate = !a.willActivate;
			ELayer.core.mods.SaveLoadOrder();
			list.List(); 
			RefreshLists(); 
			textRestart.SetActive(enable: true);
		});
		if (!a.isInPackages && !a.workshopId.IsEmpty())

public override void OnInit()

cs
		string text = Path.Combine(BaseModManager.rootMod, path);
		a.CopyContentTo(text);
		ModPackage modPackage = manager.AddPackage(new DirectoryInfo(text), isInPackages: true);
		modPackage.UpdateMeta(updateOnly: true); 
		searchCache[modPackage] = ModSearch.BuildText(modPackage); 
		manager.packages.Move(modPackage, manager.packages.IndexOf(a) - manager.packages.Count + 2);
		modPackage.willActivate = false;
		modPackage.activated = false;
		ELayer.core.mods.SaveLoadOrder();
		list.List(); 
		RefreshLists(); 
		textRestart.SetActive(enable: true);
	});
}

public override void OnInit()

cs
			});
		}
	}
	if (ModPreview.FindPreviewFile(a) != null || (bool)SteamPreview(a)) 
	{ 
		uIContextMenu.AddButton("mod_preview", delegate
		{ 
			ShowPreview(a); 
		}); 
	} 
	if (!a.workshopId.IsEmpty()) 
	{ 
		uIContextMenu.AddButton("mod_info_workshop", delegate
		{ 
			SE.Click(); 
			Application.OpenURL("https://steamcommunity.com/sharedfiles/filedetails/?id=" + a.workshopId.Trim()); 
		}); 
	} 
	uIContextMenu.AddButton("mod_info", delegate
	{
		SE.Click();
		Util.ShowExplorer(a.dirInfo.FullName + "/package.xml"); 
		if (!a.dirInfo.Exists) 
		{ 
			SE.BeepSmall(); 
			ELayer.ui.Say(a.dirInfo.FullName); 
		} 
		else
		{ 
			string text = a.dirInfo.FullName + "/package.xml"; 
			Util.ShowExplorer(File.Exists(text) ? text : a.dirInfo.FullName); 
		} 
	});
	uIContextMenu.Show();
});

public override void OnInit()

cs
{
	foreach (BaseModPackage package in manager.packages)
	{
		if (package.builtin) 
		{ 
			list2.Add(package); 
		} 
		else
		if (package.builtin == builtin && (builtin || Match(package))) 
		{
			list.Add(package); 
			target.Add(package); 
		}
	}
},

public override void OnInit()

cs
		onDragReorder = delegate(ModPackage p, int a)
		{
			BaseCore.Instance.FreezeScreen(0.1f);
			manager.packages.Move(p, a); 
			SE.Tab(); 
			textRestart.SetActive(enable: true); 
			ELayer.core.mods.SaveLoadOrder(); 
			list.List(); 
			List<object> items = target.items; 
			int num = items.IndexOf(p); 
			MoveTo(p, items[Mathf.Clamp(num + a, 0, items.Count - 1)] as BaseModPackage); 
		},
		canDragReorder = (ModPackage p) => !p.builtin
	};
	UIList.ICallback callbacks = obj; 
	uIList2.callbacks = obj; 
	uIList.callbacks = callbacks; 
	list.List(); 
	list2.List(); 
} 
private bool Match(BaseModPackage p) 
{ 
	if (!searchCache.TryGetValue(p, out var value)) 
	{ 
		value = (searchCache[p] = ModSearch.BuildText(p)); 
	} 
	return ModSearch.Match(p, value, searchTerms, filterMode); 
} 
private void InitSearchUI() 
{ 
	if ((bool)inputSearch) 
	{ 
		inputSearch.SetTextWithoutNotify(""); 
		if (inputSearch.placeholder is Text text) 
		{ 
			text.text = "mod_search".lang(); 
		} 
		inputSearch.onValueChanged.AddListener(Search); 
		inputSearch.onSubmit.AddListener(Search); 
	} 
	if ((bool)buttonClearSearch) 
	{ 
		buttonClearSearch.SetOnClick(ClearSearchText); 
		buttonClearSearch.SetActive(enable: false); 
	} 
	buttonFilter = windows[0].AddBottomButton("mod_filter", CycleFilter); 
	RefreshFilterButton(); 
	if ((bool)textNoResult) 
	{ 
		textNoResult.SetText("noResult".lang(), FontColor.Passive); 
		textNoResult.SetActive(enable: false); 
	} 
} 
public void Search(string s) 
{ 
	lastSearch = s ?? ""; 
	timerSearch = 0.15f; 
	if ((bool)buttonClearSearch) 
	{ 
		buttonClearSearch.SetActive(!lastSearch.IsEmpty()); 
	} 
} 
private void ClearSearchText() 
{ 
	SE.Click(); 
	if ((bool)inputSearch) 
	{ 
		inputSearch.SetTextWithoutNotify(""); 
	} 
	Search(""); 
} 
public void ClearSearch() 
{ 
	if ((bool)inputSearch) 
	{ 
		inputSearch.SetTextWithoutNotify(""); 
	} 
	if ((bool)buttonClearSearch) 
	{ 
		buttonClearSearch.SetActive(enable: false); 
	} 
	lastSearch = ""; 
	timerSearch = 0f; 
	searchTerms = Array.Empty<string>(); 
	filterMode = ModSearch.Filter.All; 
	RefreshFilterButton(); 
	RefreshLists(); 
} 
private void CycleFilter() 
{ 
	SE.Click(); 
	filterMode = ModSearch.Filters[(int)(filterMode + 1) % ModSearch.Filters.Length]; 
	RefreshFilterButton(); 
	RefreshLists(); 
} 
private void RefreshFilterButton() 
{ 
	if ((bool)buttonFilter) 
	{ 
		buttonFilter.mainText.text = "mod_filter".lang() + ": " + FilterLabel(filterMode).lang(); 
		windows[0].rectBottom.RebuildLayout(recursive: true); 
	} 
} 
private static string FilterLabel(ModSearch.Filter f) 
{ 
	return f switch
	{ 
		ModSearch.Filter.Enabled => "mod_filter_enabled",  
		ModSearch.Filter.Disabled => "mod_filter_disabled",  
		ModSearch.Filter.Problems => "mod_filter_problem",  
		ModSearch.Filter.Local => "mod_filter_local",  
		ModSearch.Filter.Workshop => "mod_filter_workshop",  
		_ => "all",  
	}; 
} 
private void LateUpdate() 
{ 
	if (timerSearch > 0f) 
	{ 
		timerSearch -= Core.delta; 
		if (timerSearch <= 0f) 
		{ 
			timerSearch = 0f; 
			searchTerms = ModSearch.Terms(lastSearch); 
			RefreshLists(); 
		} 
	} 
	if ((bool)inputSearch) 
	{ 
		bool isFocused = inputSearch.isFocused; 
		EventSystem current = EventSystem.current; 
		if (wasSearchFocused && !isFocused && (bool)current && current.currentSelectedGameObject == inputSearch.gameObject) 
		{ 
			current.SetSelectedGameObject(null); 
		} 
		wasSearchFocused = isFocused; 
	} 
} 
private PreviewEntry GetThumb(BaseModPackage p) 
{ 
	if (previews.TryGetValue(p, out var value)) 
	{ 
		return value; 
	} 
	value = new PreviewEntry(); 
	bool owns; 
	Texture2D texture2D = LoadPreviewTexture(p, mipmap: true, out value.kind, out owns); 
	if ((bool)texture2D) 
	{ 
		Texture2D texture2D2 = ModPreview.Downscale(texture2D, 280, owns); 
		value.sprite = texture2D2.ToSprite(); 
		value.ownsTexture = owns || texture2D2 != texture2D; 
	} 
	previews[p] = value; 
	return value; 
} 
private static Texture2D LoadPreviewTexture(BaseModPackage p, bool mipmap, out ModPreview.PreviewType kind, out bool owns) 
{ 
	kind = ModPreview.PreviewType.None; 
	owns = true; 
	FileInfo fileInfo = ModPreview.FindPreviewFile(p); 
	if (fileInfo != null) 
	{ 
		try
		{ 
			Texture2D texture2D = ModPreview.LoadTexture(File.ReadAllBytes(fileInfo.FullName), out kind, mipmap); 
			if ((bool)texture2D) 
			{ 
				return texture2D; 
			} 
		} 
		catch (Exception ex) 
		{ 
			Debug.LogWarning("#mod preview " + fileInfo.FullName + ": " + ex.Message); 
		} 
	} 
	Texture2D texture2D2 = SteamPreview(p); 
	if ((bool)texture2D2) 
	{ 
		owns = false; 
		if (kind == ModPreview.PreviewType.None) 
		{ 
			kind = ModPreview.PreviewType.Jpeg; 
		} 
	} 
	return texture2D2; 
} 
private static Texture2D SteamPreview(BaseModPackage p) 
{ 
	if (!(p.item is WorkshopItem workshopItem) || !workshopItem.previewImage || workshopItem.previewImage.width <= 2) 
	{ 
		return null; 
	} 
	return workshopItem.previewImage; 
} 
private BaseModPackage FirstInfoTarget() 
{ 
	using (List<object>.Enumerator enumerator = list.items.GetEnumerator()) 
	{ 
		if (enumerator.MoveNext()) 
		{ 
			return enumerator.Current as BaseModPackage; 
		} 
	} 
	if (manager.packages.Count <= 0) 
	{ 
		return null; 
	} 
	return manager.packages[0]; 
} 
private void ShowInfo(BaseModPackage p) 
{ 
	if (!panelNote || p == null || p == panelTarget) 
	{ 
		return; 
	} 
	panelTarget = p; 
	UINote n = panelNote; 
	n.Clear(); 
	n.AddHeader(p.title.IsEmpty(p.dirInfo.Name)); 
	PreviewEntry thumb = GetThumb(p); 
	if ((bool)thumb.sprite) 
	{ 
		AddPreviewBox(n, thumb.sprite, delegate
		{ 
			ShowPreview(p); 
		}); 
		if (thumb.kind == ModPreview.PreviewType.Gif) 
		{ 
			n.AddText("mod_preview_gif".lang(), FontColor.Passive); 
		} 
	} 
	else
	{ 
		n.AddText(((thumb.kind == ModPreview.PreviewType.None) ? "mod_preview_none" : "mod_preview_unsupported").lang(), FontColor.Passive); 
	} 
	if (!p.author.IsEmpty()) 
	{ 
		AddTopic("author", p.author); 
	} 
	if (!p.version.IsEmpty()) 
	{ 
		AddTopic("version", p.version); 
	} 
	if (!p.id.IsEmpty()) 
	{ 
		FitValue(AddTopic("mod_info_id", p.id)); 
	} 
	string text = ModLoadOrderPreset.WorkshopId(p); 
	FitValue(AddTopic(text.IsEmpty() ? "mod_filter_local" : "mod_filter_workshop", text.IsEmpty() ? p.dirInfo.Name : text)); 
	if (!p.builtin && !p.willActivate) 
	{ 
		AddTopic("status", "mod_filter_disabled".lang()); 
	} 
	if (p.blockedBy != null) 
	{ 
		n.AddText("mod_info_blocked".lang(p.blockedBy.title.IsEmpty(p.blockedBy.id)), FontColor.Bad); 
	} 
	if (!p.langDepError.IsEmpty()) 
	{ 
		n.AddText(p.langDepError, FontColor.Bad); 
	} 
	if (p.duplicateOf != null) 
	{ 
		n.AddText("mod_info_duplicate".lang(p.duplicateOf.dirInfo?.Name ?? p.duplicateOf.id), FontColor.Bad); 
	} 
	if (!p.IsValidVersion()) 
	{ 
		n.AddText("mod_info_old_version".lang(p.version, ELayer.core.versionMod.GetText()), FontColor.Bad); 
	} 
	if (!p.parseError.IsEmpty()) 
	{ 
		n.AddText(p.parseError, FontColor.Bad); 
	} 
	string[] tags = p.tags; 
	if (tags != null && tags.Length > 0) 
	{ 
		AddTopic("mod_info_tags", string.Join(", ", p.tags)); 
	} 
	AddIdList(n, "mod_info_requires", p.dependency); 
	AddIdList(n, "incompatible", p.incompatible); 
	AddIdList(n, "mod_info_load_after", p.loadAfter); 
	AddIdList(n, "mod_info_load_before", p.loadBefore); 
	if (!p.description.IsEmpty()) 
	{ 
		n.Space(8); 
		n.AddText(p.description); 
	} 
	n.Build(); 
	panelScroll.content.anchoredPosition = Vector2.zero; 
	UIItem AddTopic(string lang, string value) 
	{ 
		UIItem uIItem = n.AddTopic(lang, value); 
		uIItem.text1.alignment = TextAnchor.LowerLeft; 
		return uIItem; 
	} 
} 
private static void AddPreviewBox(UINote n, Sprite sprite, Action onClick) 
{ 
	n.AddImage(sprite); 
	RectTransform rectTransform = n.transform.GetChild(n.transform.childCount - 1).Rect(); 
	rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, 240f); 
	Image componentInChildren = rectTransform.GetComponentInChildren<Image>(); 
	RectTransform rectTransform2 = componentInChildren.rectTransform; 
	rectTransform2.anchorMin = Vector2.zero; 
	rectTransform2.anchorMax = Vector2.one; 
	rectTransform2.pivot = new Vector2(0.5f, 0.5f); 
	rectTransform2.anchoredPosition = Vector2.zero; 
	rectTransform2.sizeDelta = Vector2.zero; 
	componentInChildren.preserveAspect = true; 
	Button button = componentInChildren.gameObject.AddComponent<Button>(); 
	button.transition = Selectable.Transition.None; 
	button.onClick.AddListener(delegate
	{ 
		onClick(); 
	}); 
} 
private static void FitValue(UIItem item) 
{ 
	if ((bool)item && (bool)item.text2) 
	{ 
		item.text2.resizeTextForBestFit = true; 
		item.text2.horizontalOverflow = HorizontalWrapMode.Wrap; 
		item.text2.resizeTextMinSize = 9; 
		item.text2.resizeTextMaxSize = item.text2.fontSize; 
	} 
} 
private static void AddIdList(UINote n, string lang, string[][] rows) 
{ 
	if (rows != null && rows.Length != 0) 
	{ 
		List<string> list = (from row in rows 
			where row != null && row.Length > 0 && !row[0].IsEmpty() 
			select row[0]).ToList(); 
		if (list.Count > 0) 
		{ 
			n.AddTopic(lang, string.Join(", ", list)).text1.alignment = TextAnchor.LowerLeft; 
		} 
	} 
} 
private void ShowPreview(BaseModPackage a) 
{ 
	SE.Click(); 
	ModPreview.PreviewType kind; 
	bool owns; 
	Texture2D tex = LoadPreviewTexture(a, mipmap: false, out kind, out owns); 
	if (!tex) 
	{ 
		SE.BeepSmall(); 
		ELayer.ui.Say("mod_preview_unsupported"); 
		return; 
	} 
	Sprite image = tex.ToSprite(); 
	LayerImage layerImage = ELayer.ui.AddLayer<LayerImage>(); 
	layerImage.SetImage(image); 
	layerImage.SetOnKill(delegate
	{ 
		UnityEngine.Object.Destroy(tex); 
		if (owns) 
		{ 
			UnityEngine.Object.Destroy(tex); 
		} 
	}); 
} 
private void CreatePresetUI() 
{ 
	windows[0].AddBottomButton("mod_preset", ShowPresetMenu); 
} 
private void ShowPresetMenu() 
{ 
	SE.Click(); 
	if (ModManager.disableMod) 
	{ 
		Dialog.Ok("mod_preset_disabled"); 
		return; 
	} 
	UIContextMenu uIContextMenu = ELayer.ui.CreateContextMenu(); 
	uIContextMenu.AddButton("mod_preset_save", SavePreset); 
	uIContextMenu.AddButton("mod_preset_load", delegate
	{ 
		SelectPreset(ApplyPresetFile); 
	}); 
	uIContextMenu.AddButton("mod_preset_delete", delegate
	{ 
		SelectPreset(DeletePreset); 
	}); 
	uIContextMenu.AddButton("mod_preset_copy", CopyPreset); 
	uIContextMenu.AddButton("mod_preset_paste", PastePreset); 
	uIContextMenu.AddButton("mod_preset_folder", delegate
	{ 
		Directory.CreateDirectory(CorePath.PathLoadOrderPreset); 
		Util.ShowExplorer(CorePath.PathLoadOrderPreset, selectFirstFile: true); 
	}); 
	uIContextMenu.Show(); 
} 
private void SavePreset() 
{ 
	Dialog.InputName("mod_preset_name", "mod_preset_default_name".lang(), delegate(bool cancel, string text) 
	{ 
		if (!cancel) 
		{ 
			string name = (text ?? "").Trim().SanitizeFileName().Trim(); 
			if (name.IsEmpty()) 
			{ 
				SE.BeepSmall(); 
			} 
			else if (File.Exists(ModManager.GetPresetPath(name))) 
			{ 
				Dialog.YesNo("mod_preset_overwrite".lang(name), delegate
				{ 
					WritePreset(name); 
				}); 
			} 
			else
			{ 
				WritePreset(name); 
			} 
		} 
	}); 
} 
private void WritePreset(string name) 
{ 
	if (!manager.SavePreset(name, out var _)) 
	{ 
		SE.BeepSmall(); 
		return; 
	} 
	SE.Click(); 
	ELayer.ui.Say("mod_preset_saved".lang(name)); 
} 
private void SelectPreset(Action<FileInfo> onSelect) 
{ 
	List<FileInfo> files = manager.ListPresets(); 
	if (files.Count == 0) 
	{ 
		Dialog.Ok("mod_preset_none"); 
		return; 
	} 
	Dialog.List("mod_preset_select", files, (FileInfo f) => Path.GetFileNameWithoutExtension(f.Name), delegate(int i, string _) 
	{ 
		onSelect(files[i]); 
		return true; 
	}, canCancel: true); 
} 
private void ApplyPresetFile(FileInfo file) 
{ 
	if (!manager.TryLoadPresetFile(file, out var preset, out var _)) 
	{ 
		Dialog.Ok("mod_preset_invalid"); 
	} 
	else
	{ 
		ConfirmPreset(preset); 
	} 
} 
private void DeletePreset(FileInfo file) 
{ 
	string name = Path.GetFileNameWithoutExtension(file.Name); 
	Dialog.YesNo("mod_preset_delete_confirm".lang(name), delegate
	{ 
		if (file.Exists) 
		{ 
			file.Delete(); 
		} 
		SE.Trash(); 
		ELayer.ui.Say("mod_preset_deleted".lang(name)); 
	}); 
} 
private void CopyPreset() 
{ 
	ModLoadOrderPreset.Preset preset = ModLoadOrderPreset.Save(manager.packages, "", ELayer.core.version.GetText()); 
	if (preset.entries.Count == 0) 
	{ 
		SE.BeepSmall(); 
		return; 
	} 
	GUIUtility.systemCopyBuffer = ModLoadOrderPreset.Serialize(preset); 
	SE.Click(); 
	ELayer.ui.Say("mod_preset_copied"); 
} 
private void PastePreset() 
{ 
	if (!ModLoadOrderPreset.TryParse(GUIUtility.systemCopyBuffer, out var preset, out var _)) 
	{ 
		Dialog.Ok("mod_preset_invalid"); 
		return; 
	} 
	if (preset.name.IsEmpty()) 
	{ 
		preset.name = "mod_preset_default_name".lang(); 
	} 
	ConfirmPreset(preset); 
} 
private void ConfirmPreset(ModLoadOrderPreset.Preset preset) 
{ 
	List<ModLoadOrderPreset.Entry> list = ModLoadOrderPreset.FindMissing(manager.packages, preset); 
	if (list.Count == 0) 
	{ 
		ApplyPreset(preset); 
		return; 
	} 
	Dialog.YesNo("mod_preset_missing".lang(DescribeEntries(list, 15)), delegate
	{ 
		ApplyPreset(preset); 
	}, null, "mod_preset_apply", "cancel"); 
} 
private static string DescribeEntries(List<ModLoadOrderPreset.Entry> entries, int max) 
{ 
	StringBuilder stringBuilder = new StringBuilder(); 
	for (int i = 0; i < entries.Count && i < max; i++) 
	{ 
		ModLoadOrderPreset.Entry entry = entries[i]; 
		stringBuilder.Append(entry.title.IsEmpty() ? entry.id : (entry.title + " (" + entry.id + ")")).Append('\n'); 
	} 
	if (entries.Count > max) 
	{ 
		stringBuilder.Append("mod_preset_more".lang((entries.Count - max).ToString() ?? "")).Append('\n'); 
	} 
	return stringBuilder.ToString().TrimEnd(); 
} 
private void ApplyPreset(ModLoadOrderPreset.Preset preset) 
{ 
	if (HasFilter) 
	{ 
		ClearSearch(); 
	} 
	ModLoadOrderPreset.ApplyResult applyResult = manager.ApplyPreset(preset); 
	SE.Tab(); 
	textRestart.SetActive(enable: true); 
	RefreshLists(); 
	string text = ELayer.core.version.GetText(); 
	if (!preset.gameVersion.IsEmpty() && preset.gameVersion != text) 
	{ 
		ELayer.ui.Say("mod_preset_version_warn".lang(preset.gameVersion, text)); 
	} 
	ELayer.ui.Say("mod_preset_applied".lang(preset.name, applyResult.enabled.ToString() ?? "", applyResult.missing.Count.ToString() ?? "")); 
}

public void Refresh()

public void Refresh()

cs
	public override void OnKill()
	{
		if ((bool)TooltipManager.Instance) 
		{ 
			TooltipManager.Instance.HideTooltips(immediate: true); 
		} 
		foreach (PreviewEntry value in previews.Values) 
		{ 
			if ((bool)value.sprite) 
			{ 
				if (value.ownsTexture) 
				{ 
					UnityEngine.Object.Destroy(value.sprite.texture); 
				} 
				UnityEngine.Object.Destroy(value.sprite); 
			} 
		} 
		previews.Clear(); 
		ELayer.core.mods.SaveLoadOrder();
		if (Instance == this) 
		{ 
			Instance = null; 
		} 
	}
}

ModManager โ€‹

using IniParser.Model;

cs
using IniParser.Model;
using Steamworks;
using UnityEngine;
using UnityEngine.UI; 

[Serializable]
public class ModManager : ModManagerCore
{
	private sealed class WorkshopDownload
	{ 
		public readonly WorkshopItem item; 
		public readonly BaseModPackage package; 
		public readonly bool isUpdate; 
		public float lastChange; 
		public float progress; 
		public string Title => package.title.IsEmpty(item.Title).IsEmpty(item.FileId.ToString()); 
		public WorkshopDownload(BaseModPackage package, float now) 
		{ 
			this.package = package; 
			item = (WorkshopItem)package.item; 
			isUpdate = package.installed; 
			lastChange = now; 
		} 
	} 
	public static List<object> ListPluginObject = new List<object>();

	public static bool disableMod;

public class ModManager : ModManagerCore

cs
public List<FileInfo> replaceFiles = new List<FileInfo>();

private HashSet<ulong> _subscribedItems; 
private readonly HashSet<ulong> _blockedItems = new HashSet<ulong>(); 
private int _missingContent; 
public static List<string> ListChainLoad => BaseModManager.listChainLoad;

public static DirectoryInfo DirWorkshop => Instance.dirWorkshop;

public new static ModManager Instance => (ModManager)BaseModManager.Instance; 
public static bool IsInitialized => BaseModManager.isInitialized;

public new static ModManager Instance => (ModManager)BaseModManager.Instance; 
public override void Init(string path, string defaultPackage = "_Elona")
{
	base.Init(path, defaultPackage);

public override void Init(string path, string defaultPackage = "_Elona")

cs
	Debug.Log("Core Mod:" + BaseModManager.rootDefaultPacakge);
}

public static string FormatLoadOrder(BaseModPackage p) 
{ 
	string arg = p.dirInfo?.FullName; 
	int num = (p.willActivate ? 1 : 0); 
	if (ModLoadOrderPreset.IsValidId(p.id)) 
	{ 
		return $"{arg},{num},{p.id.Trim()}"; 
	} 
	return ""; 
} 
public void SaveLoadOrder()
{
	if (!disableMod) 
	if (disableMod) 
	{
		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); 
		return; 
	} 
	List<string> list = new List<string>(); 
	foreach (BaseModPackage package in packages) 
	{ 
		string str = package.dirInfo?.FullName; 
		if (!package.builtin && !str.IsEmpty()) 
		{ 
			list.Add(FormatLoadOrder(package)); 
		} 
	}
	File.WriteAllLines(CorePath.PathLoadOrder, list); 
}

public void LoadLoadOrder()
{
	string path = CorePath.rootExe + "loadorder.txt"; 
	if (!File.Exists(path)) 
	foreach (BaseModPackage package in packages) 
	{ 
		package.orderIndex = -1; 
	} 
	string pathLoadOrder = CorePath.PathLoadOrder; 
	if (!File.Exists(pathLoadOrder)) 
	{
		return;
	}
	Dictionary<string, BaseModPackage> dictionary = new Dictionary<string, BaseModPackage>(); 
	foreach (BaseModPackage package in packages) 
	Dictionary<string, BaseModPackage> dictionary = new Dictionary<string, BaseModPackage>(StringComparer.OrdinalIgnoreCase); 
	Dictionary<string, BaseModPackage> dictionary2 = new Dictionary<string, BaseModPackage>(); 
	foreach (BaseModPackage package2 in packages) 
	{
		if (!package.builtin) 
		if (!package2.builtin) 
		{
			dictionary[package.dirInfo.FullName] = package; 
			string text = NormalizeOrderPath(package2.dirInfo?.FullName); 
			if (!text.IsEmpty()) 
			{ 
				dictionary.TryAdd(text, package2); 
			} 
			string text2 = BaseModPackage.NormalizeId(package2.id); 
			if (!text2.IsEmpty()) 
			{ 
				dictionary2.TryAdd(text2, package2); 
			} 
		}
	}
	int num = 0;
	string[] array = File.ReadAllLines(path); 
	HashSet<BaseModPackage> hashSet = new HashSet<BaseModPackage>(); 
	string[] array = File.ReadAllLines(pathLoadOrder); 
	for (int i = 0; i < array.Length; i++)
	{
		string[] array2 = array[i].Split(','); 
		if (dictionary.TryGetValue(array2[0], out var value)) 
		if (ParseLoadOrderLine(array[i], out var path, out var activate, out var id)) 
		{
			value.loadPriority = num; 
			value.willActivate = array2[1] == "1"; 
			if (!dictionary.TryGetValue(NormalizeOrderPath(path), out var value)) 
			{ 
				dictionary2.TryGetValue(BaseModPackage.NormalizeId(id) ?? "", out value); 
			} 
			if (value != null && hashSet.Add(value)) 
			{ 
				value.orderIndex = num; 
				value.willActivate = activate; 
				num++; 
			} 
		}
		num++; 
	}
	static bool ParseLoadOrderLine(string line, out string reference, out bool reference2, out string reference3) 
	{ 
		reference = null; 
		reference2 = true; 
		reference3 = null; 
		if (line.IsEmpty() || line.Trim().IsEmpty()) 
		{ 
			return false; 
		} 
		int num2 = line.LastIndexOf(','); 
		if (num2 <= 0) 
		{ 
			return false; 
		} 
		string text3 = line[(num2 + 1)..].Trim(); 
		if (text3 == "0" || text3 == "1") 
		{ 
			reference = line[..num2]; 
			reference2 = text3 == "1"; 
			return !reference.IsEmpty(); 
		} 
		int num3 = line.LastIndexOf(',', num2 - 1); 
		if (num3 <= 0) 
		{ 
			return false; 
		} 
		string text4 = line[(num3 + 1)..num2].Trim(); 
		if (text4 != "0" && text4 != "1") 
		{ 
			return false; 
		} 
		reference = line[..num3]; 
		reference2 = text4 == "1"; 
		reference3 = text3; 
		return !reference.IsEmpty(); 
	} 
} 
private static string NormalizeOrderPath(string path) 
{ 
	if (!path.IsEmpty()) 
	{ 
		return path.NormalizePath().TrimEnd('/'); 
	} 
	return ""; 
} 
public static string GetPresetPath(string name) 
{ 
	return CorePath.PathLoadOrderPreset + name.SanitizeFileName() + ".txt"; 
} 
public List<FileInfo> ListPresets() 
{ 
	if (!Directory.Exists(CorePath.PathLoadOrderPreset)) 
	{ 
		return new List<FileInfo>(); 
	} 
	return new DirectoryInfo(CorePath.PathLoadOrderPreset).GetFiles("*.txt", SearchOption.TopDirectoryOnly).OrderBy((FileInfo f) => f.Name, StringComparer.OrdinalIgnoreCase).ToList(); 
} 
public bool SavePreset(string name, out string path) 
{ 
	path = GetPresetPath(name); 
	ModLoadOrderPreset.Preset preset = ModLoadOrderPreset.Save(packages, name, EClass.core.version.GetText()); 
	if (disableMod || preset.entries.Count == 0) 
	{ 
		return false; 
	} 
	Directory.CreateDirectory(CorePath.PathLoadOrderPreset); 
	File.WriteAllText(path, ModLoadOrderPreset.Serialize(preset)); 
	return true; 
} 
public bool TryLoadPresetFile(FileInfo file, out ModLoadOrderPreset.Preset preset, out string error) 
{ 
	preset = null; 
	string text; 
	try
	{ 
		text = File.ReadAllText(file.FullName); 
	} 
	catch (Exception ex) 
	{ 
		error = ex.Message; 
		return false; 
	} 
	if (!ModLoadOrderPreset.TryParse(text, out preset, out error)) 
	{ 
		return false; 
	} 
	if (preset.name.IsEmpty()) 
	{ 
		preset.name = Path.GetFileNameWithoutExtension(file.Name); 
	} 
	return true; 
} 
public ModLoadOrderPreset.ApplyResult ApplyPreset(ModLoadOrderPreset.Preset preset, bool disableOthers = true) 
{ 
	ModLoadOrderPreset.ApplyResult result = ModLoadOrderPreset.Apply(packages, preset, disableOthers); 
	SaveLoadOrder(); 
	return result; 
}

public IEnumerator RefreshMods(Action onComplete, bool syncMods)
{
	bool flag = !BaseCore.IsOffline && syncMods && UserGeneratedContent.Client.GetNumSubscribedItems() != 0; 
	if ((bool)_loading) 
	{ 
		UnityEngine.Object.Destroy(_loading.gameObject); 
	} 
	_loading = Util.Instantiate<LoadingScreen>("LoadingScreen");
	bool flag = !BaseCore.IsOffline && syncMods && UserGeneratedContent.Client.GetNumSubscribedItems() != 0; 
	WaitForEndOfFrame awaiter = new WaitForEndOfFrame();
	packages.Clear();
	_subscribedItems = null; 
	_blockedItems.Clear(); 
	_missingContent = 0; 
	disableMod |= Application.isEditor && EClass.debug.skipMod;
	LoadLocalPackages();
	LoadCustomPackage();

public IEnumerator RefreshMods(Action onComplete, bool syncMods)

cs
	{
		yield return LoadWorkshopPackages();
	}
	else
	{ 
		DirectoryInfo[] directories = dirWorkshop.GetDirectories(); 
		foreach (DirectoryInfo dir in directories) 
		{ 
			AddPackage(dir); 
		} 
	} 
	LoadCachedWorkshopPackages(); 
}
InitPackagesMeta();
LoadLoadOrder(); 
packages.Sort((BaseModPackage a, BaseModPackage b) => a.loadPriority - b.loadPriority); 
foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.isInPackages && p.willActivate && !p.id.IsEmpty())) 
SortPackages(); 
List<BaseModPackage> list = packages.Where((BaseModPackage p) => p.CanActivate && !p.parseError.IsEmpty()).ToList(); 
if (list.Count > 0) 
{
	if (mappedPackages.TryGetValue(item.id, out var value) && value.isInPackages) 
	{ 
		value.hasPublishedPackage = true; 
	} 
	Halt(list); 
	yield break; 
}
_loading.Log($"Total number of mods:{packages.Count}");
_loading.Log("Activating Mods...");
yield return awaiter;
ActivatePackages();
foreach (BaseModPackage package in packages) 
{ 
	if (package.activated) 
	{ 
		mappedPackages[package.id] = package as ModPackage; 
	} 
} 
MapActivatedPackages(); 
BaseModManager.isInitialized = true;
yield return awaiter;
onComplete?.Invoke();

public IEnumerator RefreshMods(Action onComplete, bool syncMods)

cs
	yield return null;
}

private void Halt(List<BaseModPackage> broken) 
{ 
	List<string> list = broken.Select((BaseModPackage p) => p.title.IsEmpty(p.dirInfo?.Name) + ": package.xml does not parse - " + p.parseError).ToList(); 
	list.Add("Fix the package.xml, or unsubscribe / delete the mod, then restart the game."); 
	string text = string.Join("\n", list); 
	Debug.LogError("#mod game will not start:\n" + text); 
	EGui.CreatePopup(() => new EGui.UpdateInfo(text), (EGui _) => false); 
} 
private void SortPackages() 
{ 
	LoadLoadOrder(); 
	List<BaseModPackage> list = ModOrder.SolveOrder(packages, useLoadorder: true); 
	if (list.Count != packages.Count) 
	{ 
		Debug.LogError($"#mod order {list.Count} of {packages.Count} packages"); 
		return; 
	} 
	packages.Clear(); 
	packages.AddRange(list); 
} 
private void MapActivatedPackages() 
{ 
	foreach (BaseModPackage item in packages.Where((BaseModPackage p) => p.activated && !p.id.IsEmpty())) 
	{ 
		mappedPackages[item.id] = item as ModPackage; 
	} 
} 
public ModPackage AddPackage(DirectoryInfo dir, bool isInPackages = false)
{
	ModPackage modPackage = new ModPackage

public ModPackage AddPackage(DirectoryInfo dir, bool isInPackages = false)

cs
		dirInfo = new DirectoryInfo(dir.FullName.NormalizePath()),
		installed = true,
		isInPackages = isInPackages,
		loadPriority = priorityIndex, 
		Mapping = new FileMapping(dir)
	};
	packages.Add(modPackage);
	priorityIndex++; 
	return modPackage;
}

public ModPackage AddWorkshopPackage(WorkshopItem item, bool isInPackages = false)
{
	bool itemInstallInfo = UserGeneratedContent.Client.GetItemInstallInfo(item.FileId, out var _, out var folderPath, out var _);
	if (folderPath == null) 
	if (folderPath.IsEmpty()) 
	{
		folderPath = Path.Combine(DirWorkshop.FullName, item.FileId.ToString());
	}

public void LoadLocalPackages()

cs
DirectoryInfo[] array = directories;
foreach (DirectoryInfo directoryInfo in array)
{
	if (!disableMod || !(directoryInfo.Name != "_Elona") || !(directoryInfo.Name != "_Lang_Chinese")) 
	if (!disableMod || BaseModPackage.IsBuiltinDir(directoryInfo.Name)) 
	{
		if (directoryInfo.Name == "Mod_FixedPackageLoader")
		{

public void LoadCustomPackage()

cs
	}
}

public IEnumerator LoadWorkshopPackages() 
public void InitPackagesMeta() 
{
	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)) 
	Text status = _loading.Log("Initializing mods..."); 
	HashSet<BaseModPackage> hashSet = new HashSet<BaseModPackage>(); 
	int num = 0; 
	foreach (BaseModPackage package in packages) 
	{
		yield return awaiter; 
		num++; 
		try
		{ 
			if (!package.Init()) 
			{ 
				hashSet.Add(package); 
				Debug.LogWarning("Not a package: " + package.dirInfo.FullName); 
				continue; 
			} 
			if (package.parseError.IsEmpty() && package.id.IsEmpty()) 
			{ 
				hashSet.Add(package); 
				Debug.LogWarning("No <id> in package.xml, skipped: " + package.dirInfo.FullName); 
				continue; 
			} 
			if (!package.id.IsEmpty()) 
			{ 
				mappedPackages[package.id] = package as ModPackage; 
			} 
			Debug.Log(package.ToString()); 
			SetStatus(status, $"Initializing mods {num}/{packages.Count}: {package.title}"); 
		} 
		catch (Exception ex) 
		{ 
			_loading.Log("Mod " + package.title + "/" + package.id + " has failed to initialize, " + ex.Message); 
			Debug.LogError(ex); 
		} 
	} 
	if (hashSet.Count > 0) 
	{ 
		packages.RemoveAll(hashSet.Contains); 
		_loading.Log($"Ignored {hashSet.Count} folder(s) without a usable package.xml"); 
	} 
	SetStatus(status, $"Initialized {packages.Count} mods"); 
} 
public void ActivatePackages() 
{ 
	BaseModManager.listChainLoad.Clear(); 
	ListPluginObject.Clear(); 
	ActivatePackageList(); 
	ModUtil.OnModsActivated(); 
	ModUtil.LoadTypeFallback(); 
} 
public void ActivatePackageList() 
{ 
	Dictionary<string, BaseModPackage> loaded = new Dictionary<string, BaseModPackage>(); 
	Dictionary<string, BaseModPackage> claimed = new Dictionary<string, BaseModPackage>(); 
	int num = 0; 
	foreach (BaseModPackage package in packages) 
	{ 
		package.blockedBy = null; 
		package.langDepError = null; 
	}
	yield return UpdateWorkshopPackages(); 
	void HandleWorkshopQuery(UgcQuery query) 
	Dictionary<string, BaseModPackage> dictionary = new Dictionary<string, BaseModPackage>(); 
	foreach (BaseModPackage package2 in packages) 
	{
		foreach (WorkshopItem results in query.ResultsList) 
		string text = BaseModPackage.NormalizeId(package2.id); 
		if (text != null && !package2.hasPublishedPackage) 
		{
			AddWorkshopPackage(results); 
			dictionary.TryAdd(text, package2); 
		}
	}
	foreach (ModPackage item in from p in packages.OfType<ModPackage>() 
		where !disableMod || p.builtin 
		select p) 
	{ 
		if (!item.IsValidVersion()) 
		{ 
			_loading?.Log("Skipped (made for game " + item.version + "): " + item.title + "/" + item.id); 
		} 
		else
		{ 
			if (item.banned) 
			{ 
				continue; 
			} 
			if (item.CanActivate) 
			{ 
				BaseModPackage baseModPackage = FindIncompatible(item, loaded, claimed); 
				if (baseModPackage != null) 
				{ 
					item.blockedBy = baseModPackage; 
					num++; 
					_loading?.Log("Blocked: " + item.title + "/" + item.id + " <-> " + baseModPackage.title + "/" + baseModPackage.id); 
					continue; 
				} 
				string text2 = UnmetDependency(item, loaded, dictionary); 
				if (text2 != null) 
				{ 
					item.langDepError = text2; 
					_loading?.Log("Skipped (" + text2 + "): " + item.title + "/" + item.id); 
					continue; 
				} 
			} 
			try
			{ 
				item.Activate(); 
			} 
			catch (Exception ex) 
			{ 
				_loading?.Log("Failed to activate mod " + item.title + ": " + ex.Message); 
			} 
			finally
			{ 
				if (item.activated) 
				{ 
					BaseModManager.listChainLoad.Add(item.dirInfo.FullName); 
					RegisterLoaded(item, loaded, claimed); 
				} 
			} 
		} 
	} 
	if (num > 0) 
	{ 
		Debug.LogWarning($"#mod {num} package(s) skipped due to incompatibility"); 
	} 
}

private IEnumerator UpdateWorkshopPackages() 
private string UnmetDependency(BaseModPackage p, Dictionary<string, BaseModPackage> loaded, Dictionary<string, BaseModPackage> installed) 
{
	_loading?.Log("Updating subscriptions..."); 
	WaitForEndOfFrame awaiter = new WaitForEndOfFrame(); 
	while (true) 
	if (p.dependency == null) 
	{
		return null; 
	} 
	string[][] dependency = p.dependency; 
	foreach (string[] array in dependency) 
	{ 
		if (array == null || array.Length == 0) 
		{ 
			continue; 
		} 
		BaseModPackage baseModPackage = null; 
		BaseModPackage baseModPackage2 = null; 
		bool flag = false;
		foreach (BaseModPackage item in packages.Where((BaseModPackage p) => !p.installed)) 
		string[] array2 = array; 
		for (int j = 0; j < array2.Length; j++) 
		{
			if (!(item.item is WorkshopItem { IsBanned: false } workshopItem)) 
			string text = BaseModPackage.NormalizeId(array2[j]); 
			if (text == null) 
			{
				continue;
			}
			flag = true; 
			string text = "Downloading " + workshopItem.Title + ": "; 
			BaseModPackage baseModPackage = item; 
			if ((object)baseModPackage.progressText == null) 
			if (loaded.ContainsKey(text)) 
			{
				baseModPackage.progressText = _loading?.Log(text); 
				flag = true; 
				break; 
			}
			if (item.downloadStarted && workshopItem.DownloadCompletion >= 1f) 
			if (!installed.TryGetValue(text, out var value) || value == p) 
			{
				item.installed = true; 
				if ((bool)item.progressText) 
				{ 
					item.progressText.text = text + "Done!"; 
				} 
				continue; 
			}
			else if (workshopItem.IsDownloading || workshopItem.IsDownloadPending) 
			if (packages.IndexOf(value) > packages.IndexOf(p)) 
			{
				int num = Mathf.FloorToInt(workshopItem.DownloadCompletion * 100f); 
				if ((bool)item.progressText) 
				if (baseModPackage == null) 
				{
					item.progressText.text = text + num + "%"; 
					baseModPackage = value; 
				}
			}
			else if (!item.downloadStarted) 
			else if (baseModPackage2 == null) 
			{
				item.downloadStarted = true; 
				workshopItem.DownloadItem(highPriority: true); 
				Debug.Log("Start downloading: " + workshopItem.Title + " | " + $"Installed={workshopItem.IsInstalled}, " + $"Downloading={workshopItem.IsDownloading}, " + $"Pending={workshopItem.IsDownloadPending}"); 
				baseModPackage2 = value; 
			}
		}
		if (!flag)
		{
			yield break; 
			if (baseModPackage != null) 
			{ 
				return "requires " + baseModPackage.title.IsEmpty(baseModPackage.dirInfo?.Name) + ", which loads after this mod - move it above"; 
			} 
			if (baseModPackage2 != null) 
			{ 
				return "requires " + baseModPackage2.title.IsEmpty(baseModPackage2.dirInfo?.Name) + ", which is installed but did not load"; 
			} 
			return "requires " + string.Join(" or ", array) + ", which is not installed"; 
		}
		if (UnityEngine.Input.GetKey(KeyCode.Escape)) 
	} 
	return null; 
} 
private static BaseModPackage FindIncompatible(BaseModPackage p, Dictionary<string, BaseModPackage> loaded, Dictionary<string, BaseModPackage> claimed) 
{ 
	if (p.builtin) 
	{ 
		return null; 
	} 
	string text = BaseModPackage.NormalizeId(p.id); 
	if (text == null) 
	{ 
		return null; 
	} 
	string[][] incompatible = p.incompatible; 
	if (incompatible != null) 
	{ 
		string[][] array = incompatible; 
		foreach (string[] array2 in array) 
		{
			break; 
			if (array2 == null) 
			{ 
				continue; 
			} 
			string[] array3 = array2; 
			for (int j = 0; j < array3.Length; j++) 
			{ 
				string text2 = BaseModPackage.NormalizeId(array3[j]); 
				if (text2 == null) 
				{ 
					continue; 
				} 
				BaseModPackage value; 
				if (text2 == text) 
				{ 
					Debug.Log("#mod incompatible: '" + p.id + "' self decl, ignored"); 
				} 
				else if (loaded.TryGetValue(text2, out value) && value != null) 
				{ 
					if (!value.builtin) 
					{ 
						return value; 
					} 
					Debug.Log("#mod incompatible: '" + p.id + "' targets builtin '" + value.id + "', ignored"); 
				} 
			} 
		}
		yield return awaiter; 
	}
	Debug.Log("Workshop updating cancelled"); 
	if (claimed.TryGetValue(text, out var value2) && value2 != null && !value2.builtin) 
	{ 
		return value2; 
	} 
	return null; 
}

public void InitPackagesMeta() 
private static void RegisterLoaded(BaseModPackage p, Dictionary<string, BaseModPackage> loaded, Dictionary<string, BaseModPackage> claimed) 
{
	foreach (BaseModPackage package in packages) 
	if (p.builtin) 
	{
		try
		return; 
	} 
	string text = BaseModPackage.NormalizeId(p.id); 
	if (text == null) 
	{ 
		return; 
	} 
	loaded[text] = p; 
	string[][] incompatible = p.incompatible; 
	if (incompatible == null) 
	{ 
		return; 
	} 
	string[][] array = incompatible; 
	foreach (string[] array2 in array) 
	{ 
		if (array2 == null) 
		{ 
			continue; 
		} 
		string[] array3 = array2; 
		for (int j = 0; j < array3.Length; j++) 
		{
			if (package.Init()) 
			string text2 = BaseModPackage.NormalizeId(array3[j]); 
			if (text2 != null && !(text2 == text)) 
			{
				mappedPackages[package.id] = package as ModPackage; 
				claimed.TryAdd(text2, p); 
			}
			_loading?.Log(package.ToString()); 
		}
		catch (Exception ex) 
	} 
} 
public IEnumerator LoadWorkshopPackages() 
{ 
	PublishedFileId_t[] subscribedItems = UserGeneratedContent.Client.GetSubscribedItems(); 
	if (!subscribedItems.IsEmpty()) 
	{ 
		_subscribedItems = subscribedItems.Select((PublishedFileId_t id) => id.m_PublishedFileId).ToHashSet(); 
		yield return QuerySubscriptions(subscribedItems); 
		yield return DownloadSubscriptions(); 
		if (_missingContent > 0) 
		{
			package.willActivate = false; 
			_loading?.Log("Mod " + package.title + "/" + package.id + " has failed to initialize, reason: " + ex.Message); 
			yield return new WaitForSecondsRealtime(3f); 
		}
	}
}

public void ActivatePackages() 
private IEnumerator QuerySubscriptions(PublishedFileId_t[] subscribed) 
{
	BaseModManager.listChainLoad.Clear(); 
	ListPluginObject.Clear(); 
	foreach (ModPackage package in packages) 
	WaitForEndOfFrame awaiter = new WaitForEndOfFrame(); 
	Text status = _loading.Log("Fetching subscriptions..."); 
	Dictionary<ulong, WorkshopItem> fetched = new Dictionary<ulong, WorkshopItem>(); 
	bool aborted = false; 
	for (int i = 0; i < subscribed.Length; i += 50) 
	{
		if ((disableMod && !package.builtin) || !package.IsValidVersion()) 
		PublishedFileId_t[] array = subscribed.Skip(i).Take(50).ToArray(); 
		UgcQuery query = UgcQuery.Get(array); 
		bool completed = false; 
		bool discard = false; 
		SetStatus(status, $"Fetching subscriptions {i + array.Length}/{subscribed.Length}...(Hit ESC to cancel)"); 
		if (query == null || !query.Execute(OnQueryCompleted)) 
		{
			continue; 
			Debug.LogWarning("Workshop: steam rejected the subscription query"); 
			query?.Dispose(); 
			aborted = true; 
			break; 
		}
		try
		float deadline = Time.realtimeSinceStartup + 30f; 
		while (!completed) 
		{
			package.Activate(); 
			if (package.activated) 
			if (IsCancelRequested() || Time.realtimeSinceStartup > deadline) 
			{
				BaseModManager.listChainLoad.Add(package.dirInfo.FullName); 
				discard = true; 
				aborted = true; 
				query.Dispose(); 
				break; 
			}
			yield return awaiter; 
		}
		catch (Exception ex) 
		if (aborted) 
		{ 
			Debug.LogWarning("Workshop: subscription query cancelled or timed out"); 
			break; 
		} 
		void OnQueryCompleted(UgcQuery result) 
		{
			_loading.Log("Failed to activate mod: " + package.title + ", reason: " + ex.Message); 
			completed = true; 
			if (discard) 
			{ 
				return; 
			} 
			foreach (WorkshopItem results in result.ResultsList) 
			{ 
				SteamUGCDetails_t sourceItemDetails = results.SourceItemDetails; 
				if (sourceItemDetails.m_eResult == EResult.k_EResultOK && sourceItemDetails.m_nPublishedFileId.m_PublishedFileId != 0L) 
				{ 
					fetched[sourceItemDetails.m_nPublishedFileId.m_PublishedFileId] = results; 
				} 
			} 
		}
	}
	ModUtil.OnModsActivated(); 
	ModUtil.LoadTypeFallback(); 
	foreach (WorkshopItem value in fetched.Values) 
	{ 
		if (value.IsBanned) 
		{ 
			_blockedItems.Add(value.FileId.m_PublishedFileId); 
			_missingContent++; 
		} 
		else
		{ 
			AddWorkshopPackage(value); 
		} 
	} 
	SetStatus(status, $"Fetched {fetched.Count}/{subscribed.Length} subscriptions"); 
	if (aborted) 
	{ 
		yield break; 
	} 
	for (int j = 0; j < subscribed.Length; j++) 
	{ 
		PublishedFileId_t publishedFileId_t = subscribed[j]; 
		if (!fetched.ContainsKey(publishedFileId_t.m_PublishedFileId) && !Directory.Exists(Path.Combine(dirWorkshop.FullName, publishedFileId_t.ToString()))) 
		{ 
			_missingContent++; 
		} 
	} 
} 
private IEnumerator DownloadSubscriptions() 
{ 
	float now = Time.realtimeSinceStartup; 
	List<WorkshopDownload> queue = (from p in packages 
		where p.item is WorkshopItem workshopItem && (!p.installed || workshopItem.IsNeedsUpdate) 
		select new WorkshopDownload(p, now)).ToList(); 
	if (queue.Count == 0) 
	{ 
		yield break; 
	} 
	WaitForEndOfFrame awaiter = new WaitForEndOfFrame(); 
	Text status = _loading.Log($"Downloading {queue.Count} mods..."); 
	Dictionary<ulong, EResult> results = new Dictionary<ulong, EResult>(); 
	int total = queue.Count; 
	int completed = 0; 
	float lastActivity = now; 
	float nextStatus = 0f; 
	UserGeneratedContent.Client.EventItemDownloaded.AddListener(OnItemDownloaded); 
	try
	{ 
		while (queue.Count > 0) 
		{ 
			now = Time.realtimeSinceStartup; 
			for (int num = queue.Count - 1; num >= 0; num--) 
			{ 
				WorkshopDownload workshopDownload = queue[num]; 
				WorkshopItem item = workshopDownload.item; 
				ulong publishedFileId = item.FileId.m_PublishedFileId; 
				string path = null; 
				string reason = null; 
				bool flag = false; 
				EResult value; 
				if (!workshopDownload.package.downloadStarted) 
				{ 
					workshopDownload.package.downloadStarted = true; 
					workshopDownload.lastChange = now; 
					if (item.DownloadItem(highPriority: true)) 
					{ 
						Debug.Log("Start downloading: " + workshopDownload.Title + " | " + $"Installed={item.IsInstalled}, " + $"Update={item.IsNeedsUpdate}, " + $"Downloading={item.IsDownloading}, " + $"Pending={item.IsDownloadPending}"); 
						continue; 
					} 
					reason = "cannot start the download"; 
				} 
				else if (results.TryGetValue(publishedFileId, out value) && value != EResult.k_EResultOK) 
				{ 
					reason = $"download failed ({value})"; 
				} 
				else if (IsItemReady(item, out path)) 
				{ 
					flag = true; 
				} 
				else
				{ 
					if (item.IsDownloadPending) 
					{ 
						workshopDownload.lastChange = now; 
						continue; 
					} 
					if (item.IsDownloading) 
					{ 
						float downloadCompletion = item.DownloadCompletion; 
						if (downloadCompletion > workshopDownload.progress) 
						{ 
							workshopDownload.progress = downloadCompletion; 
							float lastChange; 
							lastActivity = (lastChange = now); 
							workshopDownload.lastChange = lastChange; 
						} 
						continue; 
					} 
					if (!(now - workshopDownload.lastChange > 20f)) 
					{ 
						continue; 
					} 
					reason = "cannot start the download"; 
				} 
				queue.RemoveAt(num); 
				lastActivity = now; 
				if (flag) 
				{ 
					completed++; 
					InstallWorkshopPackage(workshopDownload, path); 
				} 
				else
				{ 
					FailWorkshopPackage(workshopDownload, reason); 
				} 
			} 
			if (queue.Count == 0) 
			{ 
				break; 
			} 
			if (IsCancelRequested()) 
			{ 
				AbortDownloads(queue, "cancelled"); 
				break; 
			} 
			if (now - lastActivity > 90f) 
			{ 
				AbortDownloads(queue, "not responding"); 
				break; 
			} 
			if (now >= nextStatus) 
			{ 
				nextStatus = now + 0.5f; 
				WorkshopDownload workshopDownload2 = queue.Find((WorkshopDownload d) => d.item.IsDownloading) ?? queue[0]; 
				SetStatus(status, $"Downloading mods {completed}/{total}: " + $"{workshopDownload2.Title} {Mathf.FloorToInt(workshopDownload2.progress * 100f)}%...(Hit ESC to cancel)"); 
			} 
			yield return awaiter; 
		} 
	} 
	finally
	{ 
		UserGeneratedContent.Client.EventItemDownloaded.RemoveListener(OnItemDownloaded); 
	} 
	SetStatus(status, $"Downloaded {completed}/{total} mods"); 
	packages.RemoveAll((BaseModPackage p) => p.item is WorkshopItem && !p.installed); 
	void OnItemDownloaded(DownloadItemResult_t result) 
	{ 
		results[result.m_nPublishedFileId.m_PublishedFileId] = result.m_eResult; 
	} 
} 
public void LoadCachedWorkshopPackages() 
{ 
	HashSet<string> hashSet = packages.Select((BaseModPackage p) => p.dirInfo.FullName).ToHashSet(StringComparer.OrdinalIgnoreCase); 
	DirectoryInfo[] directories = dirWorkshop.GetDirectories(); 
	foreach (DirectoryInfo directoryInfo in directories) 
	{ 
		ulong result; 
		bool flag = ulong.TryParse(directoryInfo.Name, out result); 
		if ((!flag || !_blockedItems.Contains(result)) && (_subscribedItems == null || (flag && _subscribedItems.Contains(result))) && !hashSet.Contains(new DirectoryInfo(directoryInfo.FullName.NormalizePath()).FullName)) 
		{ 
			ModPackage modPackage = AddPackage(directoryInfo); 
			if (flag) 
			{ 
				modPackage.workshopId = directoryInfo.Name; 
			} 
		} 
	} 
} 
private void InstallWorkshopPackage(WorkshopDownload download, string path) 
{ 
	BaseModPackage package = download.package; 
	package.installed = true; 
	package.dirInfo = new DirectoryInfo(path.NormalizePath()); 
	if (package is ModPackage modPackage) 
	{ 
		modPackage.Mapping = new FileMapping(package.dirInfo); 
	} 
	Debug.Log("Downloaded: " + download.Title + " -> " + package.dirInfo.FullName); 
} 
private void FailWorkshopPackage(WorkshopDownload download, string reason) 
{ 
	if (download.isUpdate) 
	{ 
		Debug.LogWarning("Workshop update failed: " + download.Title + ", " + reason); 
		return; 
	} 
	_missingContent++; 
	Debug.LogWarning("Workshop download failed: " + download.Title + ", " + reason); 
} 
private void AbortDownloads(List<WorkshopDownload> queue, string reason) 
{ 
	foreach (WorkshopDownload item in queue) 
	{ 
		FailWorkshopPackage(item, reason); 
	} 
	queue.Clear(); 
} 
private static bool IsItemReady(WorkshopItem item, out string path) 
{ 
	path = null; 
	if (!item.IsInstalled || item.IsNeedsUpdate || item.IsDownloading || item.IsDownloadPending) 
	{ 
		return false; 
	} 
	if (UserGeneratedContent.Client.GetItemInstallInfo(item.FileId, out var _, out path, out var _) && !path.IsEmpty()) 
	{ 
		return Directory.Exists(path); 
	} 
	return false; 
} 
private static bool IsCancelRequested() 
{ 
	return UnityEngine.Input.GetKey(KeyCode.Escape); 
} 
private static void SetStatus(Text status, string message) 
{ 
	if ((bool)status) 
	{ 
		status.text = message; 
	} 
}

public override void ParseExtra(DirectoryInfo dir, BaseModPackage package)

ModUtil โ€‹

private static void LoadEffectTemplate()

cs
	}
}

public static DynamicInvoker Call(object instance, params string[] names) 
{ 
	return new DynamicInvoker(instance?.GetType(), instance, names); 
} 
public static DynamicInvoker Call(Type type, params string[] names) 
{ 
	return new DynamicInvoker(type, null, names); 
} 
public static DynamicInvoker Call<T>(params string[] names) 
{ 
	return new DynamicInvoker(typeof(T), null, names); 
} 
public static DynamicInvoker CallType(string typeName, params string[] names) 
{ 
	return new DynamicInvoker(DynamicReflection.FindType(typeName), null, names); 
} 
public static DynamicInvoker Construct(Type type) 
{ 
	return DynamicInvoker.Constructor(type); 
} 
public static DynamicInvoker Construct<T>() 
{ 
	return DynamicInvoker.Constructor(typeof(T)); 
} 
public static DynamicInvoker ConstructType(string typeName) 
{ 
	return DynamicInvoker.Constructor(DynamicReflection.FindType(typeName)); 
} 
public static DynamicAccessor Access(object instance, params string[] names) 
{ 
	return new DynamicAccessor(instance?.GetType(), instance, names); 
} 
public static DynamicAccessor Access(Type type, params string[] names) 
{ 
	return new DynamicAccessor(type, null, names); 
} 
public static DynamicAccessor Access<T>(params string[] names) 
{ 
	return new DynamicAccessor(typeof(T), null, names); 
} 
public static DynamicAccessor AccessType(string typeName, params string[] names) 
{ 
	return new DynamicAccessor(DynamicReflection.FindType(typeName), null, names); 
} 
public static DynamicTarget Target(Type type, params string[] names) 
{ 
	return new DynamicTarget(type, names); 
} 
public static DynamicTarget Target<T>(params string[] names) 
{ 
	return new DynamicTarget(typeof(T), names); 
} 
public static DynamicTarget TargetType(string typeName, params string[] names) 
{ 
	return new DynamicTarget(DynamicReflection.FindType(typeName), names); 
} 
public static MethodInfo FindMethod(Type type, params string[] names) 
{ 
	return new DynamicTarget(type, names).Get(); 
} 
public static MethodInfo FindMethod<T>(params string[] names) 
{ 
	return new DynamicTarget(typeof(T), names).Get(); 
} 
public static MethodInfo FindGetter(Type type, params string[] names) 
{ 
	return DynamicTarget.Accessor(type, names, setter: false); 
} 
public static MethodInfo FindGetter<T>(params string[] names) 
{ 
	return DynamicTarget.Accessor(typeof(T), names, setter: false); 
} 
public static MethodInfo FindSetter(Type type, params string[] names) 
{ 
	return DynamicTarget.Accessor(type, names, setter: true); 
} 
public static MethodInfo FindSetter<T>(params string[] names) 
{ 
	return DynamicTarget.Accessor(typeof(T), names, setter: true); 
} 
public static ConstructorInfo FindConstructor(Type type, params Type[] paramTypes) 
{ 
	return DynamicTarget.Constructor(type, paramTypes); 
} 
public static ConstructorInfo FindConstructor<T>(params Type[] paramTypes) 
{ 
	return DynamicTarget.Constructor(typeof(T), paramTypes); 
} 
public static Type FindType(string typeName) 
{ 
	return DynamicReflection.FindType(typeName); 
} 
public static T Coerce<T>(object value) 
{ 
	return DynamicReflection.Coerce<T>(value); 
} 
public static SerializableSoundData GetSoundMeta(string soundPath)
{
	string path = Path.ChangeExtension(soundPath, ".json");

Player โ€‹

public class PartySetup : EClass

cs
[JsonProperty]
public int fishArtifact;

[JsonProperty] 
public int staminaRecovery; 
[JsonProperty]
public float angle;

public void OnAdvanceRealHour()

cs
	}
}

public void RecoverStamina(int a) 
{ 
	if (a >= staminaRecovery) 
	{ 
		a = staminaRecovery; 
	} 
	if (a != 0) 
	{ 
		staminaRecovery -= a; 
		EClass.pc.stamina.Mod(a); 
	} 
} 
public void RefreshDomain()
{
	domains.Clear();

Recipe โ€‹

public string GetName()

cs
	{
		text = "(" + source.row.GetField<string>("id") + ")";
	}
	return text.ToTitleCase(); 
	text = text.ToTitleCase(); 
	if (source.row is CardRow && (source.row as CardRow).quality == 4) 
	{ 
		text = "โ˜…" + text; 
	} 
	return text; 
}

public virtual string GetDetail()

TCText โ€‹

private static bool ExtractSoundTag(ref string text, out string id, out float chโ€ฆ)

cs
{
	id = null;
	chance = 1f;
	int num = text.IndexOf("<sound", StringComparison.Ordinal); 
	int num = text.IndexOf("<sound=", StringComparison.Ordinal); 
	if (num == -1)
	{
		return false;

private static bool ExtractSoundTag(ref string text, out string id, out float chโ€ฆ)

cs
{
	return false;
}
int num3 = num + 6; 
int num3 = num + 7; 
string text2 = text.Substring(num3, num2 - num3);
int num4 = text2.IndexOf(',');
if (num4 == -1)

WidgetHP โ€‹

public void Refresh()

cs
gaugeStamina.textNow.SetSize(gaugeStamina.textNow.orgSize + extra.fontSize);
gaugeHP.UpdateValue(EMono.pc.hp, EMono.pc.MaxHP);
gaugeMP.UpdateValue(EMono.pc.mana.value, EMono.pc.mana.max);
gaugeStamina.UpdateValue(EMono.pc.stamina.value, EMono.pc.stamina.max); 
gaugeStamina.UpdateValue(EMono.pc.stamina.value, EMono.pc.stamina.max, EMono.player.staminaRecovery); 
Color c = EMono.Colors.Dark.gradientHP.Evaluate((float)EMono.pc.hp / (float)EMono.pc.MaxHP);
gaugeHP.textNow.text = "".TagColor(c, EMono.pc.hp.ToString() ?? "") + (extra.showMax ? (" / " + EMono.pc.MaxHP) : "");
c = EMono.Colors.Dark.gradientMP.Evaluate((float)EMono.pc.mana.value / (float)EMono.pc.mana.max);