Jump to content

liverare

Scripter II
  • Posts

    1296
  • Joined

  • Last visited

  • Days Won

    3
  • Feedback

    0%

Everything posted by liverare

  1. Coding Tech is a channel on YouTube that has tons of conferences held by veteran software and web developers who've been in the industry since the very, very early days. One video that struck me in particular is this: This video in particular has me thinking back to how I used to write code. I've attached to this thread what was my premium Tanner & Crafter script that I no longer maintain, and also my old Clue Scroll Aid script that died years ago. I went for a task-based system with a side order of switch/case statements, and the code really fucking stinks. The only possible salvage are some of the enumerators, data-sets, and maybe a few libraries. However, the main takeaway is that my code is definitely a cautionary tale of what not to do. From watching this video, Dr. Subramaniam touches on things that I can definitely relate to: Technical debt. I ain't got time to refactor my old messes. High complexity = low cohesion. I've tried being a smart ass with how I approached solving a problem, only to then have that "solution" break sometime in the future. Had I kept it simple and not try to account for...everything, I wouldn't have nearly as much 'technical debt' to pay. Code coupling. Even my dependencies have dependencies, and the minute I so much as blink... These are just some of what I've reflected upon. One reason I bring this up because, while I'm guilty as sin, I know some of you--and you know who you are--who are also guilty as sin. Another video full of tips: tanner & crafter.zip ClueScrollAid.zip
  2. Why are you using float types? Why aren't you using conditional sleeps?
  3. I would consider it bad practice as that would be a loop within a loop, when only the main script loop is necessary. Conditional sleeps are great in preventing your bot from spam clicking stuff; which just so happens to be the best use case for them. If you're killing chickens, it's best to attack a chicken then sleep until you're either in combat or that chicken has been stolen and is in combat with someone else. If you choose to sleep during the fighting phase, you're opening yourself up to unnecessary risk. Checking your health, looking good loot, or making sure you're in a safe area will become harder to implement as you'd have to check for all those inside of your conditional sleep. Instead, the main loop cycle should be where you run these checks, not inside of a conditional sleep.
  4. I would advise against sleeping during combat as you risk your character dying. Instead, use the onLoop to your advantage: NPC target; @Override public int onLoop() { if (target != null && target.exists()) { if (target.equals(myPlayer().getInteracting())) { // TODO nothing } else { // TODO attack if (target.interact("Attack")) { // TODO conditionally sleep until we've begun attacking target } } } else { target = npcs.closest("Goblin"); } } You can then add in other important things, such as health checker, loot checker, area checker, to make sure you can step away from combat to deal with more important things.
  5. Try following these instructions:
  6. Your GUI & lock point is debatable: If you spent too much time in the GUI, you'll be logged out. If you're unprepared in-game, you'd have to stop the script so you can ready yourself and then restart it. If the GUI is more of a helper, then locking up the game renders the GUI pointless. You don't have to block the onStart from ending; you can simply run checks onLoop to make sure your bot doesn't do anything until it has the information it needs from the GUI. Also, you should include mention about script parameters, as they're very useful for power-users who don't want an expensive GUI to have to fiddle with. I wrote a tutorial about it here.
  7. An NPC listener is a good idea, but you don't want to go overboard with too many threads for this. I would suggest a single instance of a class that handles all the listening, then all you have to do is tell it what to listen to and tell it what to do when it trigger something. However, anything that involves controlling your character should be handed in the main script loop and not in a separate thread, or things will get messy.
  8. GrandExchange inherits API API has the abstract function initializeModule initializeModule might initialise stuff required for GrandExchange.isOpen to work Try the following: public static GrandExchangeOperations getInstance(Bot bot){ if(singleton == null){ singleton = new GrandExchangeOperations(); singleton.exchangeContext(bot); singleton.initializeModule(); } return singleton; } And let me know if it still doesn't work.
  9. Perhaps it's worth adding some sort of box you can tick/script parameter you can enter to forcibly turn it off/on.
  10. Cache data as @ProjectPact mentioned Avoid updating the cache every other second if it can be helped Bulky logic and calculations belong in your main script loop Keep rendering to a minimum and allow users to turn it off Use multi-threading in places where it makes sense to handle multiple set of tasks separately For power-users, script parameters > GUI If the task is simple, then the code should be too. Don't go overboard with task nodes, switch-case states, etc. think 'happy path'. Also, you should check out:
  11. Until you show us your code, there's not really much we can do to help troubleshoot the problem. But I'm guessing you've got a loop in a loop. You're looping through all the packs of item in your inventory and interacting with each one. As time progresses - and maybe Low CPU mode is set - the bot's time to run logic and execute actions are kind of crossing each other. Your bot shoots off an event to open a bunch of items that are no longer present, because at the moment that logic check was performed, it was true. Loops being loops, they don't care for logic and simply does what it's tasked to do before the main script loop can start anew. You're not performing checks inside your loop to ensure items that were valid are still valid before interacting with them. Show us some damn code.
  12. I brought a Note 8 phone outright from Amazon. If there's any way to get it upgraded for a small fee, I could charge you the difference for the skin.
  13. if (!gui.isStarted()) { stop(); return; } This is your problem. The onStart method is executed in its entirety and, before it's even rendered, you're checking whether the GUI has been started. It hasn't. You need to move this part of your code into your onLoop. Additionally, you need to give the user time to click the button. What I suggest is: @Override public int onLoop() { if (!gui.isStarted()) { if (gui.isVisible()) { // Do nothing (or spin camera to avoid auto-logout) } else { // User closed GUI without clicking start button, so stop stop(); } } else { // Normal bot stuff here... } return 500; }
  14. Your local scripts are loaded from the OSBot/scripts/ folder. If you've deleted the contents therein, there won't be any local scripts to load If you've compiled your scripts in JDK 9+ (check your IDE) then your scripts won't be loaded and an error will be thrown
  15. It's widely believed the bans are all delayed to prevent users from knowing which scripts/bots are at fault. Monday is probably the day they go through a list of accounts to be banned.
  16. You could create a projectile listener, listen out for the flaming one that you have to constantly move to avoid, grab the destination tile for those projectiles and then fire off an event handler that speedily moves your character using a custom mouse API (so you can click tiles much more quickly).
  17. If all you have to do is to move to 5 sequential tiles that Is not a poison pool Is not the 'previous' tile Then a simple loop would do: import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import org.osbot.rs07.api.map.Position; import org.osbot.rs07.api.model.RS2Object; import org.osbot.rs07.script.API; public class VorkathPoisonPhase extends API { Position startTile; List<Position> badTiles; @Override public void initializeModule() { startTile = myPosition(); badTiles = objects.getAll().stream() .filter(VorkathPoisonPhase::isPoisonPool) .map(RS2Object::getPosition) .collect(Collectors.toList()); } public Position getNextTile() { return getAdjacentTiles(myPosition()).stream() .filter(this::isGoodTile) .sorted(this::sortByClosestToStartTile) .findFirst() .orElse(null); } private List<Position> getAdjacentTiles(Position p) { List<Position> tiles = new LinkedList<Position>(); tiles.add(p.translate(0, -1)); // north tiles.add(p.translate(1, 0)); // east tiles.add(p.translate(0, 1)); // south tiles.add(p.translate(-1, 0)); // west return tiles; } private boolean isGoodTile(Position p) { return !badTiles.contains(p); } private int sortByClosestToStartTile(Position p1, Position p2) { return Integer.compare(startTile.distance(p1), startTile.distance(p2)); } private static boolean isPoisonPool(RS2Object obj) { return false; // TODO } } Note: isPoisionPool is incomplete. I don't know if the poison is an object/npc/projectile/etc. Get start tile and all poison tiles Create a function to get a list of all adjacent tiles to start tile Get next tile (filter out tiles that have poison and sort by distance (closest) to start tile) Then... public class Test extends Script { VorkathPoisonPhase vorkathPoisonPhase; @Override public void onStart() throws InterruptedException { vorkathPoisonPhase = new VorkathPoisonPhase(); vorkathPoisonPhase.exchangeContext(bot); } @Override public int onLoop() throws InterruptedException { // When poision phase... vorkathPoisonPhase.initializeModule(); for (int i = 0; i < 5; i++) { walking.walk(vorkathPoisonPhase.getNextTile()); } return 500; } } It's incomplete and untested, but the idea is to simply find the next suitable tile to walk to, preferably located nearby the start time.
  18. NPC portalNpc = null; RS2Object portalObj = null; int portalNpcDist = Integer.MAX_VALUE; int portalObjDist = Integer.MAX_VALUE; Entity portalEntity; // Find objects portalNpc = npcs.closest("Portal"); portalObj = objects.closest("Portal"); // Check if either NPC or OBJ is valid if (portalNpc != null || portalObj != null) { // Calculate distance to NPC if (portalNpc != null) { portalNpcDist = map.distance(portalNpc); } // Calculate distance to OBJ if (portalObj != null) { portalObjDist = map.distance(portalObj); } // Check distance // Note: NPC or OBJ may be null if (portalNpcDist < portalObjDist) { // NPC is closer portalEntity = portalNpc; } else { // OBJ is same distance/closer portalEntity = portalObj; } // Finally, check portal if (portalEntity != null) { // Interact if (portalEntity.interact("Exit")) { // TODO: Conditional sleep } } }
  19. I wrote this ad-hoc and untested function: public boolean useItemOnItem(String itemA, String itemB) throws IllegalArgumentException, RuntimeException { /* Variables */ boolean successful = false; String selectedItemName; /* Validation */ if (itemA == null || itemA.isEmpty()) { throw new IllegalArgumentException("Parameter \"itemA\" is invalid!"); } else if (itemB == null || itemB.isEmpty()) { throw new IllegalArgumentException("Parameter \"itemB\" is invalid!"); } else if (itemA == itemB) { throw new IllegalArgumentException("Parameter \"itemA\" and \"itemB\" must be different!"); } else if (!inventory.contains(itemA)) { throw new RuntimeException("Inventory doesn't contain: " + itemA); } else if (!inventory.contains(itemb)) { throw new RuntimeException("Inventory doesn't contain: " + itemB); } /* Process */ selectedItemName = inventory.getSelectedItemName(); if (selectedItemName != null) { if (selectedItemName == itemA) { /* Now click on item B */ successful = inventory.getItem(itemB).interact(); } else if (selectedItemName == itemB) { /* Now click on item A */ successful = inventory.getItem(itemA).interact(); } else { /* Deselect and then re-try (safe recursion) */ if (inventory.deselectItem()) { useItemOnItem(itemA, itemB); } else { throw new RuntimeException("Failed to deselect: " + selectedItemName); } } } else { /* Select item and re-try (safe recursion) */ if (inventory.interact("Use", itemA)) { successful = useItemOnItem(itemA, itemB); } else { throw new RuntimeException("Failed to select: " + itemA); } } return successful; } Then you could do: try { if (useItemOnItem("Needle", "Thread")) { /* Conditional sleep */ } } catch (IllegalArgumentException e) { /* I should have checked we have items before executing the function */ } catch (RuntimeException e) { /* Something bad happened... */ }
  20. In XAMPP, you need to be running both the Apache and MySQL. In your script, you need to make sure these are correct for you: String host = "localhost:3306"; String db = "big_league"; String user = "root"; String pass = ""; The only variable you should need to change is 'db', because the rest are default for me so they should be default for you. Failing that, I may be able to assist you via TeamViewer later. If you still can't get it working, PM me.
  21. Perhaps a combination of the interact function and message listener. If you interact with a patch, take note of which patch that was. If you receive a message that says you've used ultra-compost, then make a note that you used said compost with said patch. Then clear the patch reference so that it's not used again by mistake.
  22. I was able to successfully interact with a MySQL database from a script. I used XAMPP Control Panel v3.2.2 to handle Apache and MySQL locally. I used mysql-connector-java-8.0.11.jar as my SQL driver. I created a folder on my Desktop and put in the following: osbot-sql/ osbot-sql/lib/mysql-connector-java-8.0.11.jar osbot-sql/lib/OSBot 2.5.8.jar osbot-sql/Start OSBot with SQL Driver.bat The contents of the batch file is as follows: "C:\Program Files\Java\jre1.8.0_172\bin\java.exe" -cp "lib/*" org.osbot.Boot -debug The first bit "C:\...\..\..\" can be changed to just "java" if your running version of Java is compatible with OSBot. Mine isn't. If yours is, then you can simply do the following: java -cp "lib/*" org.osbot.Boot -debug Once the bot loaded, I then ran a simple test script to read from a table called "big_league" from my database. The test script is as follows: import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import org.osbot.rs07.script.Script; import org.osbot.rs07.script.ScriptManifest; @ScriptManifest(author = "", info = "", logo = "", name = "SQL Test", version = 0) public class Test extends Script { @Override public void onStart() throws InterruptedException { try { String host = "localhost:3306"; String db = "big_league"; String user = "root"; String pass = ""; String connStr = String.format("jdbc:mysql://%s/%s?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC", host, db); Connection conn = DriverManager.getConnection(connStr, user, pass); ResultSet results = conn.createStatement().executeQuery("SELECT `name` FROM `item`;"); while (results.next()) { logger.debug(results.getString("name")); } } catch (SQLException e) { logger.error(e); } } @Override public int onLoop() throws InterruptedException { return 50; } } And it worked. It printed out the 3 item names I had stored in my database. If a query works, then insert, update, delete, drop, etc. will also work too. Note: Your script won't be approved for SDN release because: SDN compiler won't have those libraries, so ClassNotFoundException will occur. Developers don't want to add bloat to OSBot that only benefits a few users. Potential licensing/legal issues using external libraries commercially, or redistributing them.
×
×
  • Create New...