Mad Moxxi 6 Share Posted September 13, 2015 Mad Moxxi's Mad Framework So I've decided that most approaches to script development, presented in the public domain, are utter garbage. Constantly back and forth through classes in numerous packages, I needed a way to contain this code along with my sanity. With IntelliJ in hand, I set out to conjure up a framework with which I can achieve most any script with relative ease. I started with a sort of backend, produced and open-sourced by fellow scripter. Sadly, they closed the github repo, but I continued to build on the code. I worked tirelessly to produce something robust, manageable and feature-packed. I present to the community, Mad Framework. My solution to a number of script-related problems. Think of the remainder of this thread as a kind of JavaDoc, as I find the structure and style more concise and informal. Anything applications of the Mad Framework are entirely up to the imagination of the person using it. In the near future, I will show how it is used more in-depth, as well as how you can create your own custom tasks. Custom tasks will allow much more control over the script's behaviour along with access to far more features than are present. Front end features Logic - Execute on Condition Execute a node only when a provided condition is met. new ExecuteOnConditionTask(getContext(), () -> !getContext().getInventory().isFull(), new WebWalkTask(getContext(), FISHING_SPOT)); - Selection by Condition Select between two ChainableTasks with a provided condition. The first will be executed when the condition returns true. new SelectionTask(getContext(), () -> getContext().getInventory().isFull(), new WebWalkTask(getContext(), BANK)), new WebWalkTask(getContext(), FISHING_SPOT); - Wait for Condition Halts execution until a condition or the provided timeout is met. new WaitForConditionTask(getContext(), 3600 () -> getContext().isIdle()); Banking - Withdraw Withdraws a specified number of a given item. Use -1 as an amount to withdraw all. new WithdrawTask(getContext(), "Lobster", -1); - Deposit All Deposits all items specified by a varargs argument. A boolean specifies if deposit boxes should be used. new DepositAllTask(getContext(), true, "Iron ore"); - Deposit All Except Deposits all items except for those passed through a varargs argument. A boolean specifies whether or not to use deposit boxes. new DepositAllExceptTask(getContext(), false, "Lobster"); Interaction - Interact with Entity Interacts with a nearby entity. Takes a name or filter, along with an action. new InteractEntityTask(getContext(), "Flesh crawler", "Bloom"); new InteractEntityTask(getContext(), (entity -> entity.getName().contains("Kalphite")), "Attack"); - Interact with Item Interacts with an item in the inventory. Takes a name or filter, along with an action. new InteractItemTask(getContext(), "Silver sickle (b)", "Bloom"); new InteractItemTask(getContext(), (item -> item.getName().contains("Amulet of glory")), "Edgeville"); - Item on Entity Uses an item on an entity. Takes a pair of names or filters. new ItemOnEntityTask(getContext(), "Rune essence", "Altar"); new ItemOnEntityTask(getContext(), (item -> item.getName().contains("essence")) ,(entity -> entity.getName().equalsIgnoreCase("Altar"))); - Item-on-Item Uses an item on another item (in the inventory). Takes a pair of names or filters. Also takes a boolean argument to randomize the order. new ItemOnItemTask(getContext(), false, (first -> first.getName().contains("Pestle and mortar")), (second -> getName().contains("Chocolate"))); new ItemOnItemTask(getContext(), false, "Pestle and mortar", "Chocolate"); Traversal - Web Walk Walks to a specified location using the web walker. Location can be specified with a name (varargs, will find the closest), coordinates or a filter. new WebWalkTask(getContext(), 2313, 3242, 0); new WebWalkTask(getContext(), 2313, 3242); new WebWalkTask(getContext(), "First name", "Second name"); new WebWalkTask(getContext(), (webNode -> webNode.getName().equalsIgnoreCase("First name"))); - Local Walk Walks to a specified location within the current region. Location can be specified with a Tile argument or coordinates. new LocalWalkTask(getContext(), new Tile(2313, 3242, 0)); new LocalWalkTask(getContext(), 2313, 3242, 0); new LocalWalkTask(getContext(), 2313, 3242); Back End Features Context The Context class provides a way to pass the game instance around the back end. Generally replaces any usages of the AbstractScript class e.g. Item food = script.getInventory().get("Lobster"); would become Item food = getContext().getInventory().get("Lobster"); Managers Also referred to as loadouts or configs, managers store and handle the usage of particular categorical sets of information within the Runescape world. They use a Map<String, T> in order to store this information. T would be the thing you are storing (e.g. Potion). The manager will check its respective container for T instances matching those in the provided generic. When they are loaded, they will be stored in the map, keyed by their name or String value. The manager will drink the potion given to manager.perform(Potion potion). You would have to implement a custom node for this; one that checks if any potions can be drank and passes them to the potion manager appropriately. Available Managers: - Potion Manager - Prayer Manager - Teleport Manager - Item Manager Web Walker The web walker provides almost completely unhindered traversal across the RuneScape world. It features stair traversal for both cross-plane and "Y ladders" (The ones that teleport across the map). It also uses an implementation of the Teleport Manager in order to provide teleporting int any script. It is used in much the same way as the DreamBot webwalker, so much of it will seem familiar. Custom Nodes You can also create custom Tasks and use them as you would the Tasks provided (InteractEntityTask etc). Here is an example one might use for the Banking class. public class BankingTask extends ChainableTask { private final String axeName; private boolean hasAxe; public BankingTask(Context context, String axeName) { super(context); this.axeName = axeName; } @Override public boolean execute() { // Standard processing method return getContext().getTaskExecutor().execute( hasAxe ? new DepositAllExceptTask(getContext(), false, axeName) : new WithdrawTask(getContext(), axeName, 1)); } @Override public void prepare() { // This executes if canExecute returns false } @Override public boolean canExecute() { // Can it execute? hasAxe = getContext().getInventory().contains(axeName) || getContext().getEquipment().contains(axeName); return getContext().getInventory().isFull() || !hasAxe; } } Script Examples import ... @ScriptManifest(category = Category.WOODCUTTING, name = "Mad Flesh Killer", author = "Mad Moxxi", version = 1.0) public class FleshKiller extends MadScript { private static final String FOOD = "Lobster"; private static final boolean DEPOSIT_BOX = false; private static final String BANK = DEPOSIT_BOX ? "Bank deposit box" : "Bank booth"; private static final String MONSTER = "Flesh crawler"; private static final String ATTACK = "Attack"; private static final String EAT = "Eat"; private ChainableTask task; @Override public int process() { if (task != null && getContext().getTaskExecutor().execute(task)) return 1200; return 600; } @Override public boolean start() { this.task = buildTask(); getContext().setTaskExecutor(new ChainExecutor(getContext())); return true; } @Override public ChainableTask buildTask() { return new SelectionTask(getContext(), // IF () -> !getContext().getInventory().contains(FOOD),// INVENTORY CONTAINS food new WebWalkTask(getContext(), getContext().getWebWalker().getClosest(BANK)) // WALK TO CLOSEST bank .chain(new DepositAllExceptTask(getContext(), DEPOSIT_BOX, FOOD)) // DEPOSIT ALL EXCEPT food .chain(new WithdrawTask(getContext(), FOOD, -1)), // WITHDRAW food, -1 // ELSE new ExecuteOnConditionTask(getContext(), // EXECUTE IF getContext()::isIdle, // context.isIdle new WebWalkTask(getContext(), getContext().getWebWalker().getClosest(MONSTER)) // WALK TO CLOSEST monster .chain(new InteractEntityTask(getContext(), MONSTER, ATTACK)) // INTERACT monster, attack .chain(new WaitForConditionTask(getContext(), // WAIT UNTIL () -> !getContext().isIdle())) // context.isIdle )).chain(new ExecuteOnConditionTask(getContext(), // EXECUTE IF () -> getContext().getCombat().getHealthPercent() < 25, // LOW HP new InteractItemTask(getContext(), FOOD, EAT))); // INTERACT food, eat } @Override public void finish() { } } import ... @ScriptManifest(category = Category.COMBAT, name = "Mad Willow Chopper", author = "Mad Moxxi", version = 1.0) public class MadwillowChopper extends MadScript { private static final boolean DEPOSIT_BOX = true; private static final String BANK = DEPOSIT_BOX ? "Bank deposit box" : "Bank booth"; private static final Tree TREE = Tree.WILLOW; private static final String CHOP = "Chop-down"; private ChainableTask task; @Override public int process() { if (task != null && getContext().getTaskExecutor().execute(task)) return 1200; return 600; } @Override public boolean start() { this.task = buildTask(); getContext().setTaskExecutor(new ChainExecutor(getContext())); return true; } @Override public ChainableTask buildTask() { return new SelectionTask(getContext(), () -> getContext().getInventory().isFull(), new DepositAllTask(getContext(), true, TREE.getLogName()), new SelectionTask(getContext(), () -> getContext().getTaskExecutor().execute(new InteractEntityTask(getContext(), (entity -> entity.getName().equalsIgnoreCase(TREE.getTreeName())), CHOP)), new WebWalkTask(getContext(), (webNode -> webNode.getName().contains(TREE.getTreeName()))), new WaitForConditionTask(getContext(), () -> getContext().isIdle()))); } @Override public void finish() { } } Link to comment Share on other sites More sharing options...
Diddy 265 Share Posted September 13, 2015 Looks MAD Link to comment Share on other sites More sharing options...
lily 490 Share Posted September 13, 2015 How memory intensive is it? Seems like we're playing tricky games with the Garbage Collector =p Link to comment Share on other sites More sharing options...
Val 125 Share Posted September 13, 2015 I wish I meant what one word of this meant. Link to comment Share on other sites More sharing options...
Mad Moxxi 6 Author Share Posted September 13, 2015 How memory intensive is it? Seems like we're playing tricky games with the Garbage Collector =p It shouldn't be very memory intensive. It'd be highly advisable to know how to use lambdas for Conditions and Filters, otherwise you'll end up with code like this: new WaitForConditionTask(getContext(), new Condition() { @Override public boolean verify() { return getContext().isIdle(); } }); new InteractEntityTask(getContext(), new Filter<Entity>() { @Override public boolean match(Entity entity) { return entity.getName().equals("Flesh crawler"); } }, "Attack"); Link to comment Share on other sites More sharing options...
Zawy 877 Share Posted September 13, 2015 Wohoo, good job Link to comment Share on other sites More sharing options...
Nuclear Nezz 2012 Share Posted September 13, 2015 O now I see what you were saying rip Link to comment Share on other sites More sharing options...
qbots 239 Share Posted September 13, 2015 i feel like for a big script the buildTask method could get messy? idk Link to comment Share on other sites More sharing options...
Computor 177 Share Posted September 13, 2015 Not trying to be a prick, but this looks worse than multiple classes/separation through packages. Too much code all packed into one area. Link to comment Share on other sites More sharing options...
Dogerina 330 Share Posted September 13, 2015 looks prety clunky fam Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.