From 5948f13f0633f03068a58ab64eb3bc336364aac8 Mon Sep 17 00:00:00 2001 From: Yuri Moens Date: Sat, 22 Jan 2022 12:07:08 +0100 Subject: [PATCH] Add Motherlode Miner --- motherlodeminer/motherlodeminer.gradle.kts | 52 ++++ .../openosrs/motherlodeminer/Config.java | 43 ++++ .../motherlodeminer/MotherlodeMiner.java | 232 ++++++++++++++++++ .../motherlodeminer/tasks/Deposit.java | 44 ++++ .../motherlodeminer/tasks/FixWheel.java | 39 +++ .../motherlodeminer/tasks/GoDown.java | 42 ++++ .../openosrs/motherlodeminer/tasks/GoUp.java | 32 +++ .../motherlodeminer/tasks/HandleBank.java | 45 ++++ .../openosrs/motherlodeminer/tasks/Mine.java | 52 ++++ .../motherlodeminer/tasks/WithdrawSack.java | 50 ++++ release/motherlodeminer-1.0.0.jar | Bin 0 -> 16701 bytes 11 files changed, 631 insertions(+) create mode 100644 motherlodeminer/motherlodeminer.gradle.kts create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/Config.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/MotherlodeMiner.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Deposit.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/FixWheel.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoDown.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoUp.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/HandleBank.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Mine.java create mode 100644 motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/WithdrawSack.java create mode 100644 release/motherlodeminer-1.0.0.jar diff --git a/motherlodeminer/motherlodeminer.gradle.kts b/motherlodeminer/motherlodeminer.gradle.kts new file mode 100644 index 0000000..9db745c --- /dev/null +++ b/motherlodeminer/motherlodeminer.gradle.kts @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019 Owain van Brakel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +version = "1.0.0" + +project.extra["PluginName"] = "Chaos Motherlode Miner" // This is the name that is used in the external plugin manager panel +project.extra["PluginDescription"] = "Diggy, diggy hole" // This is the description that is used in the external plugin manager panel + +dependencies { + compileOnly(project(":util")) +} + +tasks { + jar { + manifest { + attributes(mapOf( + "Plugin-Version" to project.version, + "Plugin-Id" to nameToId(project.extra["PluginName"] as String), + "Plugin-Provider" to project.extra["PluginProvider"], + "Plugin-Description" to project.extra["PluginDescription"], + "Plugin-Dependencies" to + arrayOf( + nameToId("Chaos Util"), + nameToId("iUtils") + ).joinToString(), + "Plugin-License" to project.extra["PluginLicense"] + )) + } + } +} \ No newline at end of file diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/Config.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/Config.java new file mode 100644 index 0000000..a73b1e6 --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/Config.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, Andrew EP | ElPinche256 + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package io.reisub.openosrs.motherlodeminer; + +import net.runelite.client.config.Button; +import net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup("chaosmotherlodeminer") + +public interface Config extends net.runelite.client.config.Config { + @ConfigItem( + keyName = "startButton", + name = "Start/Stop", + description = "Start the script", + position = 100 + ) + default Button startButton() { + return new Button(); + } +} \ No newline at end of file diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/MotherlodeMiner.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/MotherlodeMiner.java new file mode 100644 index 0000000..5aabb5f --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/MotherlodeMiner.java @@ -0,0 +1,232 @@ +package io.reisub.openosrs.motherlodeminer; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Provides; + +import io.reisub.openosrs.motherlodeminer.tasks.*; +import io.reisub.openosrs.util.CScript; +import io.reisub.openosrs.util.Task; +import io.reisub.openosrs.util.Util; +import io.reisub.openosrs.util.enums.Activity; +import io.reisub.openosrs.util.tasks.Eat; +import io.reisub.openosrs.util.tasks.KittenTask; +import io.reisub.openosrs.util.tasks.Run; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.*; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.events.*; +import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.plugins.PluginDependency; +import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.plugins.iutils.iUtils; +import net.runelite.client.plugins.iutils.scene.Position; +import net.runelite.client.plugins.iutils.scripts.iScript; +import org.pf4j.Extension; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Extension +@PluginDependency(Util.class) +@PluginDependency(iUtils.class) +@PluginDescriptor( + name = "Chaos Motherlode Miner", + description = "Diggy, diggy hole", + enabledByDefault = false +) +@Slf4j +public class MotherlodeMiner extends CScript { + @Provides + Config provideConfig(ConfigManager configManager) { + return configManager.getConfig(Config.class); + } + + private static final Set MOTHERLODE_MAP_REGIONS = ImmutableSet.of(14679, 14680, 14681, 14935, 14936, 14937, 15191, 15192, 15193); + private static final int UPPER_FLOOR_HEIGHT = -490; + private static final int SACK_LARGE_SIZE = 162; + private static final int SACK_SIZE = 81; + + private int curSackSize, maxSackSize; + + @Getter + @Setter + private boolean sackFull; + + @Getter + private boolean inMlm; + + @Getter + @Setter + private Position currentVeinPosition; + + private ScheduledExecutorService executor; + + @Override + protected void loop() { + game.tick(); + } + + @Override + protected void onStart() { + super.onStart(); + + inMlm = checkInMlm(); + + executor = Executors.newSingleThreadScheduledExecutor(); + addTask(Mine.class); + addTask(GoDown.class); + addTask(Deposit.class); + addTask(FixWheel.class); + addTask(WithdrawSack.class); + addTask(HandleBank.class); + addTask(GoUp.class); + } + + @Override + protected void onStop() { + executor.shutdownNow(); + } + + @Subscribe + private void onGameTick(GameTick event) { + if (currentVeinPosition != null && currentActivity == Activity.MINING) { + if (game.objects().withPosition(currentVeinPosition).withAction("Mine").first() == null) { + currentVeinPosition = null; + setActivity(Activity.IDLE); + } + } + + if (executor != null) { + executor.schedule(() -> { + for (Task t : tasks) { + if (t.validate()) { + log.info(t.getStatus()); + t.execute(); + break; + } + } + + checkActionTimeout(); + }, 0, TimeUnit.MILLISECONDS); + } + } + + @Subscribe + private void onAnimationChanged(AnimationChanged event) { + Actor actor = event.getActor(); + if (actor == null || actor.getName() == null || !actor.getName().equals(game.localPlayer().name())) return; + + int animId = game.localPlayer().animation(); + switch (animId) { + case AnimationID.MINING_MOTHERLODE_BRONZE: + case AnimationID.MINING_MOTHERLODE_IRON: + case AnimationID.MINING_MOTHERLODE_STEEL: + case AnimationID.MINING_MOTHERLODE_BLACK: + case AnimationID.MINING_MOTHERLODE_MITHRIL: + case AnimationID.MINING_MOTHERLODE_ADAMANT: + case AnimationID.MINING_MOTHERLODE_RUNE: + case AnimationID.MINING_MOTHERLODE_DRAGON: + case AnimationID.MINING_MOTHERLODE_DRAGON_OR: + case AnimationID.MINING_MOTHERLODE_DRAGON_UPGRADED: + case AnimationID.MINING_MOTHERLODE_CRYSTAL: + case AnimationID.MINING_MOTHERLODE_GILDED: + case AnimationID.MINING_MOTHERLODE_INFERNAL: + case AnimationID.MINING_MOTHERLODE_3A: + setActivity(Activity.MINING); + break; + } + } + + @Subscribe + private void onGameObjectDespawned(GameObjectDespawned event) { + if (currentActivity == Activity.REPAIRING && event.getGameObject().getName().equals("Broken strut")) { + setActivity(Activity.IDLE); + } + } + + @Subscribe + private void onItemContainerChanged(ItemContainerChanged event) { + if (currentActivity == Activity.DEPOSITING) { + if (!game.inventory().withName("Pay-dirt").exists()) { + setActivity(Activity.IDLE); + } + } else if (currentActivity == Activity.WITHDRAWING) { + if (game.inventory().withId( + ItemID.RUNITE_ORE, + ItemID.ADAMANTITE_ORE, + ItemID.MITHRIL_ORE, + ItemID.GOLD_ORE, + ItemID.COAL, + ItemID.UNCUT_SAPPHIRE, + ItemID.UNCUT_EMERALD, + ItemID.UNCUT_RUBY, + ItemID.UNCUT_DIAMOND, + ItemID.UNCUT_DRAGONSTONE + ).exists()) { + setActivity(Activity.IDLE); + } + } else if (currentActivity == Activity.MINING) { + if (game.inventory().full()) { + setActivity(Activity.IDLE); + currentVeinPosition = null; + } + } + } + + @Subscribe + private void onVarbitChanged(VarbitChanged event) { + if (inMlm) { + refreshSackValues(); + if (curSackSize >= maxSackSize - 26) { + sackFull = true; + } + } + } + + @Subscribe + private void onGameStateChanged(GameStateChanged event) { + if (event.getGameState() == GameState.LOADING) { + inMlm = checkInMlm(); + } else if (event.getGameState() == GameState.LOGIN_SCREEN) { + inMlm = false; + } + } + + private boolean checkInMlm() { + GameState state = game.client.getGameState(); + if (state != GameState.LOGGED_IN && state != GameState.LOADING) { + return false; + } + + int[] currentMapRegions = game.client.getMapRegions(); + + for (int region : currentMapRegions) { + if (!MOTHERLODE_MAP_REGIONS.contains(region)) { + return false; + } + } + + return true; + } + + private void refreshSackValues() { + curSackSize = game.client.getVar(Varbits.SACK_NUMBER); + boolean sackUpgraded = game.client.getVar(Varbits.SACK_UPGRADED) == 1; + maxSackSize = sackUpgraded ? SACK_LARGE_SIZE : SACK_SIZE; + + if (curSackSize == 0) { + sackFull = false; + } + } + + public boolean isUpstairs() { + return Perspective.getTileHeight(game.client, game.client.getLocalPlayer().getLocalLocation(), 0) < UPPER_FLOOR_HEIGHT; + } +} \ No newline at end of file diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Deposit.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Deposit.java new file mode 100644 index 0000000..68ca4d0 --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Deposit.java @@ -0,0 +1,44 @@ +package io.reisub.openosrs.motherlodeminer.tasks; + +import io.reisub.openosrs.motherlodeminer.MotherlodeMiner; +import io.reisub.openosrs.util.Task; +import io.reisub.openosrs.util.enums.Activity; +import net.runelite.client.plugins.iutils.game.iObject; +import net.runelite.client.plugins.iutils.scene.Position; +import net.runelite.client.plugins.iutils.scene.RectangularArea; + +import javax.inject.Inject; + +public class Deposit extends Task { + @Inject + private MotherlodeMiner plugin; + + private final RectangularArea hopperArea = new RectangularArea( + new Position(3741, 5657, 0), + new Position(3755, 5674, 0) + ); + + @Override + public String getStatus() { + return "Depositing in hopper"; + } + + @Override + public boolean validate() { + return plugin.getCurrentActivity() == Activity.IDLE + && !plugin.isUpstairs() + && game.inventory().withName("Pay-dirt").exists(); + } + + @Override + public void execute() { + iObject hopper = game.objects().withName("Hopper").nearest(); + if (hopper == null) return; + + plugin.setActivity(Activity.DEPOSITING); + + hopper.interact("Deposit"); + game.waitUntil(() -> plugin.getCurrentActivity() == Activity.IDLE, 15); + game.tick(2); + } +} diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/FixWheel.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/FixWheel.java new file mode 100644 index 0000000..d116c36 --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/FixWheel.java @@ -0,0 +1,39 @@ +package io.reisub.openosrs.motherlodeminer.tasks; + +import io.reisub.openosrs.motherlodeminer.MotherlodeMiner; +import io.reisub.openosrs.util.Task; +import io.reisub.openosrs.util.enums.Activity; +import net.runelite.client.plugins.iutils.game.iObject; + +import javax.inject.Inject; +import java.util.List; + + +public class FixWheel extends Task { + @Inject + private MotherlodeMiner plugin; + + private List brokenStruts; + + @Override + public String getStatus() { + return "Fixing wheel"; + } + + @Override + public boolean validate() { + if (plugin.getCurrentActivity() != Activity.IDLE || plugin.isUpstairs()) return false; + + brokenStruts = game.objects().withName("Broken strut").all(); + + return brokenStruts.size() == 2; + } + + @Override + public void execute() { + plugin.setActivity(Activity.REPAIRING); + + brokenStruts.get(0).interact("Hammer"); + game.waitUntil(() -> plugin.getCurrentActivity() == Activity.IDLE, 30); + } +} diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoDown.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoDown.java new file mode 100644 index 0000000..7a77a06 --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoDown.java @@ -0,0 +1,42 @@ +package io.reisub.openosrs.motherlodeminer.tasks; + +import io.reisub.openosrs.motherlodeminer.MotherlodeMiner; +import io.reisub.openosrs.util.Task; +import io.reisub.openosrs.util.enums.Activity; +import net.runelite.client.plugins.iutils.game.iObject; +import net.runelite.client.plugins.iutils.scene.Position; +import net.runelite.client.plugins.iutils.scene.RectangularArea; + +import javax.inject.Inject; + +public class GoDown extends Task { + @Inject + private MotherlodeMiner plugin; + + private final RectangularArea miningArea = new RectangularArea( + new Position(3748, 5676, 0), + new Position(3754, 5684, 0) + ); + + @Override + public String getStatus() { + return "Going down"; + } + + @Override + public boolean validate() { + return plugin.getCurrentActivity() == Activity.IDLE + && plugin.isUpstairs() + && game.inventory().full(); + } + + @Override + public void execute() { + iObject ladder = game.objects().withName("Ladder").nearest(); + if (ladder == null) return; + + ladder.interact("Climb"); + game.waitUntil(() -> !plugin.isUpstairs(), 15); + game.tick(); + } +} diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoUp.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoUp.java new file mode 100644 index 0000000..b89b84f --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/GoUp.java @@ -0,0 +1,32 @@ +package io.reisub.openosrs.motherlodeminer.tasks; + +import io.reisub.openosrs.motherlodeminer.MotherlodeMiner; +import io.reisub.openosrs.util.Task; +import net.runelite.client.plugins.iutils.game.iObject; + +import javax.inject.Inject; + +public class GoUp extends Task { + @Inject + private MotherlodeMiner plugin; + + @Override + public String getStatus() { + return "Going up"; + } + + @Override + public boolean validate() { + return !plugin.isUpstairs(); + } + + @Override + public void execute() { + iObject ladder = game.objects().withName("Ladder").withAction("Climb").nearest(); + if (ladder == null) return; + + ladder.interact("Climb"); + game.waitUntil(() -> plugin.isUpstairs(), 15); + game.tick(); + } +} diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/HandleBank.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/HandleBank.java new file mode 100644 index 0000000..4f3477a --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/HandleBank.java @@ -0,0 +1,45 @@ +package io.reisub.openosrs.motherlodeminer.tasks; + +import io.reisub.openosrs.motherlodeminer.MotherlodeMiner; +import io.reisub.openosrs.util.enums.Activity; +import io.reisub.openosrs.util.tasks.BankTask; +import net.runelite.api.ItemID; + +import javax.inject.Inject; +import java.time.Duration; +import java.time.Instant; + +public class HandleBank extends BankTask { + @Inject + private MotherlodeMiner plugin; + + @Override + public boolean validate() { + if (plugin.isUpstairs() || plugin.getCurrentActivity() != Activity.IDLE) return false; + + return isLastBankDurationAgo(Duration.ofSeconds(2)) + && game.inventory().withId( + ItemID.RUNITE_ORE, + ItemID.ADAMANTITE_ORE, + ItemID.MITHRIL_ORE, + ItemID.GOLD_ORE, + ItemID.COAL, + ItemID.UNCUT_SAPPHIRE, + ItemID.UNCUT_EMERALD, + ItemID.UNCUT_RUBY, + ItemID.UNCUT_DIAMOND, + ItemID.UNCUT_DRAGONSTONE + ).exists(); + } + + @Override + public void execute() { + openBank(); + + bank.depositExcept(false, ItemID.HAMMER, ItemID.GOLDEN_NUGGET); + bank.close(); + game.waitUntil(() -> !bank.isOpen(), 3); + + last = Instant.now(); + } +} diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Mine.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Mine.java new file mode 100644 index 0000000..c2904a8 --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/Mine.java @@ -0,0 +1,52 @@ +package io.reisub.openosrs.motherlodeminer.tasks; + +import io.reisub.openosrs.motherlodeminer.MotherlodeMiner; +import io.reisub.openosrs.util.Task; +import io.reisub.openosrs.util.enums.Activity; +import net.runelite.client.plugins.iutils.game.iObject; +import net.runelite.client.plugins.iutils.scene.Position; +import net.runelite.client.plugins.iutils.scene.RectangularArea; + +import javax.inject.Inject; + +public class Mine extends Task { + @Inject + private MotherlodeMiner plugin; + + private final RectangularArea miningArea = new RectangularArea( + new Position(3748, 5676, 0), + new Position(3754, 5684, 0) + ); + + private iObject oreVein; + + @Override + public String getStatus() { + return "Mining"; + } + + @Override + public boolean validate() { + if (plugin.getCurrentActivity() != Activity.IDLE) return false; + + if (!plugin.isUpstairs()) return false; + + oreVein = game.objects() + .withName("Ore vein") + .withAction("Mine") + .filter((obj) -> miningArea.contains(obj.position()) && !obj.position().equals(new Position(3764, 5665, 0))).nearest(); + + return plugin.getCurrentActivity() == Activity.IDLE + && !game.inventory().full() + && oreVein != null; + } + + @Override + public void execute() { + plugin.setCurrentVeinPosition(oreVein.position()); + + oreVein.interact("Mine"); + game.waitUntil(() -> plugin.getCurrentActivity() == Activity.MINING, 15); + + } +} diff --git a/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/WithdrawSack.java b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/WithdrawSack.java new file mode 100644 index 0000000..4c32e80 --- /dev/null +++ b/motherlodeminer/src/main/java/io/reisub/openosrs/motherlodeminer/tasks/WithdrawSack.java @@ -0,0 +1,50 @@ +package io.reisub.openosrs.motherlodeminer.tasks; + +import io.reisub.openosrs.motherlodeminer.MotherlodeMiner; +import io.reisub.openosrs.util.Task; +import io.reisub.openosrs.util.enums.Activity; +import net.runelite.api.ItemID; +import net.runelite.client.plugins.iutils.game.iObject; + +import javax.inject.Inject; + +public class WithdrawSack extends Task { + @Inject + private MotherlodeMiner plugin; + + @Override + public String getStatus() { + return "Withdrawing from sack"; + } + + @Override + public boolean validate() { + return !plugin.isUpstairs() + && plugin.getCurrentActivity() == Activity.IDLE + && plugin.isSackFull() + && !game.inventory().withId( + ItemID.RUNITE_ORE, + ItemID.ADAMANTITE_ORE, + ItemID.MITHRIL_ORE, + ItemID.GOLD_ORE, + ItemID.COAL, + ItemID.UNCUT_SAPPHIRE, + ItemID.UNCUT_EMERALD, + ItemID.UNCUT_RUBY, + ItemID.UNCUT_DIAMOND, + ItemID.UNCUT_DRAGONSTONE + ).exists(); + } + + @Override + public void execute() { + iObject sack = game.objects().withName("Sack").withAction("Search").nearest(); + if (sack == null) return; + + plugin.setActivity(Activity.WITHDRAWING); + + sack.interact("Search"); + + game.waitUntil(() -> plugin.getCurrentActivity() == Activity.IDLE, 30); + } +} diff --git a/release/motherlodeminer-1.0.0.jar b/release/motherlodeminer-1.0.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..f410bd9387dbf8ce2f524674e862ecc0c93ddad8 GIT binary patch literal 16701 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 literal 0 HcmV?d00001