Locked thread | Replies: 26 (Who?), Viewed: 11065 times. | Locked by: Srikandi Reason: Discussion continues in download thread
Page 1 of 2
Lab Assistant
Original Poster
#1 Old 10th Jul 2009 at 4:08 AM Last edited by morgade : 11th Jul 2009 at 6:21 AM.
Default Core Mod Merger (Update - No IL editing needed !!)
First usable version posted.

This is a tool able to inject multiple Core Mods in a batch process. (and can inject code into game assemblies without messing with IL !)

- Unpack the file into your <The Sims 3 Folder>\ModMerger.
- Running ModMerger.exe will run the batch proccess, merging the two sample core mods (PeeYourself, Instant Maximize) and generate a gameplay.package into the ..\Mods\Package folder. [WARNING - It will overwrite an existent gameplay.package in this folder]
- Running mergerAndRun.bat will merge mods and run the game

This merge proccess is fast and really works. (The two sample mods provided injects code in the same method)

Now i need to work to add more injection options to modders. In this version, you can only set injection point at the start of a method. But we can define more options like:
- Inject at end, at specific instruction
- Change class/method/field access parameters (private,protected,virtual, override, etc...)

This tool will only be useful when (or if) modders agree in distribute mods in the expected format (dll + config xml).

So, if modders are interested, post your injecion options requirements here !

I'm writing more detailed documentation.
Documentation draft below
------------------------------
Sims 3 Core Mod Merger
User documentation
Instalation
Unpack the ModMerger.zip into you The Sims 3 game instalation folder (NOT the folder into "My Documents"). The tool must be in the path <The Sims 3 Folder>\ModMerger.
You need .NET Framework 3.5 installed in your machine to use this tool.
Using
Mods used in this tool must be extracted into the <The Sims 3 Folder>mods. Mods will have one *.mod file and one or more dll files.
Just run ModMerger.exe to create a new gameplay.package into your <The Sims 3 Folder>\Mods\Packages folder.
You can also run mergerAndRun.bat to merge all mods and then run the game.

Modder / Developr Documentation
Using ModMerger in your Mod
The first thing you need is to plan where into the game assemblies you will inject calls to your assembly. You can use a tool like Reflector to inspect the game assemblies.
Each injection point needs a static method in a class of your mod. The following example shows how to set up your mod.

Mod example
This is a sample code to a mod that adds an action to maximize some motives of the selected sim. We are going to insert a call into the Sims3.Gameplay.Actors.Sim class (at the start of AddSoloInteractions Method). This call will execute the method Start in the Maxime.Main class at our mod. Take a look at the C# code:

Code:
namespace Maximize
{
    public class Main
    {
        public static void Start(Sim sim)
        {
            sim.SoloInteractions.Add(new InteractionObjectPair(Maximize.MaximizeAll.Singleton, sim));
        }
    }
    
    public sealed class MaximizeAll : Interaction
    {
        public static readonly SoloSimInteractionDefinition Singleton = new Definition();

        // Methods
        protected override bool Run()
        {
            base.StandardEntry(false);
            base.Actor.Motives.ForceSetMax(CommodityKind.Bladder);
            base.Actor.Motives.ForceSetMax(CommodityKind.Fun);
            base.Actor.Motives.ForceSetMax(CommodityKind.Hygiene);
            base.Actor.Motives.ForceSetMax(CommodityKind.Energy);
            base.Actor.Motives.ForceSetMax(CommodityKind.Social);
            base.Actor.Motives.ForceSetMax(CommodityKind.Energy);
            StyledNotification.Show(new StyledNotification.Format("You cheater !", StyledNotification.NotificationStyle.kMessage));
            base.StandardExit(false);
            return true;
        }

        // Nested Types
        private sealed class Definition : SoloSimInteractionDefinition
        {
            public override string GetInteractionName(ref InteractionInstanceParameters parameters)
            {
                return "Max All";
            }
        }
    }
}


Notice that the injected method must follow some rules:

* Must be public
* Must be static
* Must receive as a parameter one instance of the class where tha call will be injected. The parameter will hold the current object being executed.

The start method uses the sim variable to insert a new interaction to the pie menu used when you left click on the active sim. This action will raise some motives of the current sim and will call you a cheater .
Now, all you need is define the injection points in the .mod file.
This mod is a xml like the following and is selft explained:

Code:
<?xml version="1.0" encoding="utf-8"?>
<mod xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <!-- Your mod name (Just for labeling) -->
  <name>Maimize Motives Mod</name>  
  <!-- You can define multiple injections tags in one mod file -->
  <injections> 
    <!-- You assembly file. (Must be in the ModMerger\mods folder during merge) -->
    <SourceAssembly>Maximize.dll</SourceAssembly> 
    <!-- The class into your assembly that contains the staic method to be called -->
    <SourceClass>Maximize.Main</SourceClass>
    <!-- The method call to be injected into the game's assembly -->
    <SourceMethod>Start</SourceMethod>
    <!-- Game assembly that will suffer call injection -->
    <TargetAssembly>Sims3GameplaySystems.dll</TargetAssembly>
    <!-- Class of the game assembly that will suffer call injection -->
    <TargetClass>Sims3.Gameplay.Actors.Sim</TargetClass>
    <!-- Method into the Class of the game assembly that will suffer call injection -->
    <TargetMethod>AddSoloInteractions</TargetMethod>
    <!-- String list of parameter types of target method . 
        Example: 
            <TargetMethodParameters> 
                 <string>System.Boolean</string>
                 <string>Sims3.Gameplay.Actors.Sim</string>
            </TargetMethodParameters> -->
    <TargetMethodParameters></TargetMethodParameters>
    <!-- Kind of injection (work in progress). Currently you can only inject calls at the top of the method -->
    <Kind>TOP</Kind>
  </injections>
</mod>


Now, just build your assembly and copy it and the .mod file to the ModMerger\mods folder.
Run ModMerger.exe and check if your mod works running the game.



Mod Merger by Marcelo Morgade - This is a work in progress !!
Download - please read all instructions before downloading any files!
File Type: zip ModMerger.zip (5.56 MB, 104 downloads) - View custom content
Description: ModMerger binaries
File Type: zip Maximize-Mod-Src.zip (10.5 KB, 50 downloads) - View custom content
Description: Sample source mod used in tool
File Type: zip PeeYourself-Mod-Src.zip (7.8 KB, 48 downloads) - View custom content
Description: Sample source (2) mod used in tool
Advertisement
Field Researcher
#2 Old 10th Jul 2009 at 4:14 AM
If you can get this working fully that would be the most amazing thing ever.

A few things spring to mind:

1) what would happen if two mods try to inject into the same place in a method, or change its behaviour in two different ways?

2) Will you be able to remove instructions from a method? or remove lines and then add different ones?

3) In the indie stone mod we turn non-virtual methods into virtual methods, so they can be overridden in a sub-class in our DLL.

4) Changing private or family methods / classes into public classes.

thanks for looking into this, I think it'd make a huge impact if you can get it working.
Lab Assistant
Original Poster
#3 Old 10th Jul 2009 at 4:44 AM
Quote:
Originally Posted by lemmy101
1) what would happen if two mods try to inject into the same place in a method, or change its behaviour in two different ways?

In the xml, a modder would choose some kind of injection into a method. Would be something like.
A) after the last instruction
B) before the first instruction, allowing the original method to continue
C) before the first instruction, ignoring the rest of the method


In case of A or B, the injection wold be sequential (call one mod, and then the other mod). We would have problems only if two mods choose the C injection mode into the same method. But there are possible workarounds.

Quote:
Originally Posted by lemmy101
2) Will you be able to remove instructions from a method? or remove lines and then add different ones?

The easiest way to do that would be using injection of type C above. One can copy the orginal method source (from Reflector), change this source, compile to an assembly and inject into the original method using type C. All injected methods will receive the instance of the object executing the original method, so it can be manipulated.

Quote:
Originally Posted by lemmy101
3) In the indie stone mod we turn non-virtual methods into virtual methods, so they can be overridden in a sub-class in our DLL.

I need to check if the Mono.Cecil Library can do these kind of things. If it cans, this could be another xml configuration.

Quote:
Originally Posted by lemmy101
4) Changing private or family methods / classes into public classes.

Same awser to question 3

Quote:
Originally Posted by lemmy101
thanks for looking into this, I think it'd make a huge impact if you can get it working.

To a tool like this really work, we just need cooperation between all modders.
Field Researcher
#4 Old 10th Jul 2009 at 5:00 AM
Thanks for the info!

I for one will be happy to help in any way I can.
Lab Assistant
Original Poster
#5 Old 10th Jul 2009 at 5:13 AM
I just tried and its really possible to make the tool change class and method acess scope and virtual, override flags.

Quote:
I for one will be happy to help in any way I can.

I think the best way to help is try to create something like this xml config to a big mod like indie stone.
If you can define all injections and changes needed in the game assemblies, we could try make it work with this mod merger.
Mother Function
retired moderator
#6 Old 10th Jul 2009 at 10:29 AM
I don't understand how y'all do it...but y'all are awesome! I hope this works.

"Holy Shift! Check out the asymptotes on that mother function!"
Lab Assistant
#7 Old 11th Jul 2009 at 4:00 AM
This looks very cool, I'm definitely going to test it out
Lab Assistant
Original Poster
#8 Old 11th Jul 2009 at 4:01 AM Last edited by morgade : 11th Jul 2009 at 4:54 AM.
Posted first version.
You can try mergin two sample core mods.
Lab Assistant
#9 Old 11th Jul 2009 at 4:44 AM
The merging worked correctly, now I have to work on adding my own hacks :P

I do have a question about the injection though. When you said
Quote:
Originally Posted by morgade
A) after the last instruction
B) before the first instruction, allowing the original method to continue
C) before the first instruction, ignoring the rest of the method


I'm assuming that's specified in the Kind tag? If that's correct, what are the three values that apply? I'm looking forward to playing around with this
Lab Assistant
Original Poster
#10 Old 11th Jul 2009 at 4:54 AM
Quote:
Originally Posted by xalwaysvindicatedx
I'm assuming that's specified in the Kind tag? If that's correct, what are the three values that apply? I'm looking forward to playing around with this

Actually this version only have the "TOP" kind (before the first instruction).
I'm implementing other injection options and should post a new version very soon.
Lab Assistant
#11 Old 11th Jul 2009 at 5:08 AM
Ah, okay, no problem. I'm just working on merging over a couple things like enabling debug interactions, so I shouldn't need to have it disable the original code.
Lab Assistant
#12 Old 11th Jul 2009 at 5:20 AM
Nice work! Big day for the little guys who wanna core mod! =)
Lab Assistant
Original Poster
#13 Old 11th Jul 2009 at 5:42 AM
Update - Posted a documentation draft
Don't ask me, I just code
#14 Old 12th Jul 2009 at 1:03 AM
Very cool. Glad to see someone's actually done this. I've been way too busy.
Test Subject
#15 Old 12th Jul 2009 at 2:10 AM
y'all rock
Fat Obstreperous Jerk
#16 Old 12th Jul 2009 at 2:27 AM
This would be more useful if it could take an existing core mod as the injection target, as some of the more advanced core mods are simply too complex to insert into a base game DLL in such a manner, and would be better used as a base from which to insert smaller things.

Grant me the serenity to accept the things I cannot change, the courage to change the things I cannot accept, and the wisdom to hide the bodies of those I had to kill because they pissed me off.
Lab Assistant
Original Poster
#17 Old 12th Jul 2009 at 2:43 AM
Quote:
Originally Posted by J. M. Pescado
This would be more useful if it could take an existing core mod as the injection target, as some of the more advanced core mods are simply too complex to insert into a base game DLL in such a manner, and would be better used as a base from which to insert smaller things.


Actually, it uses a set of assemblies in the default directory as a start point. It's possible to replace this base assembly with some more complex mod.

Other approach would be scan a base game assembly and then detect diferences with modified assemblies (type by type, method by method, instruction by instruction) and then apply all modifications found in a set of assemblies. (I think I shoud have started by this approach). It would be slower, but we could merge all mods just the way they are being produced now !
Lab Assistant
#18 Old 12th Jul 2009 at 3:06 AM
Quote:
Originally Posted by J. M. Pescado
This would be more useful if it could take an existing core mod as the injection target, as some of the more advanced core mods are simply too complex to insert into a base game DLL in such a manner, and would be better used as a base from which to insert smaller things.
I partly disagree. While taking one of the more intrusive core mods as a base is a good idea, I think the core mods can still greatly benefit from this. Right now all the large core mods include tons of little things that are not associated with the primary mod, and these little things would be great candidates for breaking out into patches. I'm talking about stuff like the changes that were incorporated from your mod into Indie Stone (At least assuming that was the case from the thanks there) and other little things like that. That way people are not forced to take features A B and C just because they want X Y and Z, which is the whole point of code merging to begin with.
Fat Obstreperous Jerk
#19 Old 12th Jul 2009 at 3:42 AM
Quote:
Originally Posted by morgade
Actually, it uses a set of assemblies in the default directory as a start point. It's possible to replace this base assembly with some more complex mod.
Well, sure, but this is a tool you're peddling to the Peasantry. Asking them to manipulate files in such a manner is going to cause someone to mess something up. Better to present the choice to them in-game rather than having them try to mainpulate files for it.

Quote:
Originally Posted by morgade
Other approach would be scan a base game assembly and then detect diferences with modified assemblies (type by type, method by method, instruction by instruction) and then apply all modifications found in a set of assemblies. (I think I shoud have started by this approach). It would be slower, but we could merge all mods just the way they are being produced now !
That probably would have been the better approach, although doing it in binary would involve having to do things like rewrite all the instruction addresses if something was inserted. Of course, you probably already have to do that anyway.

Grant me the serenity to accept the things I cannot change, the courage to change the things I cannot accept, and the wisdom to hide the bodies of those I had to kill because they pissed me off.
Lab Assistant
Original Poster
#20 Old 12th Jul 2009 at 7:17 AM
Quote:
That probably would have been the better approach, although doing it in binary would involve having to do things like rewrite all the instruction addresses if something was inserted. Of course, you probably already have to do that anyway.


Yeah, but this is not that easy.

I can generate a initial set of game assemblies with ALL Types, Fields and Methods marked as Public.

This way, if you want to change drastically the logic of a game method, all you need is to use the injection type REPLACE (removes original code and inject a call to your method, receiving the instance and the same parameters).

If I had the source code of some of these big mods, I could show how easy would be to achieve this behavior.
Theorist
#21 Old 12th Jul 2009 at 6:33 PM
This all sounds so exciting, and I am hoping this is a very successful endeavor.

However,
Quote:
Well, sure, but this is a tool you're peddling to the Peasantry. Asking them to manipulate files in such a manner is going to cause someone to mess something up. Better to present the choice to them in-game rather than having them try to mainpulate files for it.

Speaking as one of the peasantry, I know if I tried to do anything very complex, I would just break it. Just the thoughts of having to "manipulate files" is enough to send me running and screaming from the room. I hate being that way but there just doesn't seem to be a whole lot I can do to change it. :p
Lab Assistant
#22 Old 12th Jul 2009 at 8:24 PM
Quote:
Originally Posted by J. M. Pescado
Well, sure, but this is a tool you're peddling to the Peasantry. Asking them to manipulate files in such a manner is going to cause someone to mess something up. Better to present the choice to them in-game rather than having them try to mainpulate files for it.


I somewhat agree with you, as I like the way the AwesomeMod is configurable in a relatively easy-to-use way. At the same time though, I think as more people learn about the application, more modders will make their mods ready-to-go to be installed in this fashion. Just my $0.02
Lab Assistant
#23 Old 12th Jul 2009 at 9:42 PM
Seems to me that if "the peasantry" want to mess with this stuff, they should learn to backup their files first. Or have the proggy do this automatically maybe.
Lab Assistant
#24 Old 13th Jul 2009 at 1:57 AM
Wow, this is a pretty huge development. It not only makes merging possible, which seemed highly unlikely until now, but it makes core modding in general significantly more approachable. Impressive job, Morgade!

I know the last thing people want is another file format, but this seems like such a fundamental development of how core mods will be used and developed. A simple new file format, for example a .CMM file that would be a trivial wrapper for the dll and the the injection description xml, would lead to far less confusion and might even encourage developers to make their projects more compatible. Users could then put all the CMM files in a core modules type directory and run your to program to merge and/or launch Sims3.
Lab Assistant
Original Poster
#25 Old 13th Jul 2009 at 2:05 AM
Posted in the downloads section.
Please, post new answers here: => http://www.modthesims.info/d/354748
Locked thread | Locked by: Srikandi Reason: Discussion continues in download thread
Page 1 of 2
Back to top