IceBoxModLib 使用说明 / User Manual
Updated 3 weeks agoIceBoxModLib 模组作者使用说明
IceBoxModLib 是一个面向《Roadside Research》BepInEx IL2CPP 模组开发的公共库。它将多个模组里重复使用的基础能力统一封装起来,帮助你更快地实现配置、本地化、运行时 UI 提示、图片加载与 IL2CPP 类型注册。
说明:本手册面向模组作者,并提供中英双语版本。英文内容位于中文内容下方。
Note: This guide is intended for mod authors and is provided in both Chinese and English. The English section is below the Chinese section.
中文
适用场景
- 你正在为《Roadside Research》开发 BepInEx IL2CPP 模组
- 你希望多个模组共用统一的基础代码,而不是在每个项目里重复复制
- 你需要简化配置项注册、本地化切换、通知提示、运行时图片替换或自定义
MonoBehaviour注册
环境要求
- 游戏版本:
0.1.85+ - 模组加载器:
BepInEx IL2CPP 6.0.0 be.755 - 前置安装位置:
BepInEx/plugins/IceBoxModLib.dll
接入方式
- 将
IceBoxModLib.dll放入游戏的BepInEx/plugins目录。 - 在你的模组项目中引用
IceBoxModLib.dll,或直接添加项目引用。 - 在插件入口类上声明硬依赖,确保库优先加载。
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
[BepInDependency(IceBoxModLib.PluginInfo.PLUGIN_GUID, BepInDependency.DependencyFlags.HardDependency)]
public class YourMod : BasePlugin
{
}
前置信息
- 库 GUID:
IceBoxStudio.RoadsideResearch.ModLib - 库名称:
IceBoxModLib - 当前版本:
1.0.0
可用模块
IceBoxModLib.Config:配置基类,封装常用ConfigEntry注册方法IceBoxModLib.Localization:本地化服务,跟随游戏语言切换,并支持回退语言IceBoxModLib.UI:屏幕底部弹出式通知提示IceBoxModLib.Utilities:外部图片加载、Sprite 替换、容器 UI 刷新等工具IceBoxModLib.Runtime:IL2CPP 自定义类型注册辅助工具
1. 配置管理
如果你的模组有多个配置项,建议创建一个继承 ModConfigBase 的配置管理类。这个基类已经封装了常见类型的注册方法:
RegisterBoolRegisterStringRegisterKeyCodeRegisterInt / RegisterIntRangeRegisterFloat / RegisterFloatRange
public class ConfigManager : ModConfigBase
{
public ConfigEntry<bool> EnableFeature { get; private set; }
public ConfigEntry<string> FileName { get; private set; }
public ConfigManager(ConfigFile configFile) : base(configFile)
{
EnableFeature = RegisterBool("General", "EnableFeature", "是否启用功能", true);
FileName = RegisterString("Advanced", "FileName", "文件名", "example.png");
}
}
这样做的好处是,你可以保持每个模组的配置结构统一,也更方便后续维护。
2. 多语言支持
ModLocalizationService 会监听游戏的 I2 Localization 语言变化事件,并自动把当前语言切换到你声明支持的语言;如果当前语言不在支持列表中,则自动回退到指定语言。
推荐使用方式:
- 定义你的支持语言列表。
- 初始化
ModLocalizationService。 - 为每种语言添加一个键值字典。
- 通过
GetText获取文本,并按需传入格式化参数。
private readonly ModLocalizationService _service =
new ModLocalizationService(new[] { "简体中文", "繁體中文", "English", "日本語" }, "English");
_service.AddTranslations("English", new Dictionary<string, string>
{
{ "notification.done", "Done" }
});
_service.AddTranslations("简体中文", new Dictionary<string, string>
{
{ "notification.done", "已完成" }
});
string text = _service.GetText("notification.done");
如果当前语言缺少对应 key,库会继续尝试读取回退语言;如果回退语言也不存在,则直接返回 key 本身,便于排查缺失文本。
3. UI 通知
如果你想在屏幕底部显示一条轻量提示,可以直接调用 ModNotification.Show。库内部会自动创建并复用通知对象。
ModNotification.Show("设置已保存");
ModNotification.Show("操作成功", 3.5f, new Color(0.55f, 1f, 0.55f, 1f));
ModNotification.Dismiss();
说明:
- 默认显示时长为
5秒 - 第三个参数可选,用于设置文字颜色
- 通知对象由库统一管理,你无需自己创建
Canvas或 UI 物体
4. 图片加载与替换
ImageLoader.LoadSpriteFromFile 适合从磁盘读取 PNG、JPG 等外部图片并转换为 Unity Sprite。这个方法已经处理了 IL2CPP 环境下常见的纹理与精灵生命周期问题。
string imagePath = Path.Combine(pluginDir, "wallpaper.png");
Sprite sprite = ImageLoader.LoadSpriteFromFile(imagePath);
如果你已经拿到了某个 UI 根节点,也可以用 ReplaceImageBySpriteName 在子节点中查找 Image 组件,并把指定名称的原始 Sprite 替换成新的 Sprite。
bool replaced = ImageLoader.ReplaceImageBySpriteName(
rootTransform,
"PCBackground_Naked",
sprite
);
使用建议:
- 传入绝对路径,而不是相对路径
- 优先把外部资源放在你的模组 DLL 同目录,便于发布与排错
- 替换 UI 图片时,建议先通过 UnityExplorer 确认原始
Sprite名称
5. 容器 UI 刷新
当你的模组通过代码修改了 Store.ItemContainer 的数量,例如调用 TryRemoveItem 或 AddItem 后,游戏中货架上的数量标签不会自动更新。调用 ItemContainerRefreshHelper.Refresh 可以立即刷新对应标签。
using IceBoxModLib.Utilities;
// 从容器中取走物品后刷新 UI
int removed = container.TryRemoveItem(amount);
if (removed > 0)
{
ItemContainerRefreshHelper.Refresh(container);
}
说明:
- 适用于所有
ItemContainer子类,例如Shelf、Box - 会自动同步 Fusion 网络状态、更新 3D 物品视觉、刷新数量标签和库存总量标签
- 内部使用
2秒缓存避免频繁调用时的性能开销 - 如果场景中的货架数量发生了变化,例如新放置或移除,可调用
ItemContainerRefreshHelper.InvalidateCache()清除缓存
如果你修改了容器中的物品类型,而不仅是数量,可以传入第二个参数指定变更前的物品:
Item previousItem = container.Item;
// ... 修改物品 ...
ItemContainerRefreshHelper.Refresh(container, previousItem);
6. IL2CPP 类型注册
如果你的模组需要在运行时创建自定义 MonoBehaviour,请先调用 Il2CppTypeRegistry.RegisterType<T>()。它会自动避免重复注册。
public class YourBehaviour : MonoBehaviour
{
public YourBehaviour(IntPtr ptr) : base(ptr)
{
}
}
Il2CppTypeRegistry.RegisterType<YourBehaviour>();
GameObject go = new GameObject("YourObject");
UnityEngine.Object.DontDestroyOnLoad(go);
go.AddComponent<YourBehaviour>();
适用情况:
- 动态创建常驻管理器对象
- 在场景切换后继续保留行为组件
- 为补丁逻辑挂接
Update、OnGUI等 Unity 生命周期
推荐集成顺序
- 先声明对
IceBoxModLib的硬依赖 - 再初始化配置与本地化
- 随后注册你的 IL2CPP 类型并创建常驻对象
- 最后再应用 Harmony 补丁或启动业务逻辑
发布建议
- 面向玩家发布时,不要将
IceBoxModLib.dll打包进你的模组压缩包 - 请在 Nexus Mods 页面通过 Requirements 明确声明
IceBoxModLib为必需前置,并引导玩家单独下载 - 如果你的模组依赖外部图片或数据文件,请把这些资源和 DLL 放在同一模组目录中
- 在模组页面明确标注
IceBoxModLib为必需前置,可以减少缺依赖导致的报错反馈
适合配合本库的功能示例
- 自动化操作类模组:使用配置项控制开关,用通知反馈执行结果,用容器刷新工具确保 UI 同步
- 带多语言文本的 UI 模组:用本地化服务统一管理显示文本
- 自定义贴图、图标、壁纸类模组:用图片工具加载外部资源并替换 UI 图像
- 需要常驻管理器的系统型模组:用 IL2CPP 类型注册创建自己的 Behaviour
问题反馈
如果你在开发中发现库缺少某些通用能力,或者某个 API 不够方便使用,欢迎通过 GitHub Issues 提交建议。
English
When to Use It
- You are developing a BepInEx IL2CPP mod for Roadside Research
- You want to reuse a common foundation instead of copying the same helper code into every project
- You need a simpler workflow for config registration, language switching, notifications, runtime image replacement, or custom
MonoBehaviourregistration
Requirements
- Game version:
0.1.85+ - Mod loader:
BepInEx IL2CPP 6.0.0 be.755 - Required install path:
BepInEx/plugins/IceBoxModLib.dll
How to Integrate
- Put
IceBoxModLib.dllinto the game'sBepInEx/pluginsfolder. - Reference
IceBoxModLib.dllin your mod project, or add it as a project reference. - Declare a hard dependency on your plugin entry class so the library is loaded first.
[BepInPlugin(PluginInfo.PLUGIN_GUID, PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)]
[BepInDependency(IceBoxModLib.PluginInfo.PLUGIN_GUID, BepInDependency.DependencyFlags.HardDependency)]
public class YourMod : BasePlugin
{
}
Library Info
- GUID:
IceBoxStudio.RoadsideResearch.ModLib - Name:
IceBoxModLib - Current version:
1.0.0
Available Modules
IceBoxModLib.Config: Base class for configuration helpers and commonConfigEntryregistrationIceBoxModLib.Localization: Localization service with game language tracking and fallback supportIceBoxModLib.UI: Lightweight bottom-screen notification popupsIceBoxModLib.Utilities: External image loading, sprite replacement, and container UI refresh utilitiesIceBoxModLib.Runtime: IL2CPP custom type registration helpers
1. Configuration Management
If your mod has multiple configuration entries, it is recommended to create a config manager class that inherits from ModConfigBase. The base class already wraps the most common registration helpers:
RegisterBoolRegisterStringRegisterKeyCodeRegisterInt / RegisterIntRangeRegisterFloat / RegisterFloatRange
public class ConfigManager : ModConfigBase
{
public ConfigEntry<bool> EnableFeature { get; private set; }
public ConfigEntry<string> FileName { get; private set; }
public ConfigManager(ConfigFile configFile) : base(configFile)
{
EnableFeature = RegisterBool("General", "EnableFeature", "Enable feature", true);
FileName = RegisterString("Advanced", "FileName", "File name", "example.png");
}
}
This keeps your config structure consistent across projects and makes long-term maintenance easier.
2. Localization
ModLocalizationService listens to the game's I2 Localization language change event and automatically switches to the current game language if it is included in your supported list. If not, it falls back to the language you specify.
Recommended flow:
- Define your supported languages.
- Initialize
ModLocalizationService. - Add one translation dictionary per language.
- Use
GetTextto read localized text, with optional formatting arguments.
private readonly ModLocalizationService _service =
new ModLocalizationService(new[] { "简体中文", "繁體中文", "English", "日本語" }, "English");
_service.AddTranslations("English", new Dictionary<string, string>
{
{ "notification.done", "Done" }
});
_service.AddTranslations("简体中文", new Dictionary<string, string>
{
{ "notification.done", "已完成" }
});
string text = _service.GetText("notification.done");
If the current language is missing a key, the library tries the fallback language next. If that is also missing, it returns the key itself, which makes missing entries easier to spot during development.
3. UI Notifications
If you want to show a lightweight message near the bottom of the screen, call ModNotification.Show directly. The library creates and reuses the notification object for you.
ModNotification.Show("Settings saved");
ModNotification.Show("Operation succeeded", 3.5f, new Color(0.55f, 1f, 0.55f, 1f));
ModNotification.Dismiss();
Notes:
- Default display duration is
5seconds - The third parameter is optional and controls the text color
- You do not need to create your own
Canvasor notification object
4. Image Loading and Replacement
ImageLoader.LoadSpriteFromFile is intended for loading external PNG and JPG assets from disk and converting them into Unity Sprite objects. It already handles common texture and sprite lifetime issues in IL2CPP environments.
string imagePath = Path.Combine(pluginDir, "wallpaper.png");
Sprite sprite = ImageLoader.LoadSpriteFromFile(imagePath);
If you already have a UI root transform, you can also use ReplaceImageBySpriteName to find child Image components and replace the original sprite by name.
bool replaced = ImageLoader.ReplaceImageBySpriteName(
rootTransform,
"PCBackground_Naked",
sprite
);
Recommended practice:
- Use absolute file paths instead of relative paths
- Keep external assets in the same directory as your mod DLL whenever possible
- Use UnityExplorer first if you need to inspect the original sprite name in the target UI
5. Container UI Refresh
When your mod programmatically modifies a Store.ItemContainer quantity, such as after calling TryRemoveItem or AddItem, the quantity labels on shelves will not update automatically. Calling ItemContainerRefreshHelper.Refresh will immediately refresh the corresponding labels.
using IceBoxModLib.Utilities;
// Refresh UI after removing items from a container
int removed = container.TryRemoveItem(amount);
if (removed > 0)
{
ItemContainerRefreshHelper.Refresh(container);
}
Notes:
- Works with all
ItemContainersubclasses, such asShelfandBox - Automatically syncs Fusion network state, updates 3D item visuals, refreshes quantity labels, and refreshes stock total labels
- Uses a
2second internal cache to avoid performance overhead when called frequently - If shelves are added or removed from the scene, call
ItemContainerRefreshHelper.InvalidateCache()to clear the cache
If you are changing the item type in a container, not just the quantity, pass the previous item as the second parameter:
Item previousItem = container.Item;
// ... modify item ...
ItemContainerRefreshHelper.Refresh(container, previousItem);
6. IL2CPP Type Registration
If your mod creates a custom MonoBehaviour at runtime, call Il2CppTypeRegistry.RegisterType<T>() first. It automatically avoids duplicate registrations.
public class YourBehaviour : MonoBehaviour
{
public YourBehaviour(IntPtr ptr) : base(ptr)
{
}
}
Il2CppTypeRegistry.RegisterType<YourBehaviour>();
GameObject go = new GameObject("YourObject");
UnityEngine.Object.DontDestroyOnLoad(go);
go.AddComponent<YourBehaviour>();
Typical use cases:
- Persistent manager objects created at runtime
- Components that should survive scene changes
- Systems that need Unity lifecycle methods such as
UpdateorOnGUI
Recommended Initialization Order
- Declare the hard dependency on
IceBoxModLibfirst - Initialize configuration and localization next
- Register your IL2CPP types and create persistent objects
- Apply Harmony patches or start gameplay logic afterward
Packaging Advice
- When publishing for players, do not package
IceBoxModLib.dllinside your mod archive - Declare
IceBoxModLibas a required dependency through the Nexus Mods Requirements section and direct users to download it separately - If your mod depends on images or data files, keep those resources in the same mod folder as the DLL
- Clearly mark
IceBoxModLibas a required dependency on your mod page to reduce missing-dependency reports
Good Fits for This Library
- Automation mods that need config toggles, simple execution feedback, and container UI sync after programmatic changes
- UI mods that need multilingual text management
- Wallpaper, icon, texture, or image replacement mods that load external assets
- System-style mods that need persistent manager behaviours in IL2CPP
Feedback
If you find that the library is missing a useful shared feature, or if an API could be made easier to use, feel free to submit suggestions through GitHub Issues.