You are viewing a potentially older version of this package. View all versions.
GymMed-Mods_Communicator-1.2.0 icon

Mods Communicator

Outward Mods Communicator enables seamless communication between mods through shared events and configuration syncing. It also lets users override any changes made by other mods, giving them full control over their settings.

Date uploaded a day ago
Version 1.2.0
Download link GymMed-Mods_Communicator-1.2.0.zip
Downloads 75
Dependency string GymMed-Mods_Communicator-1.2.0

This mod requires the following mods to function

sinai-dev-SideLoader-3.8.4 icon
sinai-dev-SideLoader

API and Mod Development Toolkit for Outward.

Preferred version: 3.8.4
BepInEx-BepInExPack_Outward-5.4.19 icon
BepInEx-BepInExPack_Outward

BepInEx pack for Outward.

Preferred version: 5.4.19

README

Outward Mods Communicator


Outward game setting to require enchantment recipe when enchanting.

Outward Mods Communicator enables seamless communication between mods through shared events and configuration syncing. It also lets users override any changes made by other mods, giving them full control over their settings. You can find library published on NuGet as Outward.ModsCommunicator.

Why should I use this?

Benefits of using this library:

Configuration Syncing

This library allows mod pack creators to synchronize configuration files without directly editing them. Users don’t need to download configuration files from third-party sources. Configurations can be edited through XML, and the control flow follows this order: User -> Mod -> Cfg Documents

Deeper explanation Currently, Outward's BepInEx does not provide a built-in way for mods to modify .cfg configuration files inside the BepInEx/config directory. Mods Communicator solves this by using two XML files. One XML file is placed in the mod’s plugin directory (recommended), and Mods Communicator uses it to override configuration settings right after the ResourcesPrefabManager class finishes its Load method. Afterwards, it reads the player’s PlayerModsOverrides.xml file, located in BepInEx/config/gymmed.Mods_Communicator folder, to apply personal overrides based on the player’s preferences.

FAQ

Why use XML instead of hardcoding values in the assembly/code/DLL? XML is used so players can freely edit values without needing to modify any code. The XML structure is simple, human-readable, and gives full control to the user.
Why are there two XML files? Mods can be updated frequently, and each update may include new default XML values. By separating the player’s personal overrides into a second XML file, updates won’t overwrite their custom settings. Mods Communicator only provides a BepInEx/config/gymmed.Mods_Communicator/PlayerModsOverrides.example.xml file — players must rename it to BepInEx/config/gymmed.Mods_Communicator/PlayerModsOverrides.xml. This makes their configuration safe from updates and re-downloads.
Why are XML files read after the ResourcesPrefabManager.Load method? Because all plugins and their configurations must be initialized first. Once ResourcesPrefabManager.Load completes, all .cfg files are loaded, and it becomes safe to apply overrides.
Does every mod that changes settings through configs need Mods Communicator as a dependency? No. The Mods Communicator library is only required for mods that want to modify other mods’ default values to create new experiences. For example, the Outward Game Settings mod uses this dependency solely for the EventBus feature to publish additional events.
Changing Configuration As User This library includes PlayerModsOverrides.example.xml file inside your BepInEx/config/gymmed.Mods_Communicator folder. You will need to change it's name to PlayerModsOverrides.xml when you can open it to add or modify XML values.
Adding Configuration Path To Mod You can add your configuration XML path inside your plugin’s Awake method like this: OutwardModsCommunicator.OMC.xmlFilePath = "FullPathTo/MyModsOverrides.xml";
Editing XML This library will contain BepInEx/config/gymmed.Mods_Communicator/PlayerModsOverrides.example.xml document as an example. Each override is added inside a ConfigOverrides element:
<ConfigOverrides>
  <Mod GUID="gymmed.outward_game_settings">
    <Section Name="Enchanting Modifications">
      <Entry Key="EnchantingSuccessChance" Value="5" />
      <Entry Key="RequireRecipeToAllowEnchant" Value="false" />
      <Entry Key="UseRecipeOnEnchanting" Value="false" />
    </Section>
  </Mod>
  <Mod GUID="gymmed.outward_mods_communicator">
    <Section Name="Event Profiler">
      <Entry Key="EnableEventsProfiler" Value="true" />
      <Entry Key="InstantLogEventsProfileData" Value="true" />
    </Section>
  </Mod>
</ConfigOverrides>
Possible mod override information can be found in BepInEx/config directory inside .cfg documents
## Settings file was created by plugin Outward Game Settings v0.0.1
## Plugin GUID: gymmed.outward_game_settings

[Enchanting Modifications]

## Allow enchanting only if enchantment is on character?
# Setting type: Boolean
# Default value: true
RequireRecipeToAllowEnchant = false

## Remove recipe after using it on enchanting?
# Setting type: Boolean
# Default value: true
UseRecipeOnEnchanting = false

## What is success chance(%) of enchanting?
# Setting type: Int32
# Default value: 50
# Acceptable value range: From 0 to 100
EnchantingSuccessChance = 5

## Play additional audio on enchanting failed/success?
# Setting type: Boolean
# Default value: true
PlayAudioOnEnchantingDone = true

Mods Communication

Communication is handled through an Event Bus — a system that allows mods to fire (publish) and listen (subscribe) to shared events.

Deeper Explanation

Outward’s BepInEx framework uses Harmony for patching — allowing mods to modify or extend existing game logic. However, Harmony alone cannot handle communication between mods. That’s where the Event Bus comes in.

Harmony and the Event Bus serve different purposes:

Harmony — Modify Existing Behavior

Harmony is a patching library that injects code before, after, or inside existing game methods. It’s great for changing how things work but not for sharing data between mods.

  • Pros:
    • Perfect for tweaking existing systems (combat, AI, loot, etc.).
    • Gives direct control over the game’s original methods.
  • Cons:
    • Can only modify what already exists.
    • Requires DLL references to patch another mod’s code.
    • Breaks easily when mods or the game update.
    • Cannot define new, reusable communication points for others.

Harmony changes how things behave — not how mods talk to each other.

Event Bus — Enable Mod Communication

The Event Bus allows mods to publish and subscribe to events without referencing each other’s DLLs. It introduces a safe, modular way for mods to share information and react to in-game events.

  • Advantages:
    • No fragile DLL dependencies or version mismatches.
    • Mods stay modular — one mod can publish, others can listen.
    • Supports entirely new custom events that didn’t exist before.

Example: A Game Settings mod can publish an OnEnchantSuccess event. Another mod can listen for it and play new sounds, change visuals, or trigger additional effects when enchantments succeed.

FAQ

Can’t I just patch another mod’s method?

You can — but it’s fragile. You’ll need to include that mod’s DLL as a dependency, and any update to it can break your patch. The Mods Communicator Event Bus avoids this problem — mods only publish and subscribe to shared events, keeping them safe and compatible.

Can I create libraries with Mods Communicator?

Yes. You can create lightweight library mods that listen for published events and transform complex logic into simpler, abstracted event calls. Example: The Loot Manager listens for death events and injects new loot.

How does this help implement new features?

The Game Settings Mod adds enchantment success chance and exposes success/failure events. Other mods can subscribe to these to:

  • Disable default enchantment sounds.(Through config synchronization)
  • Play new audio clips or effects.
  • Trigger visual cues or animations on success or failure.

Summary: Harmony modifies existing game behavior. Event Bus enables safe, modular mod communication. Together, they make Outward’s modding ecosystem more powerful and extensible.

How to register event?
using OutwardModsCommunicator.EventBus;
...
void Awake()
{
    ...
    // GUID is your plugin ID provided as a string
    // "EnchantmentMenu@TryEnchant" is the event name
    // ("menu", typeof(EnchantmentMenu)) defines your variable name and its type
    EventBus.RegisterEvent(GUID, "EnchantmentMenu@TryEnchant", ("menu", typeof(EnchantmentMenu)));
    // add optional event description
    // EventBus.RegisterEvent(GUID, "EnchantmentMenu@TryEnchant", "Event fired before calculating enchantment success/failure.", ("menu", typeof(EnchantmentMenu)));
    // add optional description about parameter(is variable optional?)
    //EventBus.RegisterEvent(GUID, "EnchantmentMenu@TryEnchant", ("menu", typeof(EnchantmentMenu), "The enchantment menu instance that invoked the TryEnchant method."));
    // you can add multiple variables and
    // add as many as you need like this:
    //EventBus.RegisterEvent("MyPluginId", "MyClass@MyMethod", ("name", typeof(string)), ("health", typeof(int)));
    ...
}
How to publish event? Use this in places where you want to allow other mods to extend your functionality:
using OutwardModsCommunicator.EventBus;
...
void YourMethod()
{
    ...
    // Add variable receiver names and your variables references
    var payload = new EventPayload
    {
        // Will get it as named menu
        ["menu"] = yourVariable,
    };
    // Send event for subscribers to receive data
    EventBus.Publish(OutwardGameSettings.GUID,  "EnchantmentMenu@TryEnchant", payload);
}
How to subscribe to event? Use this when you want to listen to an event and execute additional code:
using OutwardModsCommunicator.EventBus;
...
void Awake()
{
    ...
    // Provide other mod GUID
    // Provide event name
    // Provide method you want to execute
    EventBus.Subscribe("gymmed.outward_game_settings", "EnchantmentMenu@TryEnchant", OnTryEnchant);
}
private static void OnTryEnchant(EventPayload payload)
{
    if (payload == null) return;
    // try to retrieve passed event data
    EnchantmentMenu menu = payload.Get<EnchantmentMenu>("menu", null);
    // if event data is null log and stop execution
    if (menu == null)
    {
        Log.LogMessage("Mod gymmed.outward_game_settings event EnchantmentMenu@TryEnchant returned null for EnchantmentMenu");
        // log received payload for errors inspection
        EventBusDataPresenter.LogPayload(payload);
        return;
    }
    // Lets log success
    Log.LogMessage($"{GUID} successfully communicated with gymmed.outward_game_settings mod and passed menu!");
}
How to get all registered events? Use this when you want to log or inspect all registered events:
using OutwardModsCommunicator.EventBus;
...
// We use harmony patch to execute code after each plugin is loaded
// and have already registered their events
[HarmonyPatch(typeof(ResourcesPrefabManager), nameof(ResourcesPrefabManager.Load))]
public class ResourcesPrefabManager_Load
{
    static void Postfix(ResourcesPrefabManager __instance)
    {
        // Log all registered events
        EventBusDataPresenter.LogRegisteredEvents();
        // Log all subsribers
        EventBusDataPresenter.LogAllModsSubsribers();
    }
}

The project also includes extra tools like EventProfiler and EventBusDataPresenter — feel free to explore them to learn more.

Can I find basic example how to use this?

You can view mod creation template here.
You can view outward game settings mod here.
You can view outward scene tester mod here.
You can view more complex example outward loot manager mod here.

How to set up

To manually set up, do the following

  1. Create the directory: Outward\BepInEx\plugins\OutwardModsCommunicator\.
  2. Extract the archive into any directory(recommend empty).
  3. Move the contents of the plugins\ directory from the archive into the BepInEx\plugins\OutwardModsCommunicator\ directory you created.
  4. It should look like Outward\BepInEx\plugins\OutwardModsCommunicator\OutwardModsCommunicator.dll Launch the game.

If you liked the mod leave a star on GitHub it's free

CHANGELOG

Changelog

Release 1.2.0 Version

Added

  • Added support for optional event description when registering events. Example: EventBus.RegisterEvent( GUID, "yourEvent", "your event description", ("yourVariableRetrievalKey", typeof(string), "Your variable description.") );

Fixed

  • Fixed readme code blocks.
  • Changed how EventBusDataPresenter shows logs. Now it is much clearer.

Release 1.1.0 Version

Added

  • Added support for optional parameter descriptions when registering events. Example: EventBus.RegisterEvent( GUID, "EnchantmentMenu@TryEnchant", ("menu", typeof(EnchantmentMenu), "The enchantment menu instance that invoked the TryEnchant method.") );
  • Added more text to readme description

Fixed

  • Moved the PlayerModsOverrides.example.xml file to BepInEx/config/gymmed.Mods_Communicator/ to ensure configuration files remain untouched after updates — even after renaming .example to enable custom overrides.

Release 1.0.1 Version

Fixed

  • Made sure to load PlayerModsOverrides.xml even if xmlFilePath variable is not provided from mods
  • Changed readme description

Release 1.0.0 Version

  • Initial release.