Posted November 7, 2015 I'm pleased to release my first mod, AlwaysForage, using Ago's Modloader. The source code is blatantly stolen adapted from Ulviirala's BetterGamemasters. Allows you to forage, botanize, and rummage on a tile regardless of whether it had recently been foraged before. It does so by adding modloader code to ensure the function isForagable and isBotanizable always returns true. It should remain up to date for any Wurm Unlimited version. Installation instructions: 1. Make sure you have Ago's Modloader2. Unzip AlwaysForage.zip to the Wurm Unlimited Dedicated Server folder so that modloader.bat and the mods folder are in the same directory as WurmServerLauncher.exe.3. Open modloader.bat and add (without quotes) "-noverify" to the list of runtime arguments. If you are unsure where to place it, put it between any set of words which begin with "-" and before the end which says modloader.jar. This is necessary to suppress a weird bytecode error.4. Start the game.5. IF YOU GET AN ERROR THAT SAYS "Expecting a stackmap frame", GO BACK AND READ NUMBER 2 Download here. Github here. 1 Share this post Link to post Share on other sites
Posted November 8, 2015 So, this lets you stand in one place and continuously forage and botanize? 1 Share this post Link to post Share on other sites
Posted November 8, 2015 Correct. Mostly a cheaty mod for me, but I figure others might enjoy it. If not, it still provides an example of how to use the modloader. Share this post Link to post Share on other sites
Posted November 8, 2015 5. IF YOU GET AN ERROR THAT SAYS "Expecting a stackmap frame", GO BACK AND READ NUMBER 2Javassist has a method to fix the altered classes: methodInfo.rebuildStackMap(classPool);I had to use it to hook the player messages: https://github.com/ago1024/WurmServerModLauncher/blob/master/src/launcher/org/gotti/wurmunlimited/modloader/ProxyServerHook.java#L117 1 Share this post Link to post Share on other sites
Posted November 8, 2015 (edited) Javassist has a method to fix the altered classes: methodInfo.rebuildStackMap(classPool);I had to use it to hook the player messages: https://github.com/ago1024/WurmServerModLauncher/blob/master/src/launcher/org/gotti/wurmunlimited/modloader/ProxyServerHook.java#L117 Thanks for this, but it throws a BadByteCode exception at me when I implement it. I have tried both rebuildStackMap and rebuildStackMapIf6. The thing is, I'm not actually even touching any bytecode directly. I'm just telling a function which checks bytecode against a value to always return true. Original function and my code below. public static boolean isForagable(int tilex, int tiley) { int value = flagsMesh.getTile(tilex, tiley); return (value & 64) == 64; } private void ForagingFunction() { try { ClassPool classPool = HookManager.getInstance().getClassPool(); CtClass ex = HookManager.getInstance().getClassPool().get("com.wurmonline.server.Server"); ClassFile cf = ex.getClassFile(); CtClass[] parameters = new CtClass[]{CtPrimitiveType.intType, CtPrimitiveType.intType}; CtMethod method = ex.getMethod("isForagable", Descriptor.ofMethod(CtPrimitiveType.booleanType, parameters)); MethodInfo methodInfo = method.getMethodInfo(); method.insertBefore("return true;"); //methodInfo.rebuildStackMapIf6(classPool, cf); methodInfo.rebuildStackMap(classPool); method = null; parameters = null; ex = null; } catch (NotFoundException | CannotCompileException var4) { throw new HookException(var4); } } Edited November 8, 2015 by cantorsdust Share this post Link to post Share on other sites
Posted November 8, 2015 Get rock to hold down F-key Share this post Link to post Share on other sites
Posted November 8, 2015 rebuildStatckMap is required when jump addresses change. Does method.setBody("return true;") work? Maybe there's an issue with the dead code after the return. Share this post Link to post Share on other sites
Posted November 8, 2015 rebuildStatckMap is required when jump addresses change.Does method.setBody("return true;") work? Maybe there's an issue with the dead code after the return. Nope, it doesn't prevent compiling but still throws the same stack map error, and the code still complains about a BadBytecode exception. Share this post Link to post Share on other sites
Posted December 21, 2015 (edited) lol To bad this doesn't work. No just kidding Edited December 21, 2015 by Seodanrot 1 Share this post Link to post Share on other sites
Posted June 5, 2016 (edited) I think step 3 is causing an error for me. I have no skill in any of this, but this is what it looks like for me: %JAVA% "-Dworkdir=%CD%" -noverify "-Djava.library.path=%CD%..... Whenever I try to run the server, it gives me the stackmap frame. I've verified step 2 4 times, before having my IT roommate verify it as well. It;s not step 2 that's causing the error, so I think it's something I might be doing wrong in step 3? I don't have a clue. Edited June 5, 2016 by Stahe Share this post Link to post Share on other sites
Posted June 6, 2016 I didn't look at the code but if this is broken I use something like the following. -- @Override public void init() { try { jsAlwaysForage(); } catch (NotFoundException | CannotCompileException e) { e.printStackTrace(); } } -- private void jsAlwaysForage() throws NotFoundException, CannotCompileException { pool = HookManager.getInstance().getClassPool(); CtMethod ctmIsForagable = pool.get("com.wurmonline.server.Server").getMethod("isForagable", "(II)Z"); ctmIsForagable.setBody("{ return true; }"); CtMethod ctmIsBotanizable = pool.get("com.wurmonline.server.Server").getMethod("isBotanizable", "(II)Z"); ctmIsBotanizable.setBody("{ return true; }"); } Share this post Link to post Share on other sites