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

    • 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.
      • 30 replies
    • Come give us feedback on the next version of TRiBot!
      • 74 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
      • 23 replies
    • Over the last three weeks, I've been working on upgrading our server infrastructure. It's finally ready and is now live!

      Why?

      Increased reliability - less server errors


      Increased availability - less downtime


      Increased security - keeping us and you secure


      Increased capacity - ability to serve you better


      Increased speed - less waiting for things to load


      Faster development - server and service updates will come faster


      What are the changes?

      Move from a single AWS EC2 instance to AWS ECS (Elastic Container Service)


      Distributed computing


      Load balancing


      Git management of server files and filesystem


      Redis caching


      How?

      AWS ECS (with 10 EC2 instances)


      AWS ElastiCache (Redis)


      AWS Load Balancing


      AWS EFS (Elastic file system)


      Please bare with us as I continue to tune the server for maximum performance. Slow loading speeds may occur temporarily. I thank everyone for their patience.

      Please post on this thread if you experience any issues other than slow loading times.
      • 51 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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...