Scrifen -- Hafen scripting API

Forum for alternative clients, mods & discussions on the same.

Re: Scrifen -- Hafen scripting API

Postby algorithm » Thu Jun 23, 2016 12:56 pm

Rhakar wrote:Sorry if I'm slightly off topic ;), but is there a way to reload the script.js without restarting the client?


of course you can :)

but let me show how to do this with few simple steps.

first, you should change onUserInput function to:
Code: Select all
function onUserInput(input) {
  print("On user input " + input);
  eval(input);
}

or something similar(key here is eval(input);)

Next, you need way to load files. I propose to do it with this function:
Code: Select all
var loadFileToString = function(fileName) {
  return('' + new java.lang.String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(fileName))));
}

Then you can execute script from file in current scope. Few more steps to do it:
Code: Select all
var script = null;
var loadScript = function() {
  eval(loadFileToString("scripts/test.js"));
}
function onGameLoaded(game) {
  print('Game loaded');
  g = game;
  loadScript();
}

scripts/test.js contains:
Code: Select all
script = new Object();

script.print = function() {
   print("some shit");
}


so now(if all other stuff in script.js setup correctly) you can run client and after it load you can type in console "script.print();" and it will print you:
On user input script.print();
some shit

then you can change scripts/test.js file to something like this:
Code: Select all
script = new Object();

script.print = function() {
   print("some other shit");
}

type in console "loadScript();" and then "script.print();" again. If you do all right you will get:
loadScript();
On user input loadScript();
script.print();
On user input script.print();
some other shit


you can do this even with script.js file itself, but you suppose to find way to call it within global context :)

P.S. Few more additions to understand it right.
In script.js you defines script variable in global scope, so you can use it everywhere in code.
After that, in onGameLoaded() function client execute loadScript() function which loads scripts/test.js file in which we construct our script variable as empty Object and assign one field to it(print function).
When you recall loadScript() function manually via console your client executes this file again, script variable reconstructs as new empty object and all fields reassigns to it according to current file content.
P.P.S. I'm not a Java or JS programmer or even CS major, just SO and Google, so i'm open to all critics :)
algorithm wrote:Cape awarded? ;)

jorb wrote:Oh, for sure. Delivery 2022. ;)
algorithm
 
Posts: 216
Joined: Thu Aug 13, 2015 2:17 pm

Re: Scrifen -- Hafen scripting API

Postby mdsantahaven » Mon Jul 04, 2016 4:17 pm

Damn, you guys are so smart!


Slightly offtopic and basic - is there any way to conveniently check if there is any water in the flask?
( i did a workaround through the barrel\stamina\flower menu checks, but that's lame)


And one more..
Is there any object hierarchy somewhere?
example:
from the example script I know the payer has .coords object inside. there is a method for it for example and coords are used in the script as well.

however...

I get a object on the map and I need to go to it, though the only method I have is - goto (x,y)... so I need to get the coords of an object.
how?
I assumed! object also has coords and it worked. yay.

but what else is there?
development is kind of a pandorabox atm :(

Thanks!
User avatar
mdsantahaven
 
Posts: 5
Joined: Fri Feb 11, 2011 4:42 am

Re: Scrifen -- Hafen scripting API

Postby Granger » Mon Jul 04, 2016 6:23 pm

Look into the Sourcecode, run the client in a debugger to inspect the state or write a method to dump an object tree to stdout.
⁎ Mon Mar 22, 2010 ✝ Thu Jan 23, 2020
User avatar
Granger
 
Posts: 9263
Joined: Mon Mar 22, 2010 2:00 pm

Re: Scrifen -- Hafen scripting API

Postby mdsanta » Tue Jul 05, 2016 3:54 am

Granger wrote:Look into the Sourcecode, run the client in a debugger to inspect the state or write a method to dump an object tree to stdout.

Thx....


Here is another problem...
Code: Select all
function dropCropsFromInv(){
    var inv = g.getInvItems();
   for (var i = 0; i < inv.length; i++) {
      if ((inv[i] == cropName) || (inv[i] == cropSeedName)) {
                     g.dropItem(inv[i]);
           sleep (200);
                   }
   }
}


getting exception in g.dropItem(inv[i]);
org.mozilla.javascript.WrappedException: Wrapped haven.UI$UIException: Wdgmsg sender (haven.GItem) is not in rwidgets (script.js#707)
at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1893)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:148)
at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:225)
at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:32)
at org.mozilla.javascript.gen.script_js_1._c_dropCropsFromInv_28(script.js:707)
at org.mozilla.javascript.gen.script_js_1.call(script.js)
at org.mozilla.javascript.optimizer.OptRuntime.callName0(OptRuntime.java:74)
at org.mozilla.javascript.gen.script_js_1._c_harvestAll_27(script.js:634)
at org.mozilla.javascript.gen.script_js_1.call(script.js)
at org.mozilla.javascript.optimizer.OptRuntime.callName(OptRuntime.java:63)
at org.mozilla.javascript.gen.script_js_1._c_doAction_22(script.js:547)
at org.mozilla.javascript.gen.script_js_1.call(script.js)
at org.mozilla.javascript.optimizer.OptRuntime.callName0(OptRuntime.java:74)
at org.mozilla.javascript.gen.script_js_1._c_onGameLoaded_4(script.js:114)
at org.mozilla.javascript.gen.script_js_1.call(script.js)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:393)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3282)
at org.mozilla.javascript.gen.script_js_1.call(script.js)
at haven.Evaluator.call(Evaluator.java:140)
at haven.GameUI.lambda$new$0(GameUI.java:208)
at haven.Evaluator.lambda$new$0(Evaluator.java:39)
at java.lang.Thread.run(Unknown Source)
Caused by: haven.UI$UIException: Wdgmsg sender (haven.GItem) is not in rwidgets
at haven.UI.wdgmsg(UI.java:272)
at haven.Widget.wdgmsg(Widget.java:641)
at haven.Widget.wdgmsg(Widget.java:643)
at haven.GameUI.wdgmsg(GameUI.java:832)
at haven.Widget.wdgmsg(Widget.java:643)
at haven.Window.wdgmsg(Window.java:316)
at haven.GameUI$Hidewnd.wdgmsg(GameUI.java:423)
at haven.Widget.wdgmsg(Widget.java:643)
at haven.Inventory.wdgmsg(Inventory.java:166)
at haven.Widget.wdgmsg(Widget.java:643)
at haven.Widget.wdgmsg(Widget.java:636)
at haven.Game.dropItem(Game.java:844)
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 org.mozilla.javascript.MemberBox.invoke(MemberBox.java:126)
... 20 more


PS. ...in some cases when this crash doesn't happen... I see a strange thing...
lets say I have 10 items I need to drop.
script comes to this method... starts dropping them..
and in the middle of it - goes to the next step. 0_o sometimes - still trying to finish this one.
Can somebody explain what happens? Is it running as parallel thread and doesn't keep up with the game of some sorts?
User avatar
mdsanta
 
Posts: 99
Joined: Mon May 09, 2016 8:36 pm

Re: Scrifen -- Hafen scripting API

Postby Granger » Tue Jul 05, 2016 8:03 am

mdsanta wrote:Here is another problem...
Code: Select all
function dropCropsFromInv(){
    var inv = g.getInvItems();
   for (var i = 0; i < inv.length; i++) {
      if ((inv[i] == cropName) || (inv[i] == cropSeedName)) {
                     g.dropItem(inv[i]);
           sleep (200);
                   }
   }
}


lets say I have 10 items I need to drop.
script comes to this method... starts dropping them..
and in the middle of it - goes to the next step. 0_o sometimes - still trying to finish this one.
Can somebody explain what happens? Is it running as parallel thread and doesn't keep up with the game of some sorts?


g.getInvItems() seems to return a list of names (at least you compare it directly to cropName||cropSeesName), and g.dropItem() seems to drop one item referenced through the name.

That particular interface into the inventory is bad: with multiple items of same name it dosn't specify which individual object you work on, so when you drop one the next loop will drop the same item in case it hasn't vanished from the container yet or even throw the exception since the object vanishes between g.dropItem() selecting it by name (which requires another scan of the container contents) and accessing the object to actually send the message to the server.
⁎ Mon Mar 22, 2010 ✝ Thu Jan 23, 2020
User avatar
Granger
 
Posts: 9263
Joined: Mon Mar 22, 2010 2:00 pm

Re: Scrifen -- Hafen scripting API

Postby mdsanta » Tue Jul 05, 2016 2:17 pm

Granger wrote:That particular interface into the inventory is bad: with multiple items of same name it dosn't specify which individual object you work on, so when you drop one the next loop will drop the same item in case it hasn't vanished from the container yet or even throw the exception since the object vanishes between g.dropItem() selecting it by name (which requires another scan of the container contents) and accessing the object to actually send the message to the server.


Thanks, Mon! Sounds legit to be the damn root cause.
guess it will be a good idea to ask for methods to get list of objects from inv and drop them by id.


... as to loops interrupted I don't know yet. Need to do some reading about asynchronous JS nature and see if I can write the code around that.
Though thinking about what you said - it is possible that script thinks it dropped all when in reality it didn't happen yet... more debugging for me.
User avatar
mdsanta
 
Posts: 99
Joined: Mon May 09, 2016 8:36 pm

Re: Scrifen -- Hafen scripting API

Postby algorithm » Wed Jul 06, 2016 7:59 am

mdsanta wrote:
Code: Select all
function dropCropsFromInv(){
    var inv = g.getInvItems();
   for (var i = 0; i < inv.length; i++) {
      if ((inv[i] == cropName) || (inv[i] == cropSeedName)) {
                     g.dropItem(inv[i]);
           sleep (200);
                   }
   }
}


Another bad thing here - using sleep function. It stops main thread and can cause some problems.
Solution is to use callbacks:

Code: Select all
function dropCropsFromInv(callback) {
   var loop = function() {
      var inv = g.getInvItems();
      for (var i = 0; i < inv.length; i++) {
            if ((inv[i] == cropName) || (inv[i] == cropSeedName)) {
               g.dropItem(inv[i]);
               setTimeout(loop, 200);
               return;
            }
      }
      if(callback) setTimeout(callback, 50);
   }
   loop();
}

In this case you define a callback which will be called after function finished. Main loop defined as function which will call self each time after dropping single crop with timeout of 200 ms. In this case no thread blocking.
algorithm wrote:Cape awarded? ;)

jorb wrote:Oh, for sure. Delivery 2022. ;)
algorithm
 
Posts: 216
Joined: Thu Aug 13, 2015 2:17 pm

Re: Scrifen -- Hafen scripting API

Postby mdsanta » Wed Jul 06, 2016 2:59 pm

algorithm wrote:Solution is to use callbacks...
...
In this case you define a callback which will be called after function finished. Main loop defined as function which will call self each time after dropping single crop with timeout of 200 ms. In this case no thread blocking.


Algorithm, very much appreciated, Sir!

I myself started to realize the uniqness of JS and all these calls and timeouts, plus b0r3d0m mentioned about sleep in his script...so - more and more learning for me.
Totaly new concept.


I have another question as well if you don't mind:
Is there any reliable way to control action completion? This concept when script thread is playing run-and-catch game with the game and UI drives me nuts.
so if I plant something - I can of course check if a new object showed up in the said coordinates.
if I take something in hand.... can verify that number of item in inv went down by 1.
but all these are just a ways to know mm.. what a black cat in the dark room does based on the sounds it makes... if you know what I mean.
User avatar
mdsanta
 
Posts: 99
Joined: Mon May 09, 2016 8:36 pm

Re: Scrifen -- Hafen scripting API

Postby algorithm » Thu Jul 07, 2016 6:48 am

mdsanta wrote:
algorithm wrote:Solution is to use callbacks...
...
In this case you define a callback which will be called after function finished. Main loop defined as function which will call self each time after dropping single crop with timeout of 200 ms. In this case no thread blocking.


Algorithm, very much appreciated, Sir!

I myself started to realize the uniqness of JS and all these calls and timeouts, plus b0r3d0m mentioned about sleep in his script...so - more and more learning for me.
Totaly new concept.


I have another question as well if you don't mind:
Is there any reliable way to control action completion? This concept when script thread is playing run-and-catch game with the game and UI drives me nuts.
so if I plant something - I can of course check if a new object showed up in the said coordinates.
if I take something in hand.... can verify that number of item in inv went down by 1.
but all these are just a ways to know mm.. what a black cat in the dark room does based on the sounds it makes... if you know what I mean.


Some of API's has return values to check result.
But you should imagine that you live in a very determent world, and you can't brake it rules in other ways than change the world itself :)
algorithm wrote:Cape awarded? ;)

jorb wrote:Oh, for sure. Delivery 2022. ;)
algorithm
 
Posts: 216
Joined: Thu Aug 13, 2015 2:17 pm

Re: Scrifen -- Hafen scripting API

Postby APXEOLOG » Thu Jul 07, 2016 2:57 pm

mdsanta wrote:I have another question as well if you don't mind:
Is there any reliable way to control action completion? This concept when script thread is playing run-and-catch game with the game and UI drives me nuts.
so if I plant something - I can of course check if a new object showed up in the said coordinates.
if I take something in hand.... can verify that number of item in inv went down by 1.
but all these are just a ways to know mm.. what a black cat in the dark room does based on the sounds it makes... if you know what I mean.

That's the downside of the event-based system. I wonder why people still use it for bots
W10 Meme Plot | W9 Mantis Garden | W8 Core | W7 Ofir | W6 the City of Dis | W5 Vitterstad | W4 A.D. | W3 Mirniy
jorb wrote:All your characters will be deleted, and I will level every village any one of them were ever members of.
User avatar
APXEOLOG
 
Posts: 1267
Joined: Fri Apr 23, 2010 7:58 am
Location: Somewhere on Earth

PreviousNext

Return to The Wizards' Tower

Who is online

Users browsing this forum: No registered users and 81 guests