Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Buy OSRS Gold

Sell OSRS Gold
NeuroGenix

[SNIPPET] RSLogin

Recommended Posts

Posted (edited)

I've put together this RSLogin class which has the method RSLogin.login(user, pass, long sleepOnDisconnect). This is useful for scripts that hop worlds a lot and encounter the too many login attempts screen because the Login.login method will force you to sleep for 8 to 10 minutes (or restart your script) when this happens but now you can specify the sleep duration in sleepOnDisconnect.

It may also be useful in different situations, I'm not 100% sure about this, but I think the Login.login method executes as follows:

  1. Check login message (probably switch(Login.getLoginMessage))
  2. return false if it equals INVALID, BANNED, etc.
  3. otherwise attempt to login

Whereas RSLogin.login executes:

  1. Check login message (switch(Login.getLoginMessage))
  2. Attempt to login if LOGIN_MESSAGE.ENTER is returned
  3. else, click back button, reattempt login
  4. return false if it AGAIN equals INVALID, BANNED, etc

Which is useful for scripts like mine which hold multiple Account objects during runtime and cycle through them as banned because for me when an account goes to log in, immediately after the previous account was banned, using Login.login would return false since it reads the login message from the previous account. Now, using RSLogin.login, I can safely call login on my next account and it will disregard the BANNED screen, attempt to login again, and only return false if it yet again fails; moving onto the next account.

Lemme know if you find this useful, or whether you have any suggestions.

RSLogin class

Spoiler
package scripts.API.Login;

import java.awt.Rectangle;

import org.tribot.api.General;
import org.tribot.api.Timing;
import org.tribot.api.input.Mouse;
import org.tribot.api2007.Game;
import org.tribot.api2007.Interfaces;
import org.tribot.api2007.Login;
import org.tribot.api2007.Login.LOGIN_MESSAGE;
import org.tribot.api2007.types.RSInterface;

import scripts.API.Util.GameUtil;
import scripts.API.Util.InterfaceUtil;

public class RSLogin {
	
	private static final int MAX_ATTEMPTS = 3, MOUSE_BUTTON = 1, FIRST_LOGIN_ATTEMPT = 0;
	
	private static final int EXISTING_USER_BTN_X = 409, EXISTING_USER_BTN_Y = 281, WIDTH = 40, HEIGHT = 20,
								CANCEL_BTN_X = 409, CANCEL_BTN_Y = 311, BACK_BUTTON_X = 334, BACK_BUTTON_Y = 318,
								OK_BUTTON_X = 356, OK_BUTTON_Y = 292, TRY_AGAIN_BUTTON_X = 330, TRY_AGAIN_BUTTON_Y = 266;
	
	public static boolean login(String username, String password, long sleepOnDisconnect) {
		for(int i = 0; i < MAX_ATTEMPTS; i++) {
			switch(getLoginState()) {
			case LOGGED_OUT:
				return handleLogIn(username, password, sleepOnDisconnect, FIRST_LOGIN_ATTEMPT);
			case CONNECTING:
				return Timing.waitCondition(() -> hasLoadedWelcomeScreen(), 20000) && login(username, password, sleepOnDisconnect);
			case WELCOME_SCREEN:
				return handleWelcomeScreen();
			case LOGGED_IN:
				if(Timing.waitCondition(() -> GameUtil.isGameLoaded(), General.randomLong(15000, 20000))) {
					printSuccessfulLogin();
					return true;
				}
				return false;
			case UNKNOWN:
				General.println("ERROR: Unknown game state.");
				General.sleep(300, 600);
			default:
				General.println("ERROR: Line 38 LoginUtil.login");
				General.sleep(300, 600);
			}
		}	
		return false;
	}
	
	private static boolean handleWelcomeScreen() {
		RSInterface welcomeScreen = Interfaces.get(378, 87);
		if(!InterfaceUtil.isOnScreen(welcomeScreen))
			return false;
		
		General.sleep(400, 1400);
		
		return InterfaceUtil.click(welcomeScreen) && Timing.waitCondition(() -> GameUtil.isGameLoaded(), 10000);
	}
	
	private static boolean hasLoadedWelcomeScreen() {
		RSInterface welcomeScreen = Interfaces.get(378, 87);
		return InterfaceUtil.isOnScreen(welcomeScreen);
	}
	
	private static LOGINSTATE getLoginState() {			
		switch(Game.getGameState()) {
		case 10:
			return LOGINSTATE.LOGGED_OUT;
		case 20:
			return LOGINSTATE.CONNECTING;
		case 25:
			return LOGINSTATE.CONNECTING;
		case 30: 
			if(hasLoadedWelcomeScreen())
				return LOGINSTATE.WELCOME_SCREEN;
			
			return LOGINSTATE.LOGGED_IN;
		default:
			return LOGINSTATE.UNKNOWN;	
		}
	}
	
	private static boolean handleLogIn(String username, String password, long sleepOnDisconnect, int attemptNumber) {
		General.sleep(100);
		
		if(attemptNumber > MAX_ATTEMPTS)
			return false;
			
		int attempt = attemptNumber + 1;
		long seconds = sleepOnDisconnect / 1000;
		
		if(Login.getLoginMessage() == null) {
			clickInRectangle(EXISTING_USER_BTN_X, EXISTING_USER_BTN_Y, WIDTH, HEIGHT);
			General.sleep(400, 1400);
			return Timing.waitCondition(() -> Login.getLoginMessage() != null, General.randomLong(3000, 5000))
					&& login(username, password, sleepOnDisconnect);
		}
		
		switch(Login.getLoginMessage()) {
		case ALREADY_LOGGED_IN:
			if(attempt > 2) {
				General.println("ERROR: Account is already logged in, trying one more time in 15 seconds.");
				General.sleep(15000);
			}
			
			clickInRectangle(CANCEL_BTN_X, CANCEL_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case AUTHENTICATOR:
			General.println("ERROR: Authenticator required to login.");
			return false;
			
		case BANNED: 
			if(attempt > 1) {
				General.println("ERROR: Account is banned");
				return false;
			}
			
			clickInRectangle(BACK_BUTTON_X, BACK_BUTTON_Y, HEIGHT, WIDTH);
			break;
			
		case BETA_WORLD:
			General.println("ERROR: This is a beta world.");
			return false;
			
		case CONNECTING:
			//The user has logged out during runtime and is on new/existing user login screen, click existing user button
			clickInRectangle(EXISTING_USER_BTN_X, EXISTING_USER_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case DISCONNECTED:
			clickInRectangle(OK_BUTTON_X, OK_BUTTON_Y, WIDTH, HEIGHT);
			break;
		
		case ENTER:
			return Login.login(username, password) 	? login(username, password, sleepOnDisconnect) 
													: handleLogIn(username, password, sleepOnDisconnect, attempt);
			
		case ERROR_CONNECTING:
			if(attempt > 2) {
				General.println("ERROR: Error connecting, trying one more time in 15 seconds");
				General.sleep(15000);
			}
			
			clickInRectangle(CANCEL_BTN_X, CANCEL_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case INVALID:
			if(attempt > 1) {
				General.println("ERROR: Invalid login details.");
				return false;
			}
			
			clickInRectangle(TRY_AGAIN_BUTTON_X, TRY_AGAIN_BUTTON_Y, WIDTH, HEIGHT);
			break;
			
		case INVALID_SKILL_TOTAL:
			if(attempt > 1) {
				General.println("ERROR: Invalid skill total for world.");
				return false;
			}
			
			clickInRectangle(CANCEL_BTN_X, CANCEL_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case LOCKED:
			if(attempt > 1) {
				General.println("ERROR: Account is locked.");
				return false;
			}
			
			clickInRectangle(BACK_BUTTON_X, BACK_BUTTON_Y, HEIGHT, WIDTH);
			break;
			
		case LOGIN_LIMIT_EXCEEDED:
			if(attempt > 1) {
				General.println("ERROR: Login limit exceeded, waiting " + seconds + " seconds to retry.");
				General.sleep(sleepOnDisconnect);
			}
			
			clickInRectangle(CANCEL_BTN_X, CANCEL_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case MEM_WORLD:
			if(attempt > 1) {
				General.println("ERROR: Members required for this world.");
				return false;
			}
			
			clickInRectangle(CANCEL_BTN_X, CANCEL_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case NEW_USER:
			General.println("ERROR: New user.");
			return false;
			
		case NOT_MEMBER:
			General.println("ERROR: Not member.");
			return false;
			
		case NO_REPLY:
			General.println("ERROR: No reply.");
			return false;
			
		case PVP_WORLD:
			General.println("ERROR: This is a pvp world.");
			return false;
			
		case SERVER_OFFLINE:
			General.println("ERROR: Server offline.");
			return false;
			
		case STANDING_IN_MEMBERS:
			if(attempt > 1) {
				General.println("ERROR: Standing in members");
				return false;
			}
			
			clickInRectangle(CANCEL_BTN_X, CANCEL_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case TIMED_OUT:
			General.println("ERROR: Timed out.");
			return false;
			
		case TOO_MANY_ATTEMPTS:
			if(attempt > 1) {
				General.println("ERROR: Too many attempts, trying again in " + seconds + " seconds.");
				General.sleep(sleepOnDisconnect);
			}
			
			clickInRectangle(EXISTING_USER_BTN_X, EXISTING_USER_BTN_Y, WIDTH, HEIGHT);
			break;
			
		case UPDATED:
			General.println("ERROR: Game updated.");
			return false;
			
		case UPDATE_IN_PROGRESS:
			General.println("ERROR: Update in progress.");
			return false;
			
		case WORLD_FULL:
			if(attempt > 1) {
				General.println("ERROR: Members required for this world.");
				return false;
			}
			
			clickInRectangle(CANCEL_BTN_X, CANCEL_BTN_Y, WIDTH, HEIGHT);
			break;
		
		default:
			General.println("ERROR: Unknown login message");
			return handleLogIn(username, password, sleepOnDisconnect, attempt);
		}
		
		return Timing.waitCondition(() -> Login.getLoginMessage().equals(LOGIN_MESSAGE.ENTER), General.randomLong(3000, 5000))
				&& handleLogIn(username, password, sleepOnDisconnect, attempt);
	}
	
	private static void clickInRectangle(int x, int y, int width, int height) {
		Rectangle rectangle = new Rectangle(x,y,width,height);
		Mouse.clickBox(rectangle, MOUSE_BUTTON);
		General.sleep(400, 1400);
	}
	
	private static void printSuccessfulLogin() {
		String name = GameUtil.hasSetPlayerName() ? GameUtil.getPlayerName() : "New account";
		General.println(name + " logged in successfully.");
	}

}

enum LOGINSTATE {
	UNKNOWN, LOGGED_OUT, WELCOME_SCREEN, LOGGED_IN, CONNECTING
}

 

GameUtil class

Spoiler
package scripts.API.Util;

import java.util.Arrays;
import java.util.Optional;

import org.tribot.api2007.GroundItems;
import org.tribot.api2007.Login;
import org.tribot.api2007.NPCs;
import org.tribot.api2007.Objects;
import org.tribot.api2007.Player;
import org.tribot.api2007.Players;
import org.tribot.api2007.Login.STATE;
import org.tribot.api2007.types.RSGroundItem;
import org.tribot.api2007.types.RSNPC;
import org.tribot.api2007.types.RSObject;
import org.tribot.api2007.types.RSPlayer;

import scripts.Goals.Tutorial.Constants.Constants;

public class GameUtil {
	
	public static boolean worldChangedFrom(int oldWorld) {
		return Game.getCurrentWorld() > 0 && Game.getCurrentWorld() != oldWorld;
	}
	
	public static boolean isGameLoaded() {
		if(!Login.getLoginState().equals(STATE.INGAME))
			return false;
		
		Optional<RSGroundItem> groundItems = Arrays.asList(GroundItems.getAll()).stream().findAny();
		Optional<RSPlayer> players = Arrays.asList(Players.getAll()).stream().findAny();
		Optional<RSNPC> npcs = Arrays.asList(NPCs.getAll()).stream().findAny();
		Optional<RSObject> objects = Arrays.asList(Objects.getAll(10)).stream().findAny();
		
		return groundItems.isPresent() || players.isPresent() || npcs.isPresent() || objects.isPresent();
				
	}
  
  	public static boolean hasSetPlayerName() {
		return Game.getSetting(Constants.TUT_TASK_ID) > 10;
	}
	
	public static String getPlayerName() {
		return Player.getRSPlayer().getName();
	}
}

 

InterfaceUtil class

Spoiler
package scripts.API.Util;

import java.util.Random;

import org.tribot.api.Timing;
import org.tribot.api2007.types.RSInterface;

public class InterfaceUtil {
	
	public static boolean clickAndWait(RSInterface interf, boolean waitUntil, long waitDuration) {
		return 	click(interf) && Timing.waitCondition(() -> waitUntil, waitDuration);
	}
	
	public static void clickRandomTimes(RSInterface interf, int max) {
		int random = new Random().nextInt(max);
		for(int i = 0; i < random ; i++)
			click(interf);
	}
	
	public static boolean click(RSInterface interf) {
		return isOnScreen(interf) && interf.click();
	}
	
	public static boolean areAnyOnScreen(RSInterface... interfs) {
		for(RSInterface interf : interfs) {
			if(isOnScreen(interf))
				return true;
		}
		return false;
	}
	
	public static boolean isOnScreen(RSInterface interf) {
		return interf != null && !interf.isHidden();
	}
	
	public static boolean containsString(RSInterface interf, String string) {
		return isOnScreen(interf) && interf.getText().contains(string);
	}

}

 

 

Edited by NeuroGenix
Updated GameUtil class

Share this post


Link to post
Share on other sites

Very nice, very nice 🙂

It's definitely useful for a lot of people, as it gives you control over what happens, instead of just trying to work around TRiBot's build in methods. Which work well, but offer little in the way of flexibility.

One thing you may want to look at is the positioning of your buttons. If I recall correctly, the buttons can move slightly on resizable vs fixed, so the coordinates your using may be affected? However, the buttons are all pretty big so it's probably not a concern 🙂

Share this post


Link to post
Share on other sites
4 hours ago, Fluffee said:

Very nice, very nice 🙂

It's definitely useful for a lot of people, as it gives you control over what happens, instead of just trying to work around TRiBot's build in methods. Which work well, but offer little in the way of flexibility.

One thing you may want to look at is the positioning of your buttons. If I recall correctly, the buttons can move slightly on resizable vs fixed, so the coordinates your using may be affected? However, the buttons are all pretty big so it's probably not a concern 🙂

I'm happy you think it'll be useful, thanks Fluffee :)

I hadn't even considered fixed/resizable mode, I'll keep it in mind because some of the buttons still need testing. I couldn't get into every situation to see where the buttons where when writing the code, like the locked account screen, I don't have any locked accounts, so I'll update the snippet as/if theres issues :)

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.


  • Our picks

    • To better support the upcoming changes (TRiBot X, new repository), we're switching our login handler to Auth0. Instead of logging in with the standard form, you'll now be required to login through our Auth0 application.

      All existing accounts which have been used within approximately the past year have been imported into Auth0 using the same email and password combination which has been stored on the forums.

      What does this mean for users?

      Your account credentials are now even more securely stored


      You'll be able to login via Facebook, Google, and others in the future


      Is there anything users have to do differently now?

      Existing users: You'll have to login with the standard login, open your Account Settings, then link your Auth0 account


      New users: You'll be redirected to our Auth0 app (auth.tribot.org) where you'll be able to create an account


      Why was this change made?

      The new apps we are creating (such as the new repository) aren't able to use the forums to handle user logins


      To centralize all user accounts in one area


      To ensure that the client login doesn't go down when the forums are having problems


      To speed up our development


      Other considerations

      There's no documentation or official support for using Invision Community combined with Auth0, so there are still a few kinks we're working out


      We're in the works of creating an account management panel specifically for Auth0 accounts (ETA August)


      It's not possible to change email addresses for the time being (this will be resolved this August)


      Changing passwords is a weird process for the time being. To change your password, you'll have to use the "Don't remember your password" tool on the Auth0 login page
        • Like
      • 10 replies
    • Over the past month, we've been working hard on TRiBot's new repository - a much needed update. This change has been deemed necessary for TRiBot X, and will allow us to really speed up development of all aspects of TRiBot.

      Today we are going to share what we've been working on!


      Now you must be wondering what kind of features the new repository will have.... well, you'll have to be patient for a little while longer. We're still figuring out various technical aspects so we can't provide answers to all possible questions. We're also focusing on development rather than writing about it so that everyone can get access to our latest developments at lightning speed. I will however answer a few users' questions.

      We're planning on a release of this early to mid August, giving users some goodies before TRiBot X's release.

      Thank you all for being patient. I hope everyone is excited as much as I am!
        • Like
      • 17 replies
    • Over the past few months, I’ve been working diligently on a new project - TRiBot X. Everything has been written from the ground up, with all of the best practices of software engineering. Every aspect of TRiBot has been re-imagined to support three main goals: flexibility, useability, and reliability.
        • Like
      • 50 replies
    • Come give us feedback on the next version of TRiBot!
        • Thanks
        • Like
      • 86 replies
    • TRiBot is looking to improve a lot of its customer relationship management, customer on boarding process, customer experience, design elements, community engagement and pretty much everything else you can imagine when it comes to marketing.

      Our goal: To ensure that the marketing done TRULY reflects the experience and does not shine an inaccurate light on what TRiBot is lacking in.

      So I ask, what do you love about TRiBot and what do you hate about TRiBot? What does O S Bot, Rune M8, PowR Bot and Dre amBot do better? (yes I purposely didn't spell it right 😂).

      Love, 

      RileyZ
        • Like
      • 26 replies
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...