ago

[RELEASED] Client mod loader

275 posts in this topic

This is the initial release of a client mod loader

 

https://github.com/ago1024/WurmClientModLauncher/releases/latest

 

Instructions

* Unzip the contents of client-modlauncher-<version>.zip into the "WurmLauncher" folder

* Unzip the contents of the individual mods you want to run into the "WurmLauncher" folder. This adds the required .properties files to enable the mods.

* Run patcher.bat

* Start Wurm from Steam

 

The client-modlauncher-<version>.zip package includes the updated mods client-serverpacks and custommap as well.

 

Changelog

Check github for change logs.

 

 

Edited by ago
14 people like this

Share this post


Link to post
Share on other sites

=D  =D  =D  =D  =D  =D  =D  =D  =D  =D  =D  =D  


 


 


This is going to be great!


1 person likes this

Share this post


Link to post
Share on other sites

wowowowowowow! i fell off my chair! You're a champ!

 

 

I updated our forums with instructions on installation.   This is exciting!!           Ago is my hero!!  

 

I can start adding my pirate ships  *grin* 

Edited by razoreqx

Share this post


Link to post
Share on other sites

Great work ago. Really nice. I was reading your code yesterday and I was thinking about an improvement. Currently, if someone wants to hook a method, he has to


 


1)Find the method inside the compiled jars.


2)Understand its signature.


3)Properly apply the selector with javassist to get the right method.


4)Use javassist defined hooks to add content.


 


I wonder how easy and without performance overhead, would it be to generate code for each class and each method in certain packages and then hook that code into the  server jar.


 


For example:


 


Say there's a class Item with only method getName() in the server jar


 


The generator would iterate in the server jar and for that method, it would create code 


 


public interface ItemOverloader


{


   public void beforeGetName();


   public void afterGetName();


   public boolean breakGetName();


 


}


 


public ItemOverloadManager


{


  public static List<ItemOverloader> overloaders =  new ArrayList<>();


 


  public static void beforeGetName()


  {


     for(ItemOverloader i: overloaders)


        i.beforeGetName();


  }


 


  public static void afterGetName()


  {


     for(ItemOverloader i: overloaders)


        i.afterGetName();


  }


 


  public static boolean breakGetName()


  {


     for(ItemOverloader i: overloaders)


        if(i.breakGetName())


           return true;


        return false;


  }


}


 


then the javassist would:


 


CtClass itemClazz = ... bla bla


CtMethod getNameMethod = ... bla bla


getNameMethod.executeBefore("ItemOverloadManager.beforeGetName()");


getNameMethod.executeAfter("ItemOverloadManager.afterGetName()");


getNameMethod.execute("if(ItemOverloadManager.breakGetname()) return;");


...


...


 


 


So at the end, you end up with a full set of new classes that give you interface access to the server without having to know javassist at all. The end user-developer, would program against the machine generated interfaces that would be included in the mod loader library.


 


I wonder what performance downgrade would that have, as it would mean that all method calls, would lookup a static class and then iterate a list in it to call the extra code.


Edited by ElvenElder

Share this post


Link to post
Share on other sites

I wonder what performance downgrade would that have, as it would mean that all method calls, would lookup a static class and then iterate a list in it to call the extra code.

This would kill performance all over the place.

For example the creature poll() method in the server is called once for every creature every few seconds. This goes on to call at least a dozen other methods. For every creature every few seconds. Adding a hook almost anywhere without actually needing would definitly kill the performance. And to make things worse the client usually has way more CPU usage. The impact would be even more severe. And this even ignores the memory overhead for all the objects and lists.

And it's not even covering what's needed to change the program behaviour in methods.

I'd love to have an easier way to change things but using javassist is actually one of the best tradeoffs between performance and ease of use. With the Java language we're actually blessed. Doing the same with a linked C++ program would be a ton harder since we'd have no decompiler, no method names and probably performance optimized code which is even harder to read.

Edited by ago
2 people like this

Share this post


Link to post
Share on other sites

True that. I was worried myself a lot about the performance too. Is there any way with recent javassist versions, to inject a method on runtime ? In essense would that be possible ?


 


1)Patch server.jar with a pre main method.


2)When server starts and pre-main is called, select CtMethods from classes that are loaded


3)Inject javassist code on those methods without restarting the server or writting directly to the jar, but it's in-memory JVM representation.


Edited by ElvenElder

Share this post


Link to post
Share on other sites

whoops....ago, something wong with the patcher, it replaces it with only the patch files, client.jar only 26k.


Share this post


Link to post
Share on other sites

It copies client.jar to client-patched.jar and replaces client.jar with the loader

Share this post


Link to post
Share on other sites

True that. I was worried myself a lot about the performance too. Is there any way with recent javassist versions, to inject a method on runtime ? In essense would that be possible ?

 

1)Patch server.jar with a pre main method.

2)When server starts and pre-main is called, select CtMethods from classes that are loaded

3)Inject javassist code on those methods without restarting the server or writting directly to the jar, but it's in-memory JVM representation.

This is exactly what the modloader and the mods do.

Share this post


Link to post
Share on other sites

When I set this up last night I had to manually rename a copy of client.jar to client patched but otherwise works great, thank you

Share this post


Link to post
Share on other sites

There was in fact a typo that prevented the patcher from identifying the original jar.

I posted https://github.com/ago1024/WurmClientModLauncher/releases/tag/v0.1.1

The original client.jar is probably lost. You can redownload it from steam by checking the local files for errors in steam (Wurm Unlimited -> Properties -> Local files -> Check game files for error)

1 person likes this

Share this post


Link to post
Share on other sites

We have this in test and its working flawlessly.   I was able to add all my new 2d textures, sound effects, and 3d models.    Make sure you have the bandwidth if your a server owner as upstream bandwidth can become quite saturated as new users using the client modloader are downloading the mod packs.   


Share this post


Link to post
Share on other sites

I've added the hitching post demo code to the server loader.

 

hitchingpost.properties has the entry "serverPacks=hitchingpostpack.jar". This will instruct the serverpacks mod to push the packs jar to the client.

 

You can even push the packs to client without a dedicated mod. Just add "serverPacks=pack1.jar,pack2.jar" to serverpacks.properties and place the pack files into mods/serverpacks

 

The packs must contain a mappings.txt with all entries in the pack and the packs must contain all used data.I don't think they can refer to any files from other packs.

Share this post


Link to post
Share on other sites

Ok, I think I understand what you are doing here. but for some reason I can't get it to work. The coding is in there and I can make the hitching post. but the graphic is still a question mark bag.

I put hitchingpost and hitchingpostpack both in the hitchingpost file inside the mods folder. that didn't work so I tried putting the hitchingpostpack into the serverpacks folder and it still didn't work.

It just doesn't seem to push the file to the client.

What am I missing?

 

I hope I'll get this to work because that would work pretty amazing this way

Share this post


Link to post
Share on other sites

is the serverpacks mod enabled?

 

There should be messages like this in the console output before the GUI is started:

Nov 21, 2015 11:39:23 PM org.gotti.wurmunlimited.mods.serverpacks.ServerPackMod addPack
INFORMATION: Added pack A0553A65523FE3159852CCAF022C54E021E81492 for pack mods\hitchingpost\hitchingpostpack.jar
Nov 21, 2015 11:39:23 PM com.wurmonline.server.gui.WurmServerGuiMain main

And if the server sends the file the client should either get a strange PM with the pack URL or the file should appear in the packs folder.

Edited by ago

Share this post


Link to post
Share on other sites

Got this error when trying to connect in the console

  1. Exception in thread "Sound Loader 0" org.gotti.wurmunlimited.modloader.classhooks.HookException: java.lang.IllegalAccessException: Class org.gotti.wurmonline.clientmods.serverpacks.ServerPacksMod$2$1 can not access a member of class com.wurmonline.client.resources.Resources with modifiers "private"
  2.         at org.gotti.wurmunlimited.modloader.classhooks.HookManager.invoke(HookManager.java:241)
  3.         at com.wurmonline.client.resources.Resources.findResource(Resources.java)
  4.         at com.wurmonline.client.resources.Resources.getResource(Resources.java:129)
  5.         at com.wurmonline.client.sound.SoundEngine$4.run(SoundEngine.java:384)
  6.         at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
  7.         at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
  8.         at java.lang.Thread.run(Unknown Source)
  9. Caused by: java.lang.IllegalAccessException: Class org.gotti.wurmonline.clientmods.serverpacks.ServerPacksMod$2$1 can not access a member of class com.wurmonline.client.resources.Resources with modifiers "private"
  10.         at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
  11.         at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(Unknown Source)
  12.         at java.lang.reflect.AccessibleObject.checkAccess(Unknown Source)
  13.         at java.lang.reflect.Method.invoke(Unknown Source)
  14.         at org.gotti.wurmonline.clientmods.serverpacks.ServerPacksMod$2$1.invoke(ServerPacksMod.java:92)
  15.         at org.gotti.wurmunlimited.modloader.classhooks.HookManager.invoke(HookManager.java:231)
  16.         ... 6 more

 

 

Did not recieve the packs either.

I tested this locally and it works just fine, I'm not sure why there is any difference with the dedicated setup, files are mostly 1:1

Edited by WesncIsMe

Share this post


Link to post
Share on other sites

Ok, I have to admit defeat so far. Here's what I've done.

 

1) Deleted Wurm from Steam and reinstalled it

2) Downloaded a fresh copy of the client mod and installed it

3) Renamed serverpacks.disabled to serverpacks.properties on client

4) Ran patcher.bat on client

5) Turned off Windows Firewall and Windows Defender (I am running on Windows 10)

6) Tried connecting to server1 running Wurm dedicated server on ubuntu 15.04. No additional packs delivered to packs directory on client. Server reports host port for serverpacks in log file

7) Tried connecting to server2 running Wurm dedicated server on a Windows machine (hosted by Citadel in this case). No additional packs delivered to packs directory on client.

8) Tried turning off all other mods on linux server. No difference

 

I am not receiving the funny PM message nor the pack files. One of my server participants mentioned receiving the weird message.

 

Does anyone have a working server that I could do a quick client connection to as a test of my client functionality? If the client works then it's something on my server side.

 

~Nappy

 

 

Share this post


Link to post
Share on other sites

I've encountered a bug with the modloader.  It seems that whenever the patcher is run, the ability to manage animal permissions is inexplicably removed from the game.  I've tested this by re-validating files and removing serverpacks, and for some reason it seems that the patcher is disabling it.  Other players on the same server are having the same issue.

 

Edit: Just wanted to clarify a few things.  Running the patcher and Wurm with no mods anywhere near the game still causes this strange glitch to occur.  I ran it in local with a fresh patcher install and still had it occur.  Best of luck in fixing it though!  You've done the community a great favor! :)

Edited by AspieInc

Share this post


Link to post
Share on other sites

Is this happeing with the client or the server mod launcher?

 

I tried with and without client modlauncher and with and without server modlauncher and got "manage animals" on the body but I the cared for and unbranded horse was not listed as manageable although it was listed. I'm not sure if there are other requirements to manage an animal

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now