Jump to content

DMT Modding Tool


HAL9000

Recommended Posts

Just checking in to say this to Hal: AWESOME job, as usual. You're the boss! See ya around!

 

Hey Morte ^^ good to see you. How's things? If you get some time come hang out on Guppy's discord server. I'm usually lurking in the DMT section

Link to comment
Share on other sites

Hello,

I use 3 IHarmony patches. Each one calls harmony.PatchAll() in its Start() method. As a consequence, all 3 patches are applied 3 times !

How can I make sure all 3 patches only get applied once ? Should I call harmony.PatchAll() a single time (but how to ensure all patches have been seen) ? Is there a Patch() method that would apply the current IHarmony and not the other ones ?

Thank you !

The call to PatchAll() is:

var harmony = HarmonyInstance.Create(GetType().ToString());
harmony.PatchAll(Assembly.GetExecutingAssembly());

Edit:
- Using harmony.Patch(original, null, new HarmonyMathod(postfix)); did not apply the patch.

- Using a global bool flag to ensure PatchAll is called once does the trick.

- I checked that the problem only occurs within one mod. Calling PatchAll from one mod does not reapply patches in other mods.

 

Using a global bool flag like I did is enough only because the problem does not happen cross-mod. I feel the single-call check should be moved to the DMT library, because other users might run into the same mistake (Am I the only one tricked here ?). I can't see a use case where we want to apply patches multiple times (even then, it could be 2 different methods).

 

 

Edited by Umbrella
Answer and tool suggestion (see edit history)
Link to comment
Share on other sites

Unhandled Exception: System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at LocalisationTable.ReadFromStream(BinaryReader br, String path)
   at LocalisationTable.Load(String path)
   at DMT.Tasks.LocalisationPatch.PatchTextFile(PatchData data, String sourcePath, String destPath, String patchFilePath)
   at DMT.Tasks.LocalisationPatch.Patch(PatchData data)
   at DMT.PatchData.Patch()
   at DMTViewer.Program.Main(String[] args)

process exited with error code -532462766
 

not sure what i'm doing wrong but i cant get any mods/modlets to build correctly, I have uninstalled and reinstalled the game. i have verified the file integrity, and i cant figure it out. I'm new to modding 7 days to die and don't know what i'm doing.

 

Link to comment
Share on other sites

  • 2 weeks later...
On 5/2/2020 at 11:27 AM, FrostX1 said:

Unhandled Exception: System.ArgumentException: An item with the same key has already been added.
   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at LocalisationTable.ReadFromStream(BinaryReader br, String path)
   at LocalisationTable.Load(String path)
   at DMT.Tasks.LocalisationPatch.PatchTextFile(PatchData data, String sourcePath, String destPath, String patchFilePath)
   at DMT.Tasks.LocalisationPatch.Patch(PatchData data)
   at DMT.PatchData.Patch()
   at DMTViewer.Program.Main(String[] args)

process exited with error code -532462766
 

not sure what i'm doing wrong but i cant get any mods/modlets to build correctly, I have uninstalled and reinstalled the game. i have verified the file integrity, and i cant figure it out. I'm new to modding 7 days to die and don't know what i'm doing.

 

Make sure you have the latest version of DMT.  DMT no longer handles localization like it did previously.  That's done by the game now.

Link to comment
Share on other sites

On 4/29/2020 at 10:49 AM, Umbrella said:

Hello,

I use 3 IHarmony patches. Each one calls harmony.PatchAll() in its Start() method. As a consequence, all 3 patches are applied 3 times !

How can I make sure all 3 patches only get applied once ? Should I call harmony.PatchAll() a single time (but how to ensure all patches have been seen) ? Is there a Patch() method that would apply the current IHarmony and not the other ones ?

Thank you !

The call to PatchAll() is:


var harmony = HarmonyInstance.Create(GetType().ToString());
harmony.PatchAll(Assembly.GetExecutingAssembly());

Edit:
- Using harmony.Patch(original, null, new HarmonyMathod(postfix)); did not apply the patch.

- Using a global bool flag to ensure PatchAll is called once does the trick.

- I checked that the problem only occurs within one mod. Calling PatchAll from one mod does not reapply patches in other mods.

 

Using a global bool flag like I did is enough only because the problem does not happen cross-mod. I feel the single-call check should be moved to the DMT library, because other users might run into the same mistake (Am I the only one tricked here ?). I can't see a use case where we want to apply patches multiple times (even then, it could be 2 different methods).

 

 

 

Hi Umbrella,

 

It's up to the modder to implement the patch call, each mod is split into it's own dll for this reason. You wouldn't want DMT making assumptions about running the patches as the modder may want to do something unusual / bespoke. 

 

If you're in control of the mod you can just remove the other two patchall calls. Each patch doesn't require a patchall call, one call grabs all the patches in the given assembly (dll file). 

 

Have a look at the bootstraping section on Harmony for how to run individual patches and for detecting already run patches. https://github.com/pardeike/Harmony/wiki/Bootstrapping

 

Cheers,

 

Hal

Link to comment
Share on other sites

Hi Hal9000, thank you.

 

I understand and agree with your answer. But still:

Quote

If you're in control of the mod you can just remove the other two patchall calls.

The problem is that each of my file (in the same mod, each implementing IHarmony and requiring someone to call PatchAll once) then needs to make assumption on other file. If I remove PatchAll from one patch, I assume another single patch will apply PatchAll. From a design perspective, it does not make much sens. From a practical perspective, whenever you remove/add some patch to your harmony folder, you need to check for the single call.

 

Quote

You wouldn't want DMT making assumptions

Agreed, but honestly 99% of modders want to apply each of their patch once. What I suggest is the DMT tool to have an extra method PatchAllOnce, so exotic use cases can do whatever they were doing before, but most users can just call PatchAllOnce() in each of their patch and no longer worry about if it's already done, or what happens when they remove a patch file.

 

Could you add this extra method to the tool ? I know I will use it for every mod I make (and I still have found no use case where I would not)


public static class Harmonys {
    private static bool Applied = false;
    public static void ApplyOnce(HarmonyInstance harmony, Assembly assembly, Type patch) {
        /* Important: the call to Assembly.GetExecutingAssembly() need be done by the caller
        TODO: check method is patched when skipping ?
        */
        Debug.Log(String.Format("Harmonys.ApplyOnce {0} -> {1}", patch.ToString(), Applied));
        if (Applied) return;
        Debug.Log(String.Format("Harmonys.Applying {0}", patch.ToString()));
        harmony.PatchAll(assembly);
        Applied = true;
    }
}

 

Link to comment
Share on other sites

Hi Umbrella,

 

I think this is where you're going wrong:

On 5/22/2020 at 1:22 PM, Umbrella said:

The problem is that each of my file (in the same mod, each implementing IHarmony and requiring someone to call PatchAll once)

 

The IHarmony interface isn't for each patch, it's for a patch manager class. So you'd define and implement the interface once for the mod (usually, though more complicated patching can use it multiple times) and that then controls how the patches are applied (usually with a PatchAll or something more complicated if needed). That's what I meant by the modder being responsible for how the patching is applied. 

 

Then when the game starts each mod's IHarmony interface is called and that's what drives your changes. DMT makes no assumptions on how you're going to do that. 

 

Does that make sense? 

 

Cheers,

 

Hal

 

 

 

Link to comment
Share on other sites

Please can somone tell me how to get this working on a hosted server ?

 

Ive got it working fine on my dedicated server and join with single player just fine but when i upload the 3 .dll files to the server it goes bonkers and wont start :-) please help

Link to comment
Share on other sites

okay, seems to work if i copy the .dll from the DMT directory to the mod directory where i have the .cs files.

But another question came up:

 

I am wrinting a IHarmony Patch, which accesses some variables inside a class, which are privater and have no getters/setters. So i wrote an IPatcherMod, to turn these into public variables instead.

 

BUT now comes the crux:

The IHarmony script can't compile, because the IPatcherMod is called at runtime, while at compiletime the variables are still public, and the dmt compiler prevents the compilation because of that reason....

 

 

Link to comment
Share on other sites

  

On 6/1/2020 at 6:42 AM, sparrow8332 said:

Please can somone tell me how to get this working on a hosted server ?

 

Ive got it working fine on my dedicated server and join with single player just fine but when i upload the 3 .dll files to the server it goes bonkers and wont start 🙂 please help

 Post your log file from the server that's erroring

 

On 6/7/2020 at 6:47 PM, Shiana said:

okay, seems to work if i copy the .dll from the DMT directory to the mod directory where i have the .cs files.

But another question came up:

 

I am wrinting a IHarmony Patch, which accesses some variables inside a class, which are privater and have no getters/setters. So i wrote an IPatcherMod, to turn these into public variables instead.

 

BUT now comes the crux:

The IHarmony script can't compile, because the IPatcherMod is called at runtime, while at compiletime the variables are still public, and the dmt compiler prevents the compilation because of that reason....

 

 

 

There's definitely something strange in your setup. IPatcherMod is used by DMT and shouldn't be in the server files. They are used during the DMT build rather than runtime of the game. Cecil should not be included with the dlls that end up in the server folders. 

 

You don't need to change the field accessor type, you can get the value in the Harmony patch using reflection

 

Cheers,

 

Hal

 

Link to comment
Share on other sites

On 6/7/2020 at 2:47 PM, Shiana said:

okay, seems to work if i copy the .dll from the DMT directory to the mod directory where i have the .cs files.

But another question came up:

 

I am wrinting a IHarmony Patch, which accesses some variables inside a class, which are privater and have no getters/setters. So i wrote an IPatcherMod, to turn these into public variables instead.

 

BUT now comes the crux:

The IHarmony script can't compile, because the IPatcherMod is called at runtime, while at compiletime the variables are still public, and the dmt compiler prevents the compilation because of that reason....

 

 

For a Harmony patch, you can access a private variable from the same class by adding it to the parameter list, with 3 leading underscores

 

        public static void Postfix(XUiC_ItemStack __instance, bool ___bLocked, bool ___isDragAndDrop)

In the XUiC_ItemStack class, there's a private variable:  bool isDragAndDrop

 

If you want to change its value, you can add ref to it:   ref bool ___isDragAndDrop

Link to comment
Share on other sites

Hey guys,

 

DMT v2 is now released. The major change is it now uses Harmony v2 instead of v1. This is a breaking change so I've bumped the DMT release to v2 as well. There are some upgrade processes you'll need to do for your mod. A lot of them can be done by DMT by using the "Attempt Hamony Auto Update" checkbox when building 

 

image.thumb.png.fe56761c29ae6b446ad11cf8dcb19523.png

 

Further details of the updates required can be found here: https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0 

 

We've also removed the requirement for the mod.xml. Now both vanilla and DMT uses the ModInfo.xml file. Again, there is an auto-update function built in that should serve most cases. Once the update is done you should delete the mod.xml file to remove any warnings that are generated in DMT. 

 

Cheers,

 

Hal

Edited by HAL9000 (see edit history)
Link to comment
Share on other sites

Thanks HAL9000

 

It worked perfect for me to compile the belt mod.

 

Spherei Core y legacy distain Terrain,they cause an error when starting the game, it does not even reach the menu, I hope that spherei fixes it and that it works for A19.

Edited by Gouki (see edit history)
Link to comment
Share on other sites

  • 1 month later...
4 hours ago, nismo1969 said:

Do Clients and the Server both need DMT 2.0 or just the Server? Regards

It depends on the mod. If it's a server only mod then the clients don't need it but anything that has changes on the client (new assets, code or xml changes) then the players also need to apply the mod

Link to comment
Share on other sites

17 hours ago, nismo1969 said:

Got DMT working on both Server and Clients but Admins cannot use F1 for any commands like "dm" "listplayerids" etc is this normal or have I missed something?. Regards

Have you given the layers admin level permissions? You add them to the permissions file or through the console if you're an admin.

 

If you have set them set the log file on the server for errors

Link to comment
Share on other sites

Having Issues building the set of mods, I've tested every mod on its own, and it has issues then too.

 

Nope: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

process exited with error code -11234


I am on the most recent version of DMT and tried using another version in case I did something wrong and still no fix

Link to comment
Share on other sites

34 minutes ago, Nslabinski said:

Having Issues building the set of mods, I've tested every mod on its own, and it has issues then too.

 

Nope: Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

process exited with error code -11234


I am on the most recent version of DMT and tried using another version in case I did something wrong and still no fix

I get the exact same error after DMT updated today when I went to "build" mods. Version 2.2.7568.19791.

Link to comment
Share on other sites

  • Roland unpinned and locked this topic
Guest
This topic is now closed to further replies.
×
×
  • Create New...