joedobo

[BETA] Farm barrel mod

19 posts in this topic

Farm barrel is a tool to sow seeds over a square area of configurable size. You harvest crops directly into the barrel and it can hold a lot, probably more then you can carry. You never have to deal with where to put crops because your inventory only holds 100 items. You can only harvest ripe crops. I tried to maintain overall time required and skill-gained-per-time-spent from farming. I wanted to remove a lot of tedious clicking, dragging and sorting.

 

:Required:

For WU 1.3.1.3  Note, I only update every other WU official release. This may mean you need to use the previous version, I do :).
Ago's WurmServerModLauncher. https://github.com/ago1024/WurmServerModLauncher/releases. I tested with v0.24

:Install:
*Get one of the archive releases and unpack it into the mods folder. The folder path should look something like this: ~Steam\SteamApps\common\Wurm Unlimited Dedicated Server\mods
* Releases are at github: https://github.com/Joedobo27/FarmBarrelMod/releases

* Open the properties file and choose what options you want.

 

a few notes:

1. Concerning the container-like-behaviour and item movement that goes on with this mod. I use this rather strange container-like setup in order to avoid having to do a bunch of bytecode changes to WU base container and item movement code.

2. the barrel rounds qualities down to the nearest whole number. (coding issue, let me know if there is a better way)

3. When the barrel's name changes it will deactivate it. If I can figure out how to make it stay active, I will.

4. I tried to make skill gain be uniform for all actions, just like yield.

5. There is a configure option to set the minimum action time. for default WU this is like 3s or 30 for mod's settings. If you have a server with a larger action speed multiplier, I have 10, you may want to use a smaller minimum time.

6. the only lasting effect this mod has is adding a new item, the seed barrel. Disabling it shouldn't do anything more then leave a missing item template behind.

7. To make things easier for me you can't work with seeds or crops in their normal item state. You'll need to empty the barrel into a bulk container and then, using the normal way, withdraw the items. 

8. speed runes, woa, rare barrel, and rare action all speed up the action timer. Specifically: woa and runes are like normal, 10% speed reduction per item rarity level, 33% speed reduction per action rarity level.

 

Sowing

* Sow a square shaped area with seeds. Activate the barrel containing farm seed, use it on a dirt or farm tile, and choose sow from the menu. It will sow an area based on its configuration settings.
* Each time a tile is sown the barrel's weight is reduced. If all of the seeds are used up the barrel's name will rename itself so it no longer has the custom crop tag.

* sowing radius is configured with the configure action. The max radius this will support is 15 and that would make a 31x31 square. You can configure the max radius and at what skill levels those unlock in the properties file. You could easily set it up to say a max of 2, so a 5x5 area, at 90 skill if you wanted something more restrictive.


Harvesting
*Activate the barrel, use it on a ripe farm tile (there are two ripe stages), and choose "harvest" from the menu. You don't need a scythe to harvest grain with this mod. The normal harvest method will also be on the list for non-grain crops. My harvest is listed towards the bottom. I may rename the action to avoid confusion. Harvested crops go directly into the seed barrel and each time you harvest the barrel's weight will go up. If the barrel is empty and after the first harvest it's name will update with a custom naming tag. Basicly, you harvest crops with the barrel and then empty it into the appropriate bulk bin (food in FSB, all else in BSB). The empty action will transfer what is in the barrel into the bin all at once. Farm yield is different then default WU. The idea is to have a uniform yield per a farm action(sow, rake harvest). It's better explained here:

http://forum.wurmonline.com/index.php?/topic/146351-wip-farm-barrel-mod/&do=findComment&comment=1579527

 

Configure

Open a r-click menu on the barrel (regardless of what is active) and there should be "configure" in the list. This will open a window that lets you set how large of a sow radius the barrel will use. There aren't any restrictions on settings here other then the max values supported. It's when a toon goes to sow that the skill checks, available seed, compatible tiles available....etc come into play. The supply value is how many seeds will be put in the barrel for the supply action.

 

Supply

Activate the barrel and use it on a crop (seed state or crop state) in a bulk container. In other words, target the crop inside a bulk container. It will transfer the lesser of the set supply quantity or the available crop count minus one. (I subtract one because I'm lazy; I don't have to deal with partial item nor deal with destroying the bulk item in the bin). The barrel will be renamed to have a custom tag for whatever the seed is inside it. The farm barrel automatically converts crops to their seed equivalent. If you click on a pumpkin it will put pumpkin seed in the barrel and reduce the pumpkin count in the bin all the while preserving the proper item counts for both seed and crop. You can only have one type of crop in the barrel at once (it's a code restriction problem, let me know if there is a better way). You can have seeds in a barrel and then target the same type of crop to fill it with more of the same seeds. You can also target seeds of the same crop type. 

 

Empty

This will put the crops inside the barrel directly into the bulk container. The barrel will rename itself and remove the custom crop tag.

 

Examine

Works like the normal examine

[16:14:30] A tool used to sow seed over an area. You can barely make out the signature of its maker,  '.ac.'.

[16:14:30] The barrel is set to sow a 1 square area and the supply amount is 50. It has 28 of sugar beet at 26 quality.

[16:14:30]  It could be improved with a log.

 

 

I'm not sure about these:

* Harvesting an area has an issue I'm not sure how to deal with. Crops don't get ripe at the same time always. I could make it so the harvest barrel only harvests ripe crops...idk
* Raking an area could be done but it's likely the toon would often run out of stamina. I could extend the rake times for area rake to offset the times we'd wait for stamina regeneration...idk.
* I'd like to figure out a way to harvest crops and put them directly into a harvest barrel that is inside a dragged vehicle. Likewise, it would be good if the same thing could be done for the seed barrel, sow with seeds that are in a barrel that's inside a dragged vehicle.

 

 

source: https://github.com/Joedobo27/FarmBarrelMod/blob/master/src/com/Joedobo27/farmbarrelmod/FarmBarrelMod.java

Edited by joedobo
1 person likes this

Share this post


Link to post
Share on other sites

I tried to add a new action, Propagate, instead of extending the "Sow" action. This didn't work either.

 

error log:

Spoiler

[02:47:11 PM] INFO com.Joedobo27.clayshards4concrete.ClayNShards4ConcreteMod: Mortar + Lye removed and Concrete creation modded.
[02:47:11 PM] SEVERE org.gotti.wurmunlimited.modloader.server.Listeners: ServerStartedListener handler for mod FarmBarrelMod failed
java.lang.RuntimeException: java.lang.IllegalAccessException: Can not set static final [Lcom.wurmonline.server.behaviours.ActionEntry; field com.wurmonline.server.behaviours.Actions.actionEntrys to [Lcom.wurmonline.server.behaviours.ActionEntry;
    at org.gotti.wurmunlimited.modsupport.actions.ModActions.registerAction(ModActions.java:51)
    at com.Joedobo27.farmbarrelmod.PropagateAction.<init>(PropagateAction.java:44)
    at com.Joedobo27.farmbarrelmod.FarmBarrelMod.onServerStarted(FarmBarrelMod.java:110)
    at org.gotti.wurmunlimited.modloader.server.ServerHook.lambda$fireOnServerStarted$2(ServerHook.java:45)
    at org.gotti.wurmunlimited.modloader.server.Listeners.lambda$fire$0(Listeners.java:35)
    at java.util.concurrent.CopyOnWriteArrayList.forEach(Unknown Source)
    at org.gotti.wurmunlimited.modloader.server.Listeners.fire(Listeners.java:33)
    at org.gotti.wurmunlimited.modloader.server.ServerHook.fireOnServerStarted(ServerHook.java:45)
    at org.gotti.wurmunlimited.modloader.server.ProxyServerHook$1$1.invoke(ProxyServerHook.java:56)
    at org.gotti.wurmunlimited.modloader.classhooks.HookManager.invoke(HookManager.java:302)
    at com.wurmonline.server.ServerLauncher.runServer(ServerLauncher.java)
    at com.wurmonline.server.gui.WurmServerGuiController.StartOfflineButtonClicked(WurmServerGuiController.java:341)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.reflect.misc.Trampoline.invoke(Unknown Source)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
    at javafx.event.Event.fireEvent(Unknown Source)
    at javafx.scene.Node.fireEvent(Unknown Source)
    at javafx.scene.control.Button.fire(Unknown Source)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(Unknown Source)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
    at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
    at javafx.event.Event.fireEvent(Unknown Source)
    at javafx.scene.Scene$MouseHandler.process(Unknown Source)
    at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source)
    at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$355(Unknown Source)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
    at com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
    at com.sun.glass.ui.View.notifyMouse(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$149(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalAccessException: Can not set static final [Lcom.wurmonline.server.behaviours.ActionEntry; field com.wurmonline.server.behaviours.Actions.actionEntrys to [Lcom.wurmonline.server.behaviours.ActionEntry;
    at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(Unknown Source)
    at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(Unknown Source)
    at sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl.set(Unknown Source)
    at java.lang.reflect.Field.set(Unknown Source)
    at org.gotti.wurmunlimited.modloader.ReflectionUtil.setPrivateField(ReflectionUtil.java:58)
    at org.gotti.wurmunlimited.modsupport.actions.ModActions.registerAction(ModActions.java:49)
    ... 81 more

[02:47:11 PM] INFO com.Joedobo27.fishingignoresrange.FishingIgnoresRange: Disabling fishing targeting proximity requirements SUCCESS

 

Has anyone got these interfaces to work in server modLoader: ModAction, BehaviourProvider, ActionPerformer?

 

I'm about ready to give up on them and insert code with JA.

 

 

edit...

I needed "ModActions.init();" in the init() section of the main class.

Edited by joedobo

Share this post


Link to post
Share on other sites

i haven't a clue on any of this, but I just wanted to say thanks for your mods, it sure is making life a lot simpler,

 

so just a note of gratitude that's all.

Share this post


Link to post
Share on other sites

Noob mistake on my part. I didn't take into consideration the entire class structure for the examples on Ago's actiondemo. I just took the action class and didn't look at the mod's main class. Its necessary to do a "ModActions.init();" and a "ModActions.registerAction(new PropagateAction());" in main because it won't work otherwise.

 

Getting familiar with using the BehaviourProvider and ActionPerformer will greatly expand what's possible.

 

@ozmodsThank you.

And I'd like to thank Ago. Without modlauncher we'd still be changing decompiled code (kinda-source) and dropping modified java files into the server/client.jar files.

1 person likes this

Share this post


Link to post
Share on other sites

@joedoboHow is this mod coming along? I would love to have it on the server I am on. Thank you in advance for making it.

Share this post


Link to post
Share on other sites

On hold until 1.3 is out and It's a high priority to finish. I'll likely have to fix my other mods first. I updated the github with my most recent changes.

It's missing some code regarding this:

private static WeakHashMap<Action, SowActionData> actionListener;

Which is a way to remember data for the whole action's duration.

 

 

Share this post


Link to post
Share on other sites

I'm stuck on the ConfigureSeedBarrelQuestion.class and that the answer() method never gets called. I know the question is asked because the UI pops up in game. The log file printing in the question constructor are the only ones that print:

[12:17:09 AM] INFO com.wurmonline.server.questions.Question: construct Item [ID: 12883496594178, name: seed barrel, QL: 76.716446, Tile: 491,767]
[12:17:09 AM] INFO com.wurmonline.server.questions.Question: id 501

 

Here is the question class:

https://github.com/Joedobo27/FarmBarrelMod/blob/master/src/com/wurmonline/server/questions/ConfigureSeedBarrelQuestion.java

 

Here is the action performer that calls it:

https://github.com/Joedobo27/FarmBarrelMod/blob/master/src/com/joedobo27/farmbarrelmod/ConfigureSeedBarrelAction.java

 

Thank you, if someone want's to take a look at this.

 

Share this post


Link to post
Share on other sites

Sorry, i don't see anything that would cause it to not work at a quick glance... did you try using the new ModQuestions stuff ago added?

 

Also your decoding in decodeRadius and decodeSupplyQuantity is wrong, you need to shift the bits right, or you'll always get 0 from the second &.

Share this post


Link to post
Share on other sites

Thanks @bdew

 

I've started to convert this over to use the ModQuestions modloader tools. I feel bad asking for examples because Ago already does so much with writing the tools. It's just hard for me to understand things without examples. Anyone know of  some examples that use the ModQuestions tools?

 

Everything except the answer part seems to be working. 

Share this post


Link to post
Share on other sites

Joe I put a note for you on discord. I don't see a sendQuestion in your answer, and everything I can rip outa the wurm code questions has a sendQuestion at the end of the answers.

Share this post


Link to post
Share on other sites

Awesome Idea! Hope it goes well

Share this post


Link to post
Share on other sites

I'm stuck again...

When using the ActionPerformer isn't it possible to have the mod add to an existent action? I want to add another sow type action but doing so bugs out the old way of sowing with seeds.

Here is code for my sow action:

https://github.com/Joedobo27/FarmBarrelMod/blob/master/src/com/joedobo27/farmbarrelmod/SowAction.java

 

Right now my mod lets me start the sow action when using seed on dirt tile but it seems to get ended right away. I get a start event message and then nothing.

 

I read the wiki for the this: https://github.com/ago1024/WurmServerModLauncher/wiki/Mods-ActionDemo. I see that it says ActionPerformer  replaces WU action but I thought Ago updated this tool to make it possible to add to WU actions with new ones.

 

Any thoughts on this?

Share this post


Link to post
Share on other sites

I'm not sure why it's not working for you, it looks to me like you're chaining correctly to ActionPerformer.super.action. Maybe setting a breakpoint on that call and tracing where it goes with a debugger will show why it's going wrong.

 

But why are you using the vanilla sow action id anyway? You could just make your own sow action (that will be used only with the barrel), and leave vanilla to do it's own thing when seeds are activated.

Share this post


Link to post
Share on other sites

@bdew

"try a debugger", I've never been able to get a debugger to work. For intelliJ one needs to run the project from the IDE and I can't get that to work. I'll look into putting a stack trace through the Logger.

 

"make a new actionId", I thought the word "sow" must be unique. It seems I can make a new actionId # and also call it "Sow".

 

Thank you for the advise! I was starting to give up on WU as it's surprisingly discouraging when there doesn't seem to be anyone around to ask for help or bounce ideas off of.

 

 

Share this post


Link to post
Share on other sites
5 minutes ago, joedobo said:

@bdew

"try a debugger", I've never been able to get a debugger to work. For intelliJ one needs to run the project from the IDE and I can't get that to work. I'll look into putting a stack trace through the Logger.

 

 

Same here with intelliJ and Netbeans.  I'd be happy to work in any IDE if I could get a debugger to work and see some of the internals in action.

Share this post


Link to post
Share on other sites

So the easiest way to get a debugger to work in intellij:

 

  1. Go to run configurations
  2. Add a "Remote" config,
  3. Switch "transport" to "shared memory" (you can leave this on socket, but i've ran into windows not closing the socket when restarting debug sessions)
  4. Write something unique in "shared memory address" (if you are debugging multiple instances, or client+server, etc.) 
  5. Copy the text from "command line arguments blah blah blah" box (the first one)
  6. Paste it somewhere in the command line in modlauncher.bat, e.g. 
    %JAVA% "-Dworkdir=%CD%" "-Djava.library.path=%CD%\nativelibs" %LOGGING% -Xmn256M -Xms512m -Xmx2048m -XX:+OptimizeStringConcat -XX:+AggressiveOpts -agentlib:jdwp=transport=dt_shmem,server=y,suspend=n,address=youradresshere -jar modlauncher.jar  %*

     

  7. Run modlauncher.bat
  8. Make sure your new remote profile is selected in IDEA
  9. Click debug

The first 6 steps need only be done once, for future use just repeat 7-9.

 

Also, if for debugging vanilla code - don't attach sources decompiled by an external decompiler (procyon/jd/whatever), let intellij use it's internal decompiler, or your debugging will be wonky due to line number mismatches.

1 person likes this

Share this post


Link to post
Share on other sites

Those debug instruction are easy to use. Guess it's all about knowing how to use the IDE tool. Now with my action performer problem, all the jumping around with action performer is a bit confusing but the simple fact the debugger works now is just too cool!

Share this post


Link to post
Share on other sites

I'm making progress on this. For some reason some things only work with new custom actions. I tried to reuse "empty" to transfer seed from a barrel into a bin and just couldn't get it to work.

 

Okay now, the reason for this update is I'd like to change this mod's harvest quantity metrics. As a short story, a few years ago in WO, Tich nerfed farming with the 1.1 change. Basically the idea was if you rake more you'll get more yield. But the cost of that was no-rake folks got nerfed. Further, the bonuses from raking didn't scale equality so planting more fields was actually better then raking more. I tried my hardest to point out that farming yield (and skill gain for that matter) should scale equally based on effort done. And it shouldn't matter what that kind of effort was done. Thus a sow, rake, and harvest should all contributed equally using time as a equalization bases.

 

Now I can make what I wanted be so! Basically I'd change farming yield for this mod's harvest action so it's calculated with modified-skill / 15 equals the yield for two actions. Modified skill is a kinda a weighted average of skill and rake quality. The end result is a person would see higher yield harvest. but it would also make thing equal so you could farm however you wanted an know you're not doing something less efficient. Note that the yield would have a minimum function so yield is never less then 2, even if without raking. Here is a brief summary table:

Spoiler

rake count 5    
skill divisor 15    
       
skill sow+harvest rake total yeild
10 0.667 1.666666667 2.000
20 1.333 3.333333333 5.000
30 2.000 5 7.000
40 2.667 6.666666667 9.000
50 3.333 8.333333333 12.000
60 4.000 10 14.000
70 4.667 11.66666667 16.000
80 5.333 13.33333333 19.000
90 6.000 15 21.000
100 6.667 16.66666667 23.000

 

Farm barrel is a supplementary system so player could still use the default WO ways. I won't be removing it or changing that in anyway. 

2 people like this

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