3using System.Collections.Frozen;
4using System.Reflection;
5using System.Security.Cryptography;
13using NuGet.Versioning;
17using System.IO.Compression;
26 public static string ReportLink =
"https://gitee.com/SC-SPM/SurvivalcraftApi/issues";
29 public static string APIReleasesLink_API =
"https://gitee.com/api/v5/repos/SC-SPM/SurvivalcraftApi/releases";
31 public static string fName =
"ModsManager";
33 [Obsolete(
"使用ApiVersionString")]
45 public static string DocPath =
"app:/doc";
49 public static string ExternalPath => EngineActivity.BasePath;
50 public static string DocPath = EngineActivity.BasePath;
57 public static string UserDataPath {
get; } = $
"{DocPath}/UserId.dat";
65 public static string SettingPath {
get; } = $
"{DocPath}/Settings.xml";
66 public static string ConfigsPath {
get; } = $
"{DocPath}/Configs.xml";
67 public static string LogPath {
get; } = $
"{ExternalPath}/Bugs";
68 public static string ModsPath = $
"{ExternalPath}/Mods";
69 public static bool IsAndroid => OperatingSystem.IsAndroid();
81 public Dictionary<ModLoader, bool>
Loaders = [];
85 if (!
Loaders.TryGetValue(modLoader, out _)) {
91 Loaders.Remove(modLoader, out _);
95 if (
Loaders.TryGetValue(toDisable, out _)) {
104 public static Dictionary<string, string>
Configs = [];
122 public static Dictionary<string, ModHook>
ModHooks = [];
123 public static Dictionary<string, Assembly>
Dlls = [];
126 modEntity =
ModList.Find(px => px.modInfo.PackageName == packagename);
127 return modEntity !=
null;
146 public static void HookAction(
string HookName, Func<ModLoader, bool> action)
149 foreach (
ModLoader modLoader
in modHook.Loaders.Keys) {
150 if (
TryInvoke(modHook, modLoader, action)) {
160 foreach (
ModLoader modLoader
in modHook.Loaders.Keys.Reverse()) {
161 if (
TryInvoke(modHook, modLoader, action)) {
168 public static Dictionary<KeyValuePair<ModHook, ModLoader>,
bool>
m_hookBugLogged = [];
172 if (action.Invoke(modLoader)) {
177 catch (Exception ex) {
178 KeyValuePair<ModHook, ModLoader> keyValuePair =
new(modHook, modLoader);
194 modHook =
new ModHook(HookName);
197 modHook.Add(modLoader);
201 ModEntity modEntity =
ModList.Find(p => p.modInfo.PackageName == packageName);
202 if (modEntity !=
null
204 modHook.Disable(from, modEntity.
Loader, reason);
215 if (jsonElement.TryGetProperty(
"Name", out JsonElement name)) {
216 modInfo.Name = name.GetString();
218 if (jsonElement.TryGetProperty(
"Version", out JsonElement version)
219 && version.ValueKind == JsonValueKind.String) {
220 modInfo.Version = version.GetString()?.Trim();
221 if (modInfo.Version != null) {
222 NuGetVersion.TryParse(modInfo.Version, out modInfo.NuGetVersion);
225 if (jsonElement.TryGetProperty(
"ApiVersion", out JsonElement apiVersion)
226 && apiVersion.ValueKind == JsonValueKind.String) {
227 string apiVersionString = apiVersion.GetString()?.Trim();
228 modInfo.ApiVersion = apiVersionString;
229 if (apiVersionString ==
"1.80") {
230 apiVersionString =
"1.8";
232 else if (apiVersionString ==
"1.81") {
233 apiVersionString =
"1.8.1";
237 if (jsonElement.TryGetProperty(
"Description", out JsonElement description)
238 && description.ValueKind == JsonValueKind.String) {
239 modInfo.Description = description.GetString();
241 if (jsonElement.TryGetProperty(
"ScVersion", out JsonElement scVersion)
242 && scVersion.ValueKind == JsonValueKind.String) {
243 modInfo.ScVersion = scVersion.GetString();
245 if (jsonElement.TryGetProperty(
"Link", out JsonElement link)
246 && link.ValueKind == JsonValueKind.String) {
247 modInfo.Link = link.GetString();
249 if (jsonElement.TryGetProperty(
"Author", out JsonElement author)
250 && author.ValueKind == JsonValueKind.String) {
251 modInfo.Author = author.GetString();
253 if (jsonElement.TryGetProperty(
"PackageName", out JsonElement packageName)
254 && packageName.ValueKind == JsonValueKind.String) {
255 modInfo.PackageName = packageName.GetString();
261 if (jsonElement.TryGetProperty(
"Dependencies", out JsonElement dependencies)) {
262 if (dependencies.ValueKind == JsonValueKind.Array) {
263 modInfo.Dependencies = dependencies.EnumerateArray()
264 .Where(dependency => dependency.ValueKind == JsonValueKind.String)
265 .Select(dependency => dependency.GetString())
267 foreach (
string dependency
in modInfo.Dependencies) {
268 int index = dependency.IndexOf(
':');
270 string dependencyPackageName = dependency.Substring(0, index);
271 string dependencyVersion = dependency.Substring(index + 1).Trim();
272 if (TryParseVersionRange(dependencyVersion, out VersionRange dependencyVersionRange)) {
273 modInfo.DependencyRanges.Add(dependencyPackageName, dependencyVersionRange);
277 modInfo.DependencyRanges.Add(dependency, VersionRange.All);
281 else if (dependencies.ValueKind == JsonValueKind.Object) {
282 foreach (JsonProperty dependency
in dependencies.EnumerateObject()) {
283 if (dependency.Value.ValueKind == JsonValueKind.String) {
284 string dependencyPackageName = dependency.Name;
285 string dependencyVersion = dependency.Value.GetString()?.Trim();
286 if (TryParseVersionRange(dependencyVersion, out VersionRange dependencyVersionRange)) {
287 modInfo.DependencyRanges.Add(dependencyPackageName, dependencyVersionRange);
293 if (jsonElement.TryGetProperty(
"LoadOrder", out JsonElement loadOrder)
294 && loadOrder.ValueKind == JsonValueKind.Number) {
295 modInfo.LoadOrder = loadOrder.GetInt32();
298 if (jsonElement.TryGetProperty(
"NonPersistentMod", out JsonElement nonPersistentMod)
299 && nonPersistentMod.ValueKind == JsonValueKind.True) {
300 modInfo.NonPersistentMod =
true;
312 XElement element =
new(
"Configs");
313 foreach (KeyValuePair<string, string> c
in Configs) {
314 element.SetAttributeValue(c.Key, c.Value);
331 catch (Exception e) {
332 Log.
Error($
"Load configs failed. Reason: {e}");
339 if (xElement.Name !=
"Configs") {
342 foreach (XAttribute c
in xElement.Attributes()) {
343 if (!
Configs.ContainsKey(c.Name.LocalName)) {
349 catch (Exception e) {
350 Log.
Error($
"Load configs failed. Reason: {e}");
361 public static void SetConfig(
string key,
string value) {
362 if (!
Configs.TryAdd(key, value)) {
367 public static string ImportMod(
string name, Stream stream) {
374 string realName = name;
382 realName = $
"{nameWithoutSuffix}({num}){ModSuffix}";
387 stream.CopyTo(fileStream);
393 for (
int i = 0; i <
ModList.Count; i++) {
417 (x.IsDisabled ?
int.MaxValue : x.modInfo?.LoadOrder ??
int.MaxValue).CompareTo(
418 y.IsDisabled ?
int.MaxValue : y.modInfo?.LoadOrder ??
int.MaxValue
428 if (packageName ==
null) {
445 List<ModEntity> modEntities =
ModListAll.FindAll(px => !px.IsDisabled && px.modInfo?.PackageName == packageName);
446 if (modEntities.Count > 1) {
447 modEntity1.IsDisabled =
true;
449 AddException(
new Exception($
"Multiple mods with PackageName [{packageName}], please keep only one."));
452 AppDomain.CurrentDomain.AssemblyResolve += (_, args) => {
455 Assembly? assembly =
Dlls.GetValueOrDefault(args.Name)
460 catch (Exception e) {
461 Log.
Error($
"Load assembly [{args.Name}] failed:{e}");
469 public static void AddException(Exception e,
bool AllowContinue_ =
false) {
488 if (modEntity.
modInfo ==
null) {
489 LoadingScreen.
Warning($
"The modinfo.json is missing or broken from [{Storage.GetFileName(modEntity.ModFilePath)}], and this mod will be disabled.");
492 LoadingScreen.
Warning($
"The package name [{modEntity.modInfo.PackageName}] of [{Storage.GetFileName(modEntity.ModFilePath)}] is not allowed, and this mod will not be loaded.");
498 catch (Exception e) {
509 stream.Seek(0, SeekOrigin.Begin);
510 return new StreamReader(stream).ReadToEnd();
517 byte[] bytes =
new byte[stream.Length];
518 stream.Seek(0, SeekOrigin.Begin);
519 stream.ReadExactly(bytes);
524 [Obsolete(
"Use GetSha256 instead.")]
525 public static string GetMd5(
string input) {
527 throw new NotSupportedException(
"MD5 is not supported on browser. Use GetSha256 instead.");
529 byte[] data = MD5.HashData(Encoding.Default.GetBytes(input));
530 StringBuilder sBuilder =
new();
531 for (
int i = 0; i < data.Length; i++) {
532 sBuilder.Append(data[i].ToString(
"x2"));
534 return sBuilder.ToString();
539 byte[] data = SHA256.HashData(Encoding.Default.GetBytes(input));
540 StringBuilder sBuilder =
new();
541 for (
int i = 0; i < data.Length; i++) {
542 sBuilder.Append(data[i].ToString(
"x2"));
544 return sBuilder.ToString();
547 public static bool FindElement(XElement xElement, Func<XElement, bool> func, out XElement elementout) {
548 elementout = xElement.Descendants().FirstOrDefault(func);
549 return elementout !=
null;
553 elementout = xElement.Descendants().FirstOrDefault(e => e.Attribute(
"Guid")?.Value == guid);
554 return elementout !=
null;
557 public static bool HasAttribute(XElement element, Func<string, bool> func, out XAttribute xAttributeout) {
558 xAttributeout = element.Attributes()
559 .FirstOrDefault(a => func(a.Name.LocalName));
560 return xAttributeout !=
null;
563 public static void CombineClo(XElement clothesRoot, Stream toCombineStream) {
565 foreach (XElement element
in toCombineRoot.Elements()) {
566 string indexValue = element.Attribute(
"Index")?.Value;
567 if (indexValue ==
null) {
568 clothesRoot.Add(toCombineRoot);
571 List<XAttribute> newAttributes = [];
572 foreach (XAttribute attribute
in element.Attributes()) {
573 if (attribute.Name.LocalName.StartsWith(
"new-")) {
574 newAttributes.Add(attribute);
577 if (newAttributes.Count > 0
578 &&
FindElement(clothesRoot, e => e.Attribute(
"Index")?.Value == indexValue, out XElement element1)) {
579 foreach (XAttribute newAttribute
in newAttributes) {
580 element1.SetAttributeValue(newAttribute.Name.LocalName.Substring(4), newAttribute.Value);
583 else if (
HasAttribute(element, name => name.StartsWith(
"r-"), out XAttribute _)
584 &&
FindElement(clothesRoot, e => e.Attribute(
"Index")?.Value == indexValue, out XElement element2)) {
589 clothesRoot.Add(toCombineRoot);
594 public static void CombineCr(XElement xElement, Stream cloorcr) {
600 foreach (XElement element
in needCombine.Elements()) {
601 if (element.Attribute(
"Result") !=
null) {
602 if (
HasAttribute(element, name => name.StartsWith(
"new-"), out XAttribute attribute)) {
606 foreach (XAttribute xAttribute
in element.Attributes())
608 if (xAttribute.Name == attribute.Name) {
611 if (ele.Attribute(xAttribute.Name) ==
null) {
617 out XElement element1
619 element1.SetAttributeValue(attribute.Name.LocalName.Substring(4), attribute.Value);
620 element1.SetValue(element.Value);
623 else if (
HasAttribute(element, name => name.StartsWith(
"r-"), out XAttribute attribute1)) {
627 foreach (XAttribute xAttribute
in element.Attributes())
629 if (xAttribute.Name == attribute1.Name) {
632 if (ele.Attribute(xAttribute.Name) ==
null) {
638 out XElement element1
645 xElement.Add(element);
652 public static void Modify(XElement source, XElement change) {
655 item => item.Name.LocalName == change.Name.LocalName
656 && item.Attribute(
"Guid") !=
null
657 && change.Attribute(
"Guid") !=
null
658 && item.Attribute(
"Guid")?.Value == change.Attribute(
"Guid")?.Value,
659 out XElement xElement1
661 foreach (XElement xElement
in change.Elements()) {
662 Modify(xElement1, xElement);
683 if (ReferenceEquals(
this, other)) {
689 public override bool Equals(
object obj) {
712 new(
"7347a83f-2d46-4fdf-bce2-52677de0b568",
"Game.ComponentBody"),
713 new(
"4e14ce27-fdef-46ca-8ea0-26af43c215e5",
"Game.ComponentHealth"),
714 new(
"7ecfafc4-4603-424c-87dd-1df59e7ef413",
"Game.ComponentPlayer"),
715 new(
"9dc356e5-7dc8-45f6-8779-827ddee9966c",
"Game.ComponentMiner"),
716 new(
"6f538db3-f1fe-4e91-8ef5-627c0b1a74ba",
"Game.ComponentRunAwayBehavior"),
717 new(
"8b3d07dc-6498-4691-9686-cf4edabb8f3f",
"Game.ComponentGui"),
718 new(
"e2636c38-f179-4aa1-b087-ed6920d66e8e",
"Game.SubsystemTerrain"),
719 new(
"96e79f99-a082-4190-9ab6-835dc49ebbdd",
"Game.SubsystemExplosions"),
720 new(
"dafb8e14-11b9-44b7-a208-424b770aeaa9",
"Game.SubsystemProjectiles"),
721 new(
"32d392de-69c1-4d04-9e0b-5c7463201892",
"Game.SubsystemPickables"),
722 new(
"54a4f6d5-98dd-4dc3-bf6d-04dfd972c6b7",
"Game.SubsystemTime"),
723 new(
"b2e68ecd-49fc-4c05-b784-424da13f8550",
"Game.ComponentDispenser"),
724 new(
"f6b020bb-8994-6ae6-289b-a842e3eb9ca5",
"Game.ComponentFactors"),
725 new(
"a346c456-5087-48c4-835a-5829b3f35c68",
"Game.ComponentLevel"),
726 new(
"1df4e627-c959-4e6a-bfa2-b7ee3ef08c99",
"Game.ComponentClothing"),
727 }.ToFrozenDictionary();
734 public static void CombineDataBase(XElement databaseRoot, Stream toCombineStream,
string modPackageName) {
736 XElement databaseObjects = databaseRoot.Element(
"DatabaseObjects");
737 foreach (XElement element
in toCombineRoot.Elements()) {
739 if (!
string.IsNullOrEmpty(modPackageName)
740 && element.Name.LocalName ==
"EntityTemplate") {
741 string guid = element.Attribute(
"Guid")?.Value;
742 bool isNewEntity =
true;
743 if (!
string.IsNullOrEmpty(guid)) {
747 XElement parameterElement =
new(
"Parameter");
748 parameterElement.SetAttributeValue(
"Name",
"ModSource");
749 parameterElement.SetAttributeValue(
"Value", modPackageName);
750 parameterElement.SetAttributeValue(
"Type",
"string");
751 element.Add(parameterElement);
755 if (
HasAttribute(element, str => str.StartsWith(
"new-"), out XAttribute newAttribute)) {
756 XAttribute guidAttribute = element.Attribute(
"Guid");
757 if (guidAttribute ==
null) {
760 string guid = guidAttribute.Value;
762 string newAttributeName = newAttribute.Name.LocalName.Substring(4);
763 if (newAttributeName ==
"Value"
764 && oldElement.Attribute(
"Name")?.Value ==
"Class") {
765 if (
ClassSubstitutes.TryGetValue(guid, out List<ClassSubstitute> classSubstitutes)) {
766 classSubstitutes.Add(
new ClassSubstitute (modPackageName, newAttribute.Value));
776 oldElement.SetAttributeValue(newAttributeName, newAttribute.Value);
781 Modify(databaseObjects, element);
788 Queue<(string, XElement)> needToSolves = [];
789 foreach ((
string guid, List<ClassSubstitute> substitutes) in
ClassSubstitutes) {
795 if (substitutes.Any(x => x == selected)) {
798 if (substitutes.Count == oldSubstitutes.Count && oldSubstitutes.SequenceEqual(substitutes)) {
799 element.SetAttributeValue(
"Value", selected.ClassName);
804 needToSolves.Enqueue((guid, element));
808 element.SetAttributeValue(
"Value", selected.ClassName);
813 needToSolves.Enqueue((guid, element));
819 element.SetAttributeValue(
"Value", substitutes.Last().ClassName);
822 needToSolves.Enqueue((guid, element));
829 if (needToSolves.Count > 0) {
832 if (needToSolves.TryDequeue(out (
string, XElement) tuple)) {
848 if (
string.IsNullOrEmpty(value)) {
852 value = value.Trim();
853 if (value.Length == 0) {
857 char firstChar = value[0];
860 if (NuGetVersion.TryParse(value.Substring(1), out NuGetVersion nuGetVersion)) {
861 versionRange =
new VersionRange(nuGetVersion,
true, nuGetVersion,
true);
867 if (value.Length > 1) {
868 if (value[1] ==
'=') {
869 if (NuGetVersion.TryParse(value.Substring(2), out NuGetVersion nuGetVersion)) {
870 versionRange =
new VersionRange(nuGetVersion,
true);
875 if (NuGetVersion.TryParse(value.Substring(1), out NuGetVersion nuGetVersion)) {
876 versionRange =
new VersionRange(nuGetVersion,
false);
884 if (value.Length > 1) {
885 if (value[1] ==
'=') {
886 if (NuGetVersion.TryParse(value.Substring(2), out NuGetVersion nuGetVersion)) {
887 versionRange =
new VersionRange(
null,
false, nuGetVersion,
true);
892 if (NuGetVersion.TryParse(value.Substring(1), out NuGetVersion nuGetVersion)) {
893 versionRange =
new VersionRange(
null,
false, nuGetVersion);
901 if (NuGetVersion.TryParse(value.Substring(1), out NuGetVersion nuGetVersion)) {
902 versionRange =
new VersionRange(nuGetVersion,
true,
new NuGetVersion(nuGetVersion.Major + 1, 0, 0, 0));
908 if (NuGetVersion.TryParse(value.Substring(1), out NuGetVersion nuGetVersion)) {
909 versionRange =
new VersionRange(nuGetVersion,
true,
new NuGetVersion(nuGetVersion.Major, nuGetVersion.Minor + 1, 0, 0));
915 if (VersionRange.TryParse(value, out versionRange)) {
928 MemoryStream keepOpenStream =
new();
929 byte[] buff =
new byte[stream.Length];
930 stream.ReadExactly(buff);
932 bool decipher =
true;
933 for (
int i = 0; i < hc.Length; i++) {
934 if (hc[i] != buff[i]) {
940 bool decipher2 =
true;
941 for (
int i = 0; i < hc2.Length; i++) {
942 if (hc2[i] != buff[i]) {
948 byte[] buff2 =
new byte[buff.Length - hc.Length];
949 for (
int i = 0; i < buff2.Length; i++) {
950 buff2[i] = buff[buff.Length - 1 - i];
952 keepOpenStream.Write(buff2, 0, buff2.Length);
953 keepOpenStream.Flush();
955 else if (decipher2) {
956 byte[] buff2 =
new byte[buff.Length - hc2.Length];
959 int l = (buff2.Length + 1) / 2;
960 for (
int i = 0; i < buff2.Length; i++) {
962 buff2[i] = buff[hc2.Length + k];
966 buff2[i] = buff[hc2.Length + l + t];
970 keepOpenStream.Write(buff2, 0, buff2.Length);
971 keepOpenStream.Flush();
974 stream.Position = 0L;
975 stream.CopyTo(keepOpenStream);
978 keepOpenStream.Position = 0L;
979 return keepOpenStream;
984 byte[] buff =
new byte[stream.Length];
985 stream.ReadExactly(buff);
987 bool decipher =
true;
988 for (
int i = 0; i < hc.Length; i++) {
989 if (hc[i] != buff[i]) {
995 bool decipher2 =
true;
996 for (
int i = 0; i < hc2.Length; i++) {
997 if (hc2[i] != buff[i]) {
1002 if (decipher || decipher2) {
1005 byte[] buff2 =
new byte[buff.Length + hc2.Length];
1008 for (
int i = 0; i < hc2.Length; i++) {
1011 for (
int i = 0; i < buff.Length; i++) {
1013 buff2[k + l] = buff[i];
1018 l = hc2.Length + (buff.Length + 1) / 2;
1019 for (
int i = 0; i < buff.Length; i++) {
1021 buff2[k + l] = buff[i];
1025 string newPath = $
"{path.Substring(0, path.LastIndexOf('.'))}({LanguageControl.Get(fName, 63)}).scmod";
1026 FileStream fileStream =
new(
Storage.
GetSystemPath(newPath), FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
1027 fileStream.Write(buff2, 0, buff2.Length);
1030 fileStream.Dispose();
static void Error(object message)
static void Debug(object message)
static ReadOnlyList< Assembly > LoadedAssemblies
static string GetSystemPath(string path)
static void CreateDirectory(string path)
static bool DirectoryExists(string path)
static IEnumerable< string > ListDirectoryNames(string path)
static IEnumerable< string > ListFileNames(string path)
static Stream OpenFile(string path, OpenFileMode openFileMode)
static string GetExtension(string path)
static bool FileExists(string path)
static string GetFileNameWithoutExtension(string path)
static string CombinePaths(params string[] paths)
static XElement DatabaseNode
static void ShowDialog(ContainerWidget parentWidget, Dialog dialog)
static readonly JsonDocumentOptions DefaultJsonOptions
static void Error(string mesg)
static void Warning(string mesg)
ModDisableReason DisableReason
virtual void LoadSettings(XElement xElement)
加载设置
virtual void SaveSettings(XElement xElement)
保存设置
static void SwitchScreen(string name, params object[] parameters)
static ContainerWidget RootWidget
static void SaveSettings()
static bool LoadSettings()
文件存在则读取并返回真否则返回假
static ZipArchive Open(Stream stream, bool keepStreamOpen=false)
bool Equals(ClassSubstitute other)
override bool Equals(object obj)
override int GetHashCode()
ClassSubstitute(string packageName, string className)
Dictionary< ModLoader, bool > Loaders
void Disable(ModLoader from, ModLoader toDisable, string reason)
Dictionary< ModLoader, string > DisableReason
void Remove(ModLoader modLoader)
void Add(ModLoader modLoader)
static string GameVersion
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
static List< ModLoader > ModLoaders
static NuGetVersion APINuGetVersion
static ModInfo DeserializeJson(string json)
static bool TryInvoke(ModHook modHook, ModLoader modLoader, Func< ModLoader, bool > action)
static string UserDataPath
static string APIReleasesLink_Client
static byte[] StreamToBytes(Stream stream)
将 Stream 转成 byte[]
static string ModsSettingsPath
static void AddException(Exception e, bool AllowContinue_=false)
static string HeadingCode2
static bool GetModEntity(string packagename, out ModEntity modEntity)
static string HeadingCode
static bool FindElement(XElement xElement, Func< XElement, bool > func, out XElement elementout)
static void CombineCrLogic(XElement xElement, XElement needCombine)
static bool FindElementByGuid(XElement xElement, string guid, out XElement elementout)
static bool HasAttribute(XElement element, Func< string, bool > func, out XAttribute xAttributeout)
static Dictionary< string, ModEntity > PackageNameToModEntity
含所有已启用的模组
static void DisableHook(ModLoader from, string HookName, string packageName, string reason)
static string ScreenCapturePath
const ApiVersionEnum ApiVersion
static void CombineClo(XElement clothesRoot, Stream toCombineStream)
static void LoadModSettings(XElement xElement)
static Dictionary< string, ModHook > ModHooks
static Dictionary< string, List< ClassSubstitute > > ClassSubstitutes
static void HookActionReverse(string HookName, Func< ModLoader, bool > action)
static void SetConfig(string key, string value)
static string CharacterSkinsDirectoryName
static string CommunityContentCachePath
static void CombineCr(XElement xElement, Stream cloorcr)
static string BlockTexturesDirectoryName
static ModEntity SurvivalCraftModEntity
static string WorldsDirectoryName
static string SettingPath
static string OriginalCommunityContentCachePath
static string APILatestReleaseLink_API
static Dictionary< string, ClassSubstitute > SelectedClassSubstitutes
static void GetScmods(string path)
获取所有文件
static string GetSha256(string input)
static Dictionary< string, List< ClassSubstitute > > OldClassSubstitutes
static bool AllowContinue
static string GetMd5(string input)
static string FurniturePacksDirectoryName
static string ShortGameVersion
static string ProcessModListPath
static void LoadConfigs()
static bool StrengtheningMod(string path)
static List< ModEntity > ModList
所有已启用的模组
static string APIVersionString
static Dictionary< string, HashSet< string > > DisabledMods
static string ShortAPIVersionString
static string APILatestReleaseLink_Client
static void Modify(XElement source, XElement change)
static string ExternalPath
static bool GetAllowContinue()
static void CombineDataBase(XElement databaseRoot, Stream toCombineStream)
static void LoadConfigsFromXml(XElement xElement)
static T GetInPakOrStorageFile< T >(string filePath, string suffix="txt")
static Dictionary< string, string > Configs
static Dictionary< string, Assembly > Dlls
static void ModListAllDo(Action< ModEntity > entity)
static void RegisterHook(string HookName, ModLoader modLoader)
注册Hook
static FrozenDictionary< string, string > ImportantDatabaseClasses
static void DealWithClassSubstitutes()
static string ConfigsPath
static void CombineDataBase(XElement databaseRoot, Stream toCombineStream, string modPackageName)
static List< ModEntity > ModListAll
所有模组,含禁用的
static Dictionary< KeyValuePair< ModHook, ModLoader >, bool > m_hookBugLogged
static bool TryParseVersionRange(string value, out VersionRange versionRange)
static string StreamToString(Stream stream)
static void SaveConfigs()
static void SaveModSettings(XElement xElement)
static Stream GetDecipherStream(Stream stream)
static string APIReleasesLink_API
static string ImportMod(string name, Stream stream)
static void InitImportantDatabaseClasses()
static XElement LoadXmlFromStream(Stream stream, Encoding encoding, bool throwOnError)
static void SaveXmlToStream(XElement node, Stream stream, Encoding encoding, bool throwOnError)