Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
TheGengar

Using child/component values in script where entity selector is unable to filter them out?

Recommended Posts

To determine the letter of the fairy ring combination, and set it, I use the rotationZ of a interface child within the entire combination interface. The issue I'm facing is that I hard coded the indexes and I've read that it is bad practice. I'm unable to filter out the index I want using Laniax's entity selector since the child index has no text/actions and no unique textid or colour. I was wondering how I could overcome this? Is there another viable method aside from hardcoding child values?

Below is the code. It works perfectly. Would love any input regarding refactoring or better coding etiquette. :D

Thanks.

public class FairyRingHandler
{
    private static final int TELEPORT_ANIMATION = 3265;

    // Interfaces
    private static final int master = 398;
    private static final int childRotationOne = 3;
    private static final int childRotationTwo = 4;
    private static final int childRotationThree = 5;
    private static final int leftChildClockwise = 19;
    private static final int midChildClockwise = 21;
    private static final int rightChildClockwise = 23;

    // Rotation values
    private static final int restingRotation = 0;
    private static final int firstRotation = 1536;
    private static final int secondRotation = 1024;
    private static final int thirdRotation = 512;

    // Arrays
    private static final int[] rotations = {restingRotation, firstRotation, secondRotation, thirdRotation};
    private static final char[] validLeftChars = {'A', 'D', 'C', 'B'};
    private static final char[] validMidChars = {'I', 'L', 'K', 'J'};
    private static final char[] validRightChars = {'P', 'S', 'R', 'Q'};

    public static boolean setFairyRingCombination(String combination)
    {
        if (combination.length() != 3)
        {
            System.out.println("SetFairyRingCombination: Invalid combination length");
            return false;
        }

        // Rule out invalid character
        combination.toUpperCase();

        char letter1 = combination.charAt(0);
        char letter2 = combination.charAt(1);
        char letter3 = combination.charAt(2);

        if (!areValidCharacters(letter1, letter2, letter3))
        {
            System.out.println("setFairyRingCombination: Invalid characters entered.");
            return false;
        }

        // Open interface if it is not open
        if (!Interfaces.isInterfaceValid(master))
        {
            RSObject fairyRing = Entities.find(ObjectEntity::new).nameEquals("Fairy ring").getFirstResult();

            if (fairyRing == null)
            {
                System.out.println("setFairyRingCombination: No fairy rings are present.");
                return false;
            }

            String previousCombination = getFairyRingCombination();
            String action = "Last-destination (" + previousCombination + ")";

            // Tele to last destination
            if (previousCombination.equals(combination))
            {
                if (AccurateMouse.click(fairyRing, action))
                {
                    waitToFInishTeleporting();
                    return true;
                }

                System.out.println("setFairyRingCombination: Failed to open fairy ring interface.");
                return false;
            }

            // Open the interface
            if (!AccurateMouse.click(fairyRing, "Configure") || 
                !Timing.waitCondition(GBooleanSuppliers.isInterfaceValid(master), General.random(4800, 5340)))
            {
                System.out.println("setFairyRingCombination: Failed to open fairy ring interface.");
                return false;
            }
        }

        setCombinationLetter(letter1, leftChildClockwise);
        setCombinationLetter(letter2, midChildClockwise);
        setCombinationLetter(letter3, rightChildClockwise);

        if (!getFairyRingCombination().equals(combination))
        {
            System.out.println("setFairyRingCombination: Failed to set fairy ring combination, resetting");
            setFairyRingCombination(combination);
        }

        RSInterface confirm = Entities.find(InterfaceEntity::new).actionEquals("Confirm").getFirstResult();

        if (confirm == null)
        {
            System.out.println("setFairyRingCombination: Unable to find the confirm button, closing interface");

            RSInterface close = Entities.find(InterfaceEntity::new).actionEquals("Close").getFirstResult();

            if (close == null)
            {
                System.out.println("setFairyRingCombination: Unable to find close button?");
                return false;
            }

            close.click();
            return false;
        }

        confirm.click();

        if (!waitToFInishTeleporting())
        {
            System.out.println("setFairyRingCombination: Failed to teleport?");
            return false;
        }

        return true;
    }

    private static boolean waitToFInishTeleporting()
    {
        return  Timing.waitCondition(GBooleanSuppliers.waitForAnimation(TELEPORT_ANIMATION), General.random(1850, 2000)) &&
                Timing.waitCondition(GBooleanSuppliers.waitForAnimation(-1), General.random(3150, 3400));
    }

    private static boolean areValidCharacters(char one, char two, char three)
    {
        return isValidChar(one, validLeftChars) && isValidChar(two, validMidChars) && isValidChar(three, validRightChars);
    }

    private static boolean isValidChar(char givenChar, char[] validChars)
    {
        for (char character : validChars)
        {
            if (givenChar == character)
            {
                return true;
            }
        }

        return false;
    }

    private static void setCombinationLetter(char letter, int clockwiseIndex)
    {
        if (!Interfaces.isInterfaceValid(master))
        {
            System.out.println("setCombinationLetter: Fairy ring interface is not open.");
            return;
        }

        // case variables
        char[] characterCombination;
        int rotationChild;

        switch (clockwiseIndex)
        {
            case 19:
                characterCombination = validLeftChars;
                rotationChild = childRotationOne;
                break;
            case 21:
                characterCombination = validMidChars;
                rotationChild = childRotationTwo;
                break;
            case 23:
                characterCombination = validRightChars;
                rotationChild = childRotationThree;
                break;
            default:
                System.out.println("setCombinationLetter: Invalid lettrs, returning.");
                return;
        }

        // Find letter placement in the array.
        int currentRotation = Interfaces.get(master, rotationChild).getRotationZ();
        int desiredRotationIndex = getDesiredRotationIndex(characterCombination, letter);
        int currentRotationIndex = getCurrentRotationIndex(currentRotation);

        // Compare the two indexes and determine if you need to rotate clock, counter or nothing.
        int numberOfRotations;
        RSInterface rotationInterface;

        // TODO make it so if 3 rots required, do the other way (i.e. from clock to counter)
        if (currentRotationIndex < desiredRotationIndex)
        {
            // rotate clockwise the difference
            numberOfRotations = desiredRotationIndex - currentRotationIndex;
            rotationInterface = Interfaces.get(master, clockwiseIndex);
        }
        else
        {
            numberOfRotations = currentRotationIndex - desiredRotationIndex;
            rotationInterface = Interfaces.get(master, clockwiseIndex + 1);
        }

        // Rotate
        for (int i = 0; i < numberOfRotations; i++)
        {
            // CLick specified index
            rotationInterface.click();

            Timing.waitCondition(()->
            {
                General.sleep(125);
                return isRotationValueValid(rotationChild);
            }, General.random(1450, 1600));
        }
    }

    private static boolean isRotationValueValid(int rotationChild)
    {
        RSInterface rotationInterface = Interfaces.get(master, rotationChild);

        for (Integer rotation : rotations)
        {
            if (rotation == rotationInterface.getRotationZ())
            {
                return true;
            }
        }

        return false;
    }

    private static int getDesiredRotationIndex(char[] characterCombination, char letter)
    {
        int counter = 0;

        for (char character : characterCombination)
        {
            if (character == letter)
            {
                return counter;
            }

            counter++;
        }

        System.out.println("getDesiredRotationIndex: Error, unable to find character in given array");
        return -1;
    }

    private static int getCurrentRotationIndex(int currentRotation)
    {
        int counter = 0;

        for (int rotation : rotations)
        {
            if (rotation == currentRotation)
            {
                return counter;
            }

            counter++;
        }

        System.out.println("getCurrentRotationIndex: Error, unable to find rotation in given array");
        return -1;
    }

    /**
     * Returns a three-letter string whcih represents the fairy code combination. Please note that this should only be
     * called when the interface is not rotating (i.e. is at rest).
     *
     * @return combination
     */
    public static String getFairyRingCombination()
    {
        // Get rotation indexes and get the corresponding letters
        if (Interfaces.isInterfaceValid(master))
        {
            RSInterface masterInterface = Interfaces.get(master);

            int rotationIndexOne = getCurrentRotationIndex(masterInterface.getChild(childRotationOne).getRotationZ());
            int rotationIndexTwo = getCurrentRotationIndex(masterInterface.getChild(childRotationTwo).getRotationZ());
            int rotationIndexThree = getCurrentRotationIndex(masterInterface.getChild(childRotationThree).getRotationZ());

            if (rotationIndexOne == -1 || rotationIndexTwo == -1 || rotationIndexThree == -1)
            {
                System.out.println("getFairyRingCombination: The fairy ring is rotating thus unable to determine combination.");
                System.out.println("getFairyRingCombination: Please wait for it to stop rotating.");
                return "";
            }

            char charOne = validLeftChars[rotationIndexOne];
            char charTwo = validMidChars[rotationIndexTwo];
            char charThree = validRightChars[rotationIndexThree];

            return new String(new char[]{charOne, charTwo, charThree});
        }
        else
        {
            RSObject fairyRing = Entities.find(ObjectEntity::new).nameEquals("Fairy ring").getFirstResult();

            if (fairyRing == null)
            {
                System.out.println("getFairyRingCombination: No fairy rings are present.");
                return "";
            }

            String[] actions = fairyRing.getDefinition().getActions();
            String action = null;

            for (String s : actions)
            {
                if (s.startsWith("Last"))
                {
                    action = s;
                }
            }

            if (action == null)
            {
                System.out.println("getFairyRingCombination: Action is null some how ?.");
                return "";
            }

            return action.split("[()]")[1];
        }
    }
}

 

Share this post


Link to post
Share on other sites

It's only bad practice in the sense that interface IDs are subject to change. If you don't mind updating them if/when they do get changed, it's not really the end of the world.

Some things you could try though:

-Use the 'travel log' interface. It shows places you've recently gone to and you could probably grab info from there. I think you can also set favorites and have it activate the desired teleport location from there?

-Use DTMs/color to determine if the correct letter is selected in each spot

-Find some other identifying aspect of the interface other than text to identify each unique letter

  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Our picks

    • This update features:

      Fixed broken hooks from today's update


      Fix wilderness level with RuneLite (Thanks @Todd)


      Add support for Kotlin .class files in scripts (Thanks @wastedbro)


      Overhaul Inventory API (Thanks @wastedbro)


      Add List support for common methods


      Change method grouping to make more sense (by functionality)


      Refactor methods to utilize Java 8 streams instead of cumbersome loops




      Recognize chatbox minimization (Thanks @JoeDezzy1)


      Fix Screen#isInViewport when NPC chat is open (Thanks @JoeDezzy1)


      Fix login bot bugs (Thanks @erickho123)


      Fix hint arrow return values (Thanks @Encoded)


      Fix depositAllExcept functionality (Thanks @wastedbro)


      Change containing box interface bound and adjust for Y values (Thanks @erickho123)
      • 151 replies
    • This release will:

      Fix prayers and world hopper API (Thanks @JoeDezzy1 and @erickho123)


      Improve banking API (Thanks @Encoded)


      Adds methods for returning and using Java Lists, rather than arrays


      Slightly randomizes some hardcoded behaviour


      Removes sleeps from waitConditions; the efficiency saving potential is negligible in these use-cases, therefore cleaner code is preferable


      Other back-end improvements





      Note: If you are using LG, please restart both the RS client and TRiBot.
      • 90 replies
    • This release will:

      Add new internal framework for capturing exceptions


      Fix issue with not selecting the last column in world hopper (Thanks @Todd)


      Add a message about pin usage in Banking#openBank (Thanks @Todd)


      Disable the firewall by default (Thanks @Todd)


      Fix handling of the welcome screen after login (Thanks @Encoded)


      Fix wrong amount bank withdrawal (Thanks @Encoded)


      Fix Screen#isInViewport


      Fix Game#isInViewport (Thanks @Encoded)


      Call onBreakEnd for ListenerManager Breaking Listeners (Thanks @Encoded)


      Fix Prayer#getPrayerPoints NumberFormatException (Thanks @JoeDezzy1)



      Note: If you are using LG, please restart both the RS client and TRiBot.
      • 28 replies
    • This release will:

      Fix LG for both OSBuddy and RuneLite


      Fix issue where the resizable client isn't able to be made smaller (Thanks @JoeDezzy1)


      Fix detection of the logout game tab when resizable mode and side panels are enabled (Thanks @JoeDezzy1)


      Add initial support for Sentry to allow us to identify and easily debug exceptions happening with all TRiBot users


      Add methods to determine if the bank is actually loaded, and not just the overarching interface (Thanks @wastedbro)



      Upcoming updates:

      Improved CLI support


      Full Sentry support


      Much more
      • 64 replies
    • This release will:

      Fix NPE in Camera API (Thanks @wastedbro)


      Update deposit box interface ids (Thanks @Encoded)


      Add various bank methods (Thanks @wastedbro)


      Banking#getWithdrawXQuantity


      Banking#getDefaultWithdrawQuantity


      Banking#arePlaceholdersOn




      Fix resizeable minimap bug (Thanks @wastedbro)


      Remove Java 8 requirement


      Please note: TRiBot is not yet fully compatible with Java 10+




      Fix the break handler issues by ensuring the break handler thread never gets paused


      Fix broken settings hooks



      Upcoming updates:

      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
      • 68 replies
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...