深北兼容

创作者: misto_fixes
已更新:2026-09-19 02:25:16
8KB

关于此 MOD

恢复两个 Valheim 1.0 方法重载,使为旧版游戏构建的模组仍能正常运行。部分较旧的模组需要此项支持。

深北兼容

一个小型BepInEx补丁器,用于 英灵神殿 1.0(极北之地)它重新添加了两个游戏方法,其签名在1.0版本中发生了改变,改变方式是 添加可选尾随参数,因此为旧版游戏制作的模组仍能继续使用 不修改他们的文件:

恢复(旧版)过载 转发至 (1.0)
角色.消息(类型, 消息, 数量, 图标) 消息(type, msg, amount, icon, log = false)
SEMan.AddStatusEffect(哈希, 重置时间, 物品等级, 技能等级) 相同 + 变体 = 0

Smoothbrain的挖矿、畜牧和ComfortTweaks等旧模组需要它。一旦这些模组作者更新,就不再需要这个包了。如果游戏已经有了旧的过载,它不会做任何事情,而且它失败也不会阻止游戏启动。

注意: 添加重载会使该方法的查找变得 仅按名称 含糊不清,所以这里只针对这两个方法做兼容。那些不带参数类型修补这些方法的模组可能会受影响。

AI 披露: 此补丁程序是在AI(Anthropic的Claude)协助下编写的,随后在Valheim 1.0正式版专用服务器上进行了测试。

MIT 许可。源代码(整个修补程序):

误认兼容.cs
这是BepInEx预加载器补丁:通过给末尾参数添加默认值,恢复Valheim 1.0(Deep North)所移除的API重载,使为旧版游戏构建的模组无需修改其DLL即可继续工作。此为本项目自有代码,不再分发任何模组。每个恢复的重载都会转发到新方法,并用新末尾参数声明的默认值(或default(T))填充它们。仅处理下方白名单中的方法。注意:每添加一个重载,都会使对该方法仅按名称进行的反射/Harmony查找产生歧义。using System; using System.Collections.Generic; using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; public static class MistookenCompatPatcher { // 类型、方法、模组仍会调用的旧参数类型(完整名称)。 static readonly string[][] Shims = new string[][] { new string[] { "Character", "Message", "MessageHud/MessageType", "System.String", "System.Int32", "UnityEngine.Sprite" }, new string[] { "SEMan", "AddStatusEffect", "System.Int32", "System.Boolean", "System.Int32", "System.Single" }, // 有意不进行兼容处理:Piece.SetCreator、EffectList.Create、PlayerProfile.IncrementStat。保持更新的模组 //(例如PlantEverything)会按名称对这些方法打补丁;第二个重载会使Harmony的查找产生歧义并导致它们损坏。 }; public static IEnumerable<string> TargetDLLs { get { yield return "assembly_valheim.dll"; } } public static void Patch(AssemblyDefinition assembly) { foreach (string[] s in Shims) { try { AddForwardingOverload(assembly.MainModule, s[0], s[1], s.Skip(2).ToArray()); } catch (Exception) { /* 某个兼容处理失败绝不能阻止游戏启动 */ } } } static bool ParamsMatch(MethodDefinition m, string[] oldTypes, int count) { if (m.Parameters.Count != count) return false; for (int i = 0; i < oldTypes.Length && i < count; i++) if (m.Parameters[i].ParameterType.FullName != oldTypes[i]) return false; return true; } static void AddForwardingOverload(ModuleDefinition module, string typeName, string methodName, string[] oldTypes) { TypeDefinition type = module.GetType(typeName); if (type == null) return; if (type.Methods.Any(m => m.Name == methodName && ParamsMatch(m, oldTypes, oldTypes.Length))) return; // 已存在 MethodDefinition target = type.Methods.FirstOrDefault(m => m.Name == methodName && m.Parameters.Count > oldTypes.Length && ParamsMatch(m, oldTypes, m.Parameters.Count)); if (target == null) return; MethodAttributes attrs = MethodAttributes.Public | MethodAttributes.HideBySig; if (target.IsStatic) attrs |= MethodAttributes.Static; MethodDefinition shim = new MethodDefinition(methodName, attrs, target.ReturnType); shim.HasThis = !target.IsStatic; for (int i = 0; i < oldTypes.Length; i++) shim.Parameters.Add(new ParameterDefinition(target.Parameters[i].Name, ParameterAttributes.None, target.Parameters[i].ParameterType)); shim.Body.InitLocals = true; ILProcessor il = shim.Body.GetILProcessor(); if (!target.IsStatic) il.Emit(OpCodes.Ldarg_0); for (int i = 0; i < oldTypes.Length; i++) il.Emit(OpCodes.Ldarg, shim.Parameters[i]); for (int i = oldTypes.Length; i < target.Parameters.Count; i++) EmitDefault(shim, il, target.Parameters[i]); il.Emit(target.IsStatic || !target.IsVirtual ? OpCodes.Call : OpCodes.Callvirt, target); il.Emit(OpCodes.Ret); type.Methods.Add(shim); } static void EmitDefault(MethodDefinition shim, ILProcessor il, ParameterDefinition p) { if (p.HasConstant && p.Constant != null) { object c = p.Constant; if (c is bool) { il.Emit(((bool)c) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); return; } if (c is int) { il.Emit(OpCodes.Ldc_I4, (int)c); return; } if (c is short) { il.Emit(OpCodes.Ldc_I4, (int)(short)c); return; } if (c is byte) { il.Emit(OpCodes.Ldc_I4, (int)(byte)c); return; } if (c is float) { il.Emit(OpCodes.Ldc_R4, (float)c); return; } } TypeDefinition def = p.ParameterType.Resolve(); if (def != null && def.IsValueType) { VariableDefinition loc = new VariableDefinition(p.ParameterType); shim.Body.Variables.Add(loc); il.Emit(OpCodes.Ldloca, loc); il.Emit(OpCodes.Initobj, p.ParameterType); il.Emit(OpCodes.Ldloc, loc); } else il.Emit(OpCodes.Ldnull); } }

Valheim: 英灵神殿 的热门 MOD

探索适用于 Valheim: 英灵神殿 的最佳MOD,带来新功能、升级画面,以及令人兴奋的方式来改变您的游戏体验。

使用 Xmod 解锁 Valheim: 英灵神殿 的全部潜力 — 今天就探索这些顶级 MOD!