Magerange Posted May 9, 2017 Share Posted May 9, 2017 So I am starting to get into Java slowly and I've been writing my first script. It seems to function, which is a great start for me. However, I have an issue with ConditionalSleeping. The script spamclicks on empty jugs and uses them on the waterpump, which makes script to slow down. How do I position this to fix it according to the condition (sleep untill inventory holds only jugs of water & my account is in the area near the pump)? Here is the code: @ScriptManifest(author = "Magerange", name = "JugFiller", info = "Fills jugs with water in east Falador", version = 1.0, logo = "") public final class Main extends Script { private final Area Pump = new Area (2949, 3382, 2949, 3383); @Override public final int onLoop() throws InterruptedException { if (canFill()){ fill(); } else { bank(); } return random(175, 270); } private boolean canFill() { return getInventory().contains("Jug"); } private boolean pumpUsable(){ return Pump.contains(myPlayer()); } private void fill() { if (!Pump.contains(myPosition())){ getWalking().webWalk(Pump); } else if (pumpUsable()) { Entity wPump = getObjects().closest(24004); if (wPump != null) inventory.interact("Use","Jug"); wPump.interact("Use"); } else { new ConditionalSleep(5000) { @Override public boolean condition() { return getInventory().isEmptyExcept("Jug of water") && Pump.contains(myPosition()); } }.sleep(); } } private void bank() throws InterruptedException { if(!Banks.FALADOR_WEST.contains(myPosition())) { getWalking().webWalk(Banks.FALADOR_WEST); } else if (!getBank().isOpen()) { getBank().open(); } else if (!getInventory().isEmptyExcept("Jug")) { getBank().depositAll(); } else if (getBank().contains("Jug")) { getBank().withdrawAll("Jug"); } else { stop(true); } } } 1 Quote Link to comment Share on other sites More sharing options...
Tom Posted May 9, 2017 Share Posted May 9, 2017 (edited) Your logic seems a little backward, you should be using the conditional sleep directly after an action private void fill() { if (!Pump.contains(myPosition())){ getWalking().webWalk(Pump); } else if (pumpUsable()) { Entity wPump = getObjects().closest(24004); if (wPump != null){ inventory.interact("Use","Jug"); if(wPump.interact("Use")){ new ConditionalSleep(5000) { @Override public boolean condition() { return getInventory().isEmptyExcept("Jug of water") && Pump.contains(myPosition()); } }.sleep(); } } } } Edited May 9, 2017 by Tom 2 Quote Link to comment Share on other sites More sharing options...
Magerange Posted May 9, 2017 Author Share Posted May 9, 2017 15 minutes ago, Tom said: Your logic seems a little backward, you should be using the conditional sleep directly after an action private void fill() { if (!Pump.contains(myPosition())){ getWalking().webWalk(Pump); } else if (pumpUsable()) { Entity wPump = getObjects().closest(24004); if (wPump != null){ inventory.interact("Use","Jug"); if(wPump.interact("Use")){ new ConditionalSleep(5000) { @Override public boolean condition() { return getInventory().isEmptyExcept("Jug of water") && Pump.contains(myPosition()); } }.sleep(); } } } } Thanks! It does seem logical, but the problem stays... Maybe it is the condition that is wrong too? What condition should I do? I don't think the condition 'myPlayer().isAnimating()' saves the day as well, because when filling jugs, player does stop for a short period of time. 1 Quote Link to comment Share on other sites More sharing options...
HeyImJamie Posted May 9, 2017 Share Posted May 9, 2017 Have you tried increasing the Conditional Sleep duration? as it'll reloop if either -> 5s is passed OR your condition is met (I think that's how it works anyway) 1 Quote Link to comment Share on other sites More sharing options...
Magerange Posted May 9, 2017 Author Share Posted May 9, 2017 (edited) 5 minutes ago, HeyImJamie said: Have you tried increasing the Conditional Sleep duration? as it'll reloop if either -> 5s is passed OR your condition is met (I think that's how it works anyway) Yes. Doesn't seem to help. I still think I have messed up on the condition. To be more specific about the problem and what I want to do with it. When you fill jugs with water (if you have full inventory with empty jugs) you have to use one jug on the pump and it will fill the whole inventory. This is what I would like to replicate. Currently it spam clicks after every jug filled to use a new empty jug on the waterpump... Edited May 9, 2017 by Magerange Quote Link to comment Share on other sites More sharing options...
Tom Posted May 9, 2017 Share Posted May 9, 2017 (edited) 4 minutes ago, HeyImJamie said: Have you tried increasing the Conditional Sleep duration? as it'll reloop if either -> 5s is passed OR your condition is met (I think that's how it works anyway) That IS how it works, however he stated that his script is spamming the jugs on the pump, regardless of the condition sleep. This indicates in my eyes that something is wrong with the condition Perhaps try the condition inventory().getAmount("Jug of Water") == 28 && Pump.contains(myPosition()) If this works, I think it has to do with filtering "Jug" and we can work something else out Edited May 9, 2017 by Tom 1 Quote Link to comment Share on other sites More sharing options...
HeyImJamie Posted May 9, 2017 Share Posted May 9, 2017 2 minutes ago, Tom said: That IS how it works, however he stated that his script is spamming the jugs on the pump, regardless of the condition sleep. This indicates in my eyes that something is wrong with the condition Perhaps try the condition inventory().getAmount("Jug of Water") == 28 && Pump.contains(myPosition()) If this works, I think it has to do with filtering "Jug" and we can work something else out Ahh, yeah my bad! Still learning myself. :P Gz on S3 Btw. 1 Quote Link to comment Share on other sites More sharing options...
Magerange Posted May 9, 2017 Author Share Posted May 9, 2017 7 minutes ago, Tom said: That IS how it works, however he stated that his script is spamming the jugs on the pump, regardless of the condition sleep. This indicates in my eyes that something is wrong with the condition Perhaps try the condition inventory().getAmount("Jug of Water") == 28 && Pump.contains(myPosition()) If this works, I think it has to do with filtering "Jug" and we can work something else out It does work! However, now I have to adjust the timer, I guess. Because it takes way more time to fill 28 jugs than 5 seconds. Quote Link to comment Share on other sites More sharing options...
Apaec Posted May 9, 2017 Share Posted May 9, 2017 2 minutes ago, Magerange said: It does work! However, now I have to adjust the timer, I guess. Because it takes way more time to fill 28 jugs than 5 seconds. I wouldn't adjust the timer as you would be sitting there for 30 seconds while the conditional sleep waits if you were to be interrupted. If you're animating while filling jugs, consider an asynchronous animation? -Apa 1 Quote Link to comment Share on other sites More sharing options...
Magerange Posted May 9, 2017 Author Share Posted May 9, 2017 1 minute ago, Apaec said: I wouldn't adjust the timer as you would be sitting there for 30 seconds while the conditional sleep waits if you were to be interrupted. If you're animating while filling jugs, consider an asynchronous animation? -Apa Much appreciated! However, I am currently just scratching only the surface so your comment unfortunately makes little to no sense to me... Quote Link to comment Share on other sites More sharing options...
Tom Posted May 9, 2017 Share Posted May 9, 2017 (edited) 8 minutes ago, Magerange said: It does work! However, now I have to adjust the timer, I guess. Because it takes way more time to fill 28 jugs than 5 seconds. Nice. A better condition would be !getInventory().contains(item -> item.getName().equals("Jug")) && Pump.contains(myPosition()) As this doesnt require you to have 28 jugs of water, just as many as you happen to have in your inventory without leaving any empty jugs behind Edited May 9, 2017 by Tom 1 Quote Link to comment Share on other sites More sharing options...
Magerange Posted May 9, 2017 Author Share Posted May 9, 2017 6 minutes ago, Tom said: Nice. A better condition would be !getInventory().contains(item -> item.getName().equals("Jug")) && Pump.contains(myPosition()) As this doesnt require you to have 28 jugs of water, just as many as you happen to have in your inventory without leaving any empty jugs behind Thanks once again, Tom! This might be a rookie question, but Eclipse doesn't seem to like "->" sign, therefore I can't use that line Quote Link to comment Share on other sites More sharing options...
Tom Posted May 9, 2017 Share Posted May 9, 2017 (edited) 4 minutes ago, Magerange said: Thanks once again, Tom! This might be a rookie question, but Eclipse doesn't seem to like "->" sign, therefore I can't use that line Make sure your project is setup for Java 1.8 For more information visit: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html Edited May 9, 2017 by Tom 1 Quote Link to comment Share on other sites More sharing options...
Apaec Posted May 9, 2017 Share Posted May 9, 2017 1 hour ago, Magerange said: Much appreciated! However, I am currently just scratching only the surface so your comment unfortunately makes little to no sense to me... Apologies - I should have made it a little clearer. Essentially the issue would be that, if - for whatever reason - your player were to be interrupted while filling jugs, it would wait out the conditional sleep rather than instantly re-using the jugs on the fountain. Solving this issue is a little tricky, and requires you to think about things that change constantly while you're filling the jug. We can then check for these changing features to determine whether or not you have been interrupted. For example, animation. the myPlayer#isAnimating() check lets you know whether you are currently performing any animation. However, on its own, this check is useless - You need a way to call this check concurrently to determine whether the player is still filling jugs. However, since the player is not permanently animating, you need some kind of threshold timer system which resets when the player is animating. This means that you can query the timer and determine how long it was since the player was animating, hence infer a suitable threshold to determine whether the player is interrupted. To implement this, you will need to use both a timing system and a concurrent thread. The timing system is relatively simple, and can easily be achieved solely using System#getCurrentTimeMillis() perhaps in a class. The concurrent system is a little more difficult as if not implemented correctly, it can cause a lot of issues. To add the concurrency, you could create a class that extends Thread, and then override the run method, or you could implement Runnable should you need to make use of inheritance. Make sure you look up some code examples first! If you're not sure what any of that means, don't worry - you could put the check in the onPaint, however this is probably not a great idea - I would highly recommend against putting anything other than paint code in the onPaint loop. It's not an easy problem to solve but hopefully that helped a little! -Apa 2 Quote Link to comment Share on other sites More sharing options...
Magerange Posted May 9, 2017 Author Share Posted May 9, 2017 14 minutes ago, Apaec said: Apologies - I should have made it a little clearer. Essentially the issue would be that, if - for whatever reason - your player were to be interrupted while filling jugs, it would wait out the conditional sleep rather than instantly re-using the jugs on the fountain. Solving this issue is a little tricky, and requires you to think about things that change constantly while you're filling the jug. We can then check for these changing features to determine whether or not you have been interrupted. For example, animation. the myPlayer#isAnimating() check lets you know whether you are currently performing any animation. However, on its own, this check is useless - You need a way to call this check concurrently to determine whether the player is still filling jugs. However, since the player is not permanently animating, you need some kind of threshold timer system which resets when the player is animating. This means that you can query the timer and determine how long it was since the player was animating, hence infer a suitable threshold to determine whether the player is interrupted. To implement this, you will need to use both a timing system and a concurrent thread. The timing system is relatively simple, and can easily be achieved solely using System#getCurrentTimeMillis() perhaps in a class. The concurrent system is a little more difficult as if not implemented correctly, it can cause a lot of issues. To add the concurrency, you could create a class that extends Thread, and then override the run method, or you could implement Runnable should you need to make use of inheritance. Make sure you look up some code examples first! If you're not sure what any of that means, don't worry - you could put the check in the onPaint, however this is probably not a great idea - I would highly recommend against putting anything other than paint code in the onPaint loop. It's not an easy problem to solve but hopefully that helped a little! -Apa Wow I will need some time to chew that one down! Seems like I picked a pretty hard method to crack with my first scripting attempt. Will take a deeper look into this, no doubt! Thank you once again! Quote Link to comment Share on other sites More sharing options...