Using Harmony for addons

Harmony is a library for patching and overriding C# code at runtime. I think this would be extremely powerful if addons could patch and modify the gamemode, rather than just slotting into predefined places. If you can find a way to sandbox it sufficiently, it might be worth looking into.

That way, gamemodes don’t have to be specifically designed for addons, and addons can do more than just what the game/gamemode provide APIs for. UnityModManager is an example of how to implement mods/addons this way - perhaps you would want to go with a more managed approach to guarantee that an addon’s patches are unloaded when the user requests for the addon to be unloaded in the UI.

The downside is that the power it gives requires a deep understanding of what it is you’re trying to do, and careless addons could break compatibility or even break the entire game in subtle ways. If you decide to go this route, it might be worth providing some easier options on top, so that addons can either use Harmony or just go with gamemode predefined slots (like adding new entities or toolguns in sandbox).

“Predefined slots” like adding new entities/toolguns/whatever would probably have to be added by the gamemode. I don’t think it would fit s&box to add this functionality itself, especially since those concepts might not exist in other gamemodes.

Gamemodes could declare which entrypoints they support, mods could declare which entrypoints they provide, and at runtime the gamemode could go over the entrypoints that are enabled and call into them however they like. A similar concept is used in Fabric, which is a powerful and lightweight modloader for Minecraft. In Fabric, mods can also call into the entrypoints of other mods, allowing for some pretty powerful integrations. S&box could probably support this too.

Looking forward to hearing feedback on these ideas.

No. Harmony is for things that were not made to be modded. Nobody would prefer to mod things using Harmony instead of just implementing some interface, extending some class, attaching some events, etc.

1 Like

That’s not what I’m proposing, I’m proposing to support both.

You should be able to mod any gamemode, even those without first-class addon support, AND any gamemode should be able to implement flexible, first-class addon support. So two things - Harmony and hooks/entrypoints/just subclassing/whatever (although this post proposes entrypoints specifically, as they are the most flexible).

There are cases where a patch shouldn’t have to be an entirely new gamemode and you might want to install multiple patches at once without having to pull in source trees locally and publish the modified gamemode as an entire new gamemode. Those patches could be Harmony where simply adding new content like new entities/toolguns/etc to Sandbox or whatever other gamemode wouldn’t have to use Harmony at all, but could if they wanted to.

2 Likes

Addons which extend other addons is something that will likely be worked on later. It’s just not a priority at the moment.

Either way Harmony isn’t really the solution here because addons include source code - no need to binary patch things.

2 Likes

Have you read the post, and my reply?

Let me try to sum it up for you:

Harmony use cases:

  • Making patches to existing codebases that you don’t want to reupload.
    • “Just reupload a patched version” is not a solution: Garry’s Mod has this problem, and look at the amount of duplicates there are - anytime someone needs to fix a bug in someone else’s addon, they need to reupload the entire codebase, even things they didn’t change, and these patches can’t be mixed (you can only choose 1 duplicate to install). Depending on the time the patch was created, these duplicates end up becoming varyingly out of date. If these patches were performed at runtime on an existing addon that can be updated independently by its developer, it would never go out of date unless the patch area itself were changed.
  • Allowing multiple patches to coexist and letting users mix and match them, without having to upload every permutation
  • Modifying code that does not explicitly call into addons (like modifying obscure properties or behaviors of the gravity gun for example)

Entrypoint use cases:

  • Allowing gamemodes and addons alike to query interfaces exposed by an addon and call directly into the addon’s implementation (for example, the Sandbox gamemode calling into an addon to query which props/entities it adds, so they can be added to the spawn menu)
  • That’s basically it, but it’s still extremely powerful, as long as the gamemode has specific code to query addons and call into them. S&box could have predefined entrypoints for server start and a couple other events, basically engine stuff common to every gamemode out there, but things like entity/prop spawning are completely Sandbox(gamemode)-specific and would need support from that specific gamemode.

Please take the time to read my post before replying.

1 Like

The Harmony use cases you listed can all be solved at the root: why is this addon not on Github? You should be able to submit a pull request with the patch instead of wasting time using Harmony to fix it or uploading a duplicate. If you want to be able to tweak things then you can add a way to tweak them.

Entrypoints… this is basically what S&box is going for already. You can query for things with the library system and there are some events already. More will come when S&box actually supports loading multiple addons.

3 Likes

With GitHub:

  • Opinionated patches won’t be accepted because the author doesn’t like them, even if some of the community would prefer the patch
  • You’d have to wait for the author to accept the patch and publish it

The only way to get around this would be to publish your own copy of the addon, which goes right back to the issue of duplicates and reuploads.

I get what you’re trying to go for - “in a perfect world, everyone would just work together and make the addons perfect and everyone would be happy!” But the world isn’t perfect. People want to modify addons in opinionated ways that not everyone likes, and not every addon would accept a PR adding a setting for it.

So no, GitHub is not the solution to everything. GitHub is only a solution if you’re adding features the author likes or fixing bugs that the author wants fixed - with everything else, you are forced to reupload if you don’t have access to Harmony.


I still think that Harmony should be an option. There are problems that cannot be solved by asking the addon/gamemode author to update the source code, because they might not want to.

What if I want to change some weird obscure property in the Sandbox gamemode that would never be accepted as a PR because some people like it the other way instead? Would I have to put in a bunch of work to make it modifiable by an addon, PR that instead, then make an addon that uses that? If you say “yes, because that’s the objectively correct way to do things”, this system is going to have the same issues that Forge has.

In Forge, there are regular mods, which exclusively use Forge’s APIs, and coremods, which modify the game’s code (kind of like Harmony does for C#). Forge is incredibly hostile towards coremods, and they will attack you and ban you from their server for even trying to talk about them. If you want to do something and it isn’t possible yet, they will tell you to make a PR or GTFO. I would hate for s&box to adopt this approach - it heavily stifles innovation because the APIs might not be there. It’s not like people can make a PR to s&box to add a feature they need. People can make a PR to a gamemode if it’s on GitHub, but again - if it’s a niche or opinionated API, the author might not add it.

In Fabric, the only way to make a mod is by modifying the game’s code. They have a flexible and powerful system (Mixin) which is a lot like Harmony, but for Java. It’s not only much easier to make mods for Fabric, but mods can do a lot more because they can insert hooks anywhere in the code they like. There is an official mod called “Fabric API” that includes a ton of hooks, but that isn’t necessary to make a mod - Fabric itself is just a mod loader that gives you Mixin and says “go wild”.

In S&box I would love to just go wild. I would like to use the entrypoints to get my code running, use APIs when possible, and use Harmony when I want to change existing code - just like I do in my existing C# mods. There are people out there who know how to use Harmony correctly.

You say that Harmony is for things that were not made to be modded. There can and will be gamemodes and parts of gamemodes that were not made to be modded. Completely replacing a tool to change 1 behavior is not something I want to do because it has the exact same issues as code duplication. Forge mods do this all the time while Fabric mods don’t have to. See a trend? Be Fabric, not Forge.

3 Likes

that’s a lot of things you just wrote but i’m seeing forge, fabric, mixin… are you talking about fucking minecraft?

1 Like

I’m comparing concepts that I’m trying to explain with other projects that do similar things, yes. It helps to find well-established examples when evaluating new ideas.

3 Likes

What about the developers that do not want their code to be overwritten?

How a patch can guarantee that with the new version release of mod it would work the same or at least wouldn’t break something else?

1 Like

Don’t use a high-level language like C#?

Well, the idea with patches is that it only breaks if the patch area is changed. So, if it’s an infrequently-changed or well-established part of the addon, it will continue working for a while before it needs to be updated. In the meantime, other parts of the addon can be updated without breaking the patch, and the patch author only has to watch carefully to see if they need to do something or not.

1 Like

GitHub is only a solution if you’re adding features the author likes or fixing bugs that the author wants fixed - with everything else, you are forced to reupload if you don’t have access to Harmony .

Sounds like the perfect time for a fork anyway. If you’re moving an addon into a different direction from the original then it will likely end up being more and more different in the future.

Don’t get me wrong - I use Harmony for a few things in Rust, but Harmony is honestly a terrible way to mod things. It’s cool and gets the job done but I would never choose it over properly moddable code. Nobody is going to prefer to write all of this code instead of being able to properly extend an addon.

All I’m trying to say is consider other possible alternatives before Harmony. There will be much nicer ways to go about this.

2 Likes

No. The perfect time for a fork is exactly what you’ve described, but not everything is that. Small tweaks that the author doesn’t support don’t necessarily warrant a fork. This isn’t for “moving in a different direction than the original” - I’m not going to extend my small patches into total overhauls and somehow keep those total overhauls as patches, that would be insane. That said, small patches shouldn’t have to be forked and reuploaded as they do now.

I never said instead of. I said in addition to. Harmony is a tool, and like all tools, it’s not perfect for everything. You probably shouldn’t write an addon exclusively in Harmony if you’re going to be adding tons of content and doing tons of, well, addon things.

The reason all of that code is used in the repository I linked is because it’s adding another case to the end of a long switch statement. It needs to grab references to locals and insert the new code before the end of the switch and assign stuff into those locals… basically, it is a patch that integrates deeply into the function.

I will admit that everything that addon does could have been done instead with a smartly designed addon API, and the only reason I have to use Harmony there is because the game was not meant to be modded, like you said above. But there are things that wouldn’t make sense to make available to addons because it’s just so niche. And of course, there are cases where an addon API doesn’t exist, like when you are modifying an addon that someone never expected to be extended.