What would make the game easier to mod?

Started by Tynan, June 10, 2016, 04:01:27 PM

Previous topic - Next topic

RawCode

oredic feature is not possible to implement with CCL or any other framework without early (before database) loading support from vanilla game.
(*properly*, it's possible to install hooks and reload database, but this will double loading type and likely to cause major memory leak)

not everyone is aware, but, all "core" mod developers are obviously aware about spigot\forge.

all community currently need is 4 very minor modifications of modloader about loading mod provided assemblies with specific tag very first, ever before GUI, everything else is perfectly possible with hooks.

1000101

Yes, as RawCode and I both suggested, we need a early code injection point while the game data is in an empty state.
(2*b)||!(2*b) - That is the question.
There are 10 kinds of people in this world - those that understand binary and those that don't.

Powered By

soulkata

As a simple suggestion, putting the Detours from CCL into the core game is a great addition! :P +1 Vote for this!

Below the simple suggestions, generally speaking, when I was actively modding Rimworld, I have 3 major issues:
1. Cannot override functions that I wanted to. I have to add CCL dependency only for the Detours!
2. C# functions that, in ILSpy can't de decompiled in the right way! The ILSply can't understand the functions with yield statement, and as a modder, is difficult to Understand what the this function do! :)
3. New alphas refactor of Xml Defs, I have to mos cases rebuild my entire Xml Defs.



Rikiki

Here is another interresting one!
Add a way to set needs according to the PawnKindDef. The function RimWorld.Pawn_NeedsTracker.ShouldHaveNeed only allow to distinguish between colonist/prisoner and stranger.

A solution could be to add a <onlyForFactions> property (List<FactionDef>) in the NeedDef. This way, I could make my neutral military camp AI pawns more 'human' because they will enjoy drink a beer after o day of patrolling. :D

Here is the piece of code:

[...]
   return this.pawn.RaceProps.needsRest;
}
// Need specific to a given list of faction defs. Only for pirates, only for insects, ...
if ((pawn.Faction != null)
   && (nd.onlyForFactions.NullOrEmpty() == false)
   && nd.onlyForFactions.Contains(this.pawn.Faction.def))
{
   return true;
}
return (nd != NeedDefOf.Joy || [...]

hwfanatic

Would it be useful if you added something like LoadBefore and/or LoadAfter list to the About.xml, and then let the game try to guess the correct loading order given these parameters?

soulkata

Quote from: hwfanatic on July 07, 2016, 03:33:41 AM
Would it be useful if you added something like LoadBefore and/or LoadAfter list to the About.xml, and then let the game try to guess the correct loading order given these parameters?

+1 For this!

I came to here to write something like that! :)

natbur

Quote from: RawCode on June 21, 2016, 04:50:37 AM

foreach (Type t in asm.GetTypes())
{
if (t.HasAttribute<StaticConstructorPreInit>())
RuntimeHelpers.RunClassConstructor(t.TypeHandle);
}


This, very much this.  With this we could solve a lot of the other issues people have been mentioning in this thread.

  • Mod Dependency Resolution: could be handled by adding a "dependsOn=.." to the XML and loading a DLL mod that redirects the normal xml loader to handle ordering/missing deps
  • OrDictionary: I started working on a ModHelper abusing CustomXMLLoader() to redirect methods.  Almost had it working, but ran into the common issue of not being able to hook into the code early enough.
  • ModPack Helper: My current pet project which allows updating existing Things without completely redefining them.  I have a working prototype using CustomXMLLoader() as the pre-hook and ResolveReferences() as the post-hook.  The other feature allows decorating XML Defs with attributes which control loading based on if other Mods/Defs are loaded, but this relies on a custom Def.  A hook would allow me to augment the default loader to handle this for all Defs.

We could handle the following ourselves if we had the above hook, but barring that, more hooks in the core XMLLoader would be nice.
If I've followed the code correctly, the current process for loading Mods is:
1.  Load ModDefs
2.  Load all Non-reference properties for all Defs
3.  Resolve def reference properties

What would be nice is to add some hooks between steps:
0. PreModLoad()
1. Load ModDefs
1a. PostModLoad()/PreDefLoad()
2. Load Non-reference properties for all Defs
2a. PostDefLoad()/PreResolveRef()
3. Resolve def reference properties
3a. PostResolveRef()

For my use case, I would be using the pre/post methods to remove items from the CrossRefLoader as well as the DefDatabase.
Speaking of:
Making DefDatabase<>.Remove() public so I don't have to reflect to accomplish the above.

Otherwise, a +1 for documentation.  From the a14 post:
Quote
Various refactorings to make modding easier and code easier to maintain and more flexible. Much more functionality is now implemented as composable ThingComps.
But, I can't find a list of what these modding changes actually are anywhere.


UnlimitedHugs

#82
Hello Tynan.
I would vote on the following:
1) A global event system for mods.
Allow mods to receive callbacks for events such as- game initializing, vanilla defs loaded/reloaded, initialization/re-initialization complete (at main menu), Update (each frame), OnGUI, map loading, map loading complete, game tick, game save/load, before map unload. Also, on opening/closing of a window on the WindowStack (for interface mods). In the mods menu- callbacks for when a mod has been enabled/disabled (CCL breaks to this day if the mod menu is closed without a restart).
Most of these can be accomplished using a Unity object and MapComponents, but a dedicated system would make for cleaner and more future proof code.
2) As skullywag mentioned, source code for all enumerators (methods with yield return) would go a long way in making researching the code easier for newcomers.
3) A clean way to remove mods from a save. Say, a mod with saved things is removed and the player attempts to load a map with data added by that mod. The game could warn the player, and ask if it should proceed. The map would then be loaded, removing all missing things, researches, map components, etc. in the process. Perhaps, an "uninstall" type of functionality could be put in place, to allow the mod to perform custom cleanup on a map before removal.
Take care.
HugsLib - AllowTool - Remote Tech - Map Reroll - Defensive Positions: Github, Steam

UnlimitedHugs

I'd also like to add this: the above are just small suggestions, since with the way the game's codebase is organized it is generally a pleasure to both explore and modify. The separation between Verse and Rimworld code adds clarity, and the Def system is wonderfully flexible and an inspiration for future games.
I learned a lot by just figuring out how the game works.
HugsLib - AllowTool - Remote Tech - Map Reroll - Defensive Positions: Github, Steam

Longwelwind

#84
I feel some work could be done to provide a reliable architecture to the modders.
From a technical point of view, it would consists of a "MyMod" class (written by the modder) that inherits a "BaseMod" class (written by the devs). The BaseMod class would contains hook methods for initialization such as OnLoad, OnGameLaunch, OnGameCreate, OnGuiCreate, ... that can be overwritten by the "MyMod" class.
The game would find the address of this class in the About.xml.

This "manifest" file could also contains the dependance of the mod, then the code that handles code loading should ensures that these are loaded before calling the OnLoad method of the "MyMod" class.

Essentially, the idea is to add a layer between the game and the mods so that they don't directly access the core of the game, but an interface that the devs specify.

I've done mods & plugins for some games (Minecraft, Cities Skylines, ...), and I launched a small modding API for Planetbase, and I think this is a clean architecture that allows mods to work side-by-side without stepping on each others' toes. If the API is properly made and complete, the modders don't have to deal with hacky workarounds (Manipulating Unity's GameObject or C#'s reflection API) to introduces new mechanics to the game, though they would still be able to do it if the API doesn't provide what they're looking for (but it would be an undefined behaviour from the dev's point of view).

haha1927

i am not a modder, but to players like me, it would be much easier to be able to add mod via steam workshop or sth like the mod nexus for fallout 4.

skullywag

Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

mrofa

All i do is clutter all around.

Shinzy

Two labels for the player factions would be real neat for the thumb-in-the-middle-of-palm modders like me, to avoid multiple factions of same name or ridiculous ones like faction "Colony no hats" ::)



like one label for the scenario edit screen and another actual one in game

Diana Winters

I'm trying to make a mod (http://steamcommunity.com/sharedfiles/filedetails/?id=733113011&tscn=1469750669) that adds a new species of alien, but humans and aliens can't, ah, "hook up" without dev mode. Even if you do make them hook up with dev mode, they won't do any lovin'.

I heard this was to prevent animals from breeding with incorrect species, but this wouldn't really apply to humanlikes, would it? (Seeing as only lovers get lovin', but they don't produce babies anyways.)