The reason why I made this was purely for learning purposes.
However, I still think it would be decent to have something like this. If you are interested in how this works before adding it to your server, the dialogue contains some information.
Info: You will maybe wonder why I did not use a runscript for emails.... Well, most emails are most likely long and the runscript does not have enough space for that. So I have found my own solution.
Note: Yes I am aware I am counting this down with process entity so the times are not that accurate but whatever.
Another note: Our sources may be different. You might have to edit some stuff yourself. Post a help thread for this.
Optional part:
IP2 - Grabs country name & (Optional) country code by the IP
Place ip-to-country.bin in your project folder and place the .jar in your libs folder
[SPOIL]
Code:
public static String getCountryName(String IP, boolean CountryCode) {
String Country = null;
try {
int cache = IP2Country.MEMORY_CACHE;
IP2Country ip2 = new IP2Country(cache);
Country country = ip2.getCountry(IP);
Country = (country == null ? "UNKNOWN" : country.getName() + (CountryCode ? " | " + country.get2cStr() : ""));
} catch (IOException e) {
e.printStackTrace();
}
return Country;
}
[/SPOIL]
Click here to download IP2
If you do not decide to use this, comment out or simply remove the places where it is needed.
First off, create two classes. (com/rs/game/player) and (com/rs/game/player/dialogues)
[SPOIL]
Code:
package com.rs.game.player;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.rs.utils.Utils;
/**
*
* @Author Tristam <Hassan>
* @Project - 1. Rain
* @Date - 26 Mar 2016
*
**/
public class SecurityManager implements Serializable {
private static final long serialVersionUID = -1394761641357936615L;
private transient Player player;
public String LoginCode, lastChanged, LastSignedIn, Birthday;
public long TrustedIPTime, RequestedRemoveTime, RequestedChangeTime;
public boolean TypingEmail;
private final Pattern VALID_EMAIL_ADDRESS_REGEX = Pattern.compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$",
Pattern.CASE_INSENSITIVE);
private List<String> Email;
private List<String> IPS;
private List<String> TrustedIPS;
public void setPlayer(Player player) {
this.player = player;
}
public SecurityManager() {
TrustedIPS = new ArrayList<String>();
Email = new ArrayList<String>();
IPS = new ArrayList<String>();
}
public List<String> getEmail() {
return Email;
}
public List<String> getRegisteredIPS() {
return IPS;
}
public List<String> getTrustedIPS() {
return TrustedIPS;
}
public boolean AddEmail(String email) {
email = email.toLowerCase();
if (email == null) {
return false;
}
if (getEmail().contains(email)) {
player.sm("This e-mail already exists.");
return false;
}
if (email.equalsIgnoreCase("exit") || email.equalsIgnoreCase("close")) {
player.getInterfaceManager().sendTabInterfaces(false);
player.unlock();
Email(false);
return false;
}
if (!CheckEmailRequirement(email)) {
player.sm("Your email is missing something.");
return false;
}
Email(false);
player.getInterfaceManager().sendTabInterfaces(false);
player.unlock();
Email.add(email);
player.sm("The e-mail " + email + " has successfully been added to your account.");
return true;
}
public void TrustIP(String IP) {
if (getTrustedIPS().contains(IP)) {
player.getDialogueManager().startDialogue("SimpleMessage",
"The Trusted IP: " + IP + ", is already stored in your account.");
return;
}
getTrustedIPS().add(IP);
}
public void addRegisteredIP(String IP) {
if (getRegisteredIPS().contains(IP)) {
return;
}
getRegisteredIPS().add(IP);
}
public void check() {
if (LoginCode != null) {
if (TrustedIPS.contains(player.getSession().getIP()))
return;
player.lock();
player.getPackets().sendRunScript(109, "Please enter your Login Code to procceed:");
player.temporaryAttribute().put("enterlogincode", true);
player.getInterfaceManager().sendTabInterfaces(true);
}
}
public void displayRegisteredEmails() {
if (Email.size() < 1) {
player.sm("There are no emails linked to your account.");
return;
}
player.getInterfaceManager().sendInterface(275);
for (int i = 0; i < 100; i++)
player.getPackets().sendIComponentText(275, i, "");
player.getPackets().sendIComponentText(275, 1, "Registered email(s)");
for (int i = 0; i < Email.size(); i++) {
player.getPackets().sendIComponentText(275, 10 + i, Email.get(i));
}
UpdateLastChanged();
}
public void displayRegisteredIPS() {
player.getInterfaceManager().sendInterface(275);
for (int i = 0; i < 100; i++)
player.getPackets().sendIComponentText(275, i, "");
player.getPackets().sendIComponentText(275, 1, "Registered IP(s)");
for (int i = 0; i < IPS.size(); i++) {
player.getPackets().sendIComponentText(275, 10 + i,
IPS.get(i) + " - " + Utils.getCountryName(IPS.get(i), true));
}
UpdateLastChanged();
}
public void UpdateLastChanged() {
lastChanged = currentTime("dd MMMMM yyyy 'at' hh:mm:ss z");
}
public void UpdateLastSignedIn() {
addRegisteredIP(player.getSession().getIP());
player.sm("You last logged in " + (LastSignedIn != null ? LastSignedIn : ""));
LastSignedIn = currentTime("dd MMMM yyyy 'at' hh:mm:ss z'.'");
}
public String currentTime(String dateFormat) {
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
return sdf.format(cal.getTime());
}
public long getTimer(int type) {
if (type == 1) {
return TrustedIPTime;
} else if (type == 2) {
return RequestedRemoveTime;
} else if (type == 3) {
return RequestedChangeTime;
} else {
return -1;
}
}
public long setTimer(int type, long time) {
if (type == 1) {
return TrustedIPTime = time;
} else if (type == 2) {
return RequestedRemoveTime = time;
} else if (type == 3) {
return RequestedChangeTime = time;
} else {
return -1;
}
}
public boolean Email(boolean value) {
return TypingEmail = value;
}
public boolean isTyping() {
return TypingEmail;
}
public boolean CheckEmailRequirement(String email) {
Matcher matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(email);
return matcher.find();
}
}
[/SPOIL]
and the dialogue
[SPOIL]
Code:
package com.rs.game.player.dialogues;
public class AccountMan extends Dialogue {
/**
*
* @Author Tristam <Hassan>
* @Project - 1. Rain
* @Date - 26 Mar 2016
*
**/
int npc;
@Override
public void start() {
npc = (Integer) parameters[0];
sendNPCDialogue(npc, Normal,
"Hey! Are you here to access your security settings? "
+ (player.getSecurityManager().lastChanged == null ? ""
: "They were last changed on " + player.getSecurityManager().lastChanged));
stage = 1;
}
@Override
public void run(int interfaceId, int componentId) {
switch (stage) {
case END:
end();
break;
case 1:
sendOptions(TITLE, "'Authenticator'", "Birthday", "Email", "Overview of all IPS logged in to your account",
"Important notice");
stage = 2;
break;
case 2:
switch (componentId) {
case OPTION_1:
if (player.getSecurityManager().LoginCode != null) {
sendOptions(TITLE, "Disable 'Authenticator'", "What is this?",
"How would I benefit by enabling this?", "Request change (3 Days)",
"Trust <col=ff000>" + player.getSession().getIP() + "</col> for 1 month.");
} else {
sendOptions(TITLE, "Enable 'Authenticator'", "What is this?",
"How would I benefit by enabling this?");
}
stage = 3;
break;
case OPTION_2:
sendOptions(TITLE, (player.getSecurityManager().Birthday != null ? "Change birthday" : "Set birthday"),
"Why should I set this?");
stage = 4;
break;
case OPTION_3:
sendOptions(TITLE, "Set e-mail", "Why should I set this?", "View list of all registered email(s)");
stage = 7;
break;
case OPTION_4:
sendOptions(TITLE, "Check the overview", "What is this for?");
stage = 5;
break;
case OPTION_5:
sendNPCDialogue(npc, Happy, "We would never ever share your information with anyone else.");
stage = END;
break;
}
break;
case 3:
switch (componentId) {
case OPTION_1:
if (player.getSecurityManager().getTimer(2) > 1) {
sendDialogue(
"Someone has recently requested to remove the 'Authenticator'. If this was not you, change your password and contact an Admin.");
stage = END;
} else if (player.getSecurityManager().LoginCode != null) {
player.getSecurityManager().setTimer(2, 604800);
sendDialogue("You have requested to disable 'Authenticator'. The process will take 7 days.");
stage = END;
} else {
player.getPackets().sendRunScript(109,
"Please enter your login code, it can be anything. Do not forget this!:");
player.temporaryAttribute().put("setlogincode", true);
end();
}
player.getSecurityManager().UpdateLastChanged();
break;
case OPTION_2:
sendNPCDialogue(npc, Plain, "This is a system similiar to the 'Authenticator'.");
stage = END;
break;
case OPTION_3:
sendNPCDialogue(npc, Happy,
"I'm glad you asked! The purpose of this is to keep your account secure. The way it will keep your account secure is by, everytime you login you will not be able to do anything until you enter the so called 'Login Code'. You can also trust IPS for 1 month.");
stage = END;
break;
case OPTION_4:
if (player.getSecurityManager().getTimer(3) > 1) {
sendDialogue(
"Someone has recently requested a change. If this was not you, please change your password and contact server support.");
} else {
sendDialogue("You have successfully requested change. You can come back in 3 days to do so.");
player.getSecurityManager().setTimer(3, 259200);
}
player.getSecurityManager().UpdateLastChanged();
stage = END;
break;
case OPTION_5:
sendOptions(TITLE, "Trust this IP for one month?", "Actually no.");
stage = 6;
break;
}
break;
case 4:
switch (componentId) {
case OPTION_1:
player.getPackets().sendInputIntegerScript(true, "Enter your birthday (DD:MM:YYYY) - Example: 21 06 16:");
player.temporaryAttribute().put("setbirthday", true);
break;
case OPTION_2:
sendNPCDialogue(npc, Happy,
"You should always set a Birthday date & E-mail on your account so it would be easier to recover when requesting for it. <br>Remember: Never give either of them out to anyone.");
stage = END;
break;
}
break;
case 5:
switch (componentId) {
case OPTION_1:
player.getSecurityManager().displayRegisteredIPS();
end();
break;
case OPTION_2:
sendNPCDialogue(npc, Plain,
"Incase you thought you were hijacked or something, you can make sure you are not by checking if the IP(s) matches yours.");
stage = END;
break;
}
break;
case 6:
switch (componentId) {
case OPTION_1:
sendDialogue(
"You have successfully added this IP to the Trust List for this account. This means, you no longer have to (While using this device) enter the Login Code for one month. However, if a unrecognized device logs in, they have to.");
player.getSecurityManager().TrustIP(player.getSession().getIP());
player.getSecurityManager().setTimer(1, 2592000);
stage = END;
break;
case OPTION_2:
end();
break;
}
player.getSecurityManager().UpdateLastChanged();
break;
case 7:
switch (componentId) {
case OPTION_1:
player.getSecurityManager().Email(true);
player.sm("<col=ff0000>Type in your e-mail in the chatbox. It won't appear to anyone else. You can type exit to end.");
player.lock();
player.getInterfaceManager().sendTabInterfaces(true);
end();
break;
case OPTION_2:
sendNPCDialogue(npc, Happy,
"You should always set this, so if you happen to get hijacked you could always recover it easy by giving us these details.");
stage = END;
break;
case OPTION_3:
player.getSecurityManager().displayRegisteredEmails();
end();
break;
}
break;
}
}
@Override
public void finish() {
}
}
[/SPOIL]
Next up, go to the Player.java class and declare this
[SPOIL]
Code:
private SecurityManager securityManager;
public SecurityManager getSecurityManager() {
return securityManager;
}
[/SPOIL]
then, place these at the correct methods
Make sure you place them in the right place.
[SPOIL]
Code:
if (securityManager == null)
securityManager = new SecurityManager();
securityManager = new SecurityManager();
securityManager.setPlayer(this);
[/SPOIL]
Next up, in your public void run() { method (player.java still)
place this at the very bottom
Code:
getSecurityManager().check();
Then find your welcome server message and place this below it
Code:
getSecurityManager().UpdateLastSignedIn();
Next up, find "processentity()" and place this under processLogicPackets();
[SPOIL]
Code:
if (getSecurityManager().getTimer(1) > 0) {
if (getSecurityManager().getTimer(1) == 1) {
getSecurityManager().getTrustedIPS().clear();
}
getSecurityManager().TrustedIPTime--;
}
if (getSecurityManager().getTimer(2) > 0) {
if (getSecurityManager().getTimer(2) == 1) {
getSecurityManager().LoginCode = null;
getSecurityManager().getTrustedIPS().clear();
sm("Your request regarding the removal of 'Authenticator' has successfully been completed.");
getSecurityManager().RequestedChangeTime = 0;
}
getSecurityManager().RequestedRemoveTime--;
}
if (getSecurityManager().getTimer(3) > 0) {
if (getSecurityManager().getTimer(3) == 1) {
getSecurityManager().LoginCode = null;
sm("Your request regarding the change Login Code has successfully been completed. You can change it now.");
getSecurityManager().RequestedRemoveTime = 0;
}
getSecurityManager().RequestedChangeTime--;
}
[/SPOIL]
Now we got all that done. Find Worldpacketsdecoder.java and then find the CHAT_PACKET
Under
[SPOIL]
Code:
if (colorEffect > 11 || moveEffect > 11) { return;
}
if (message == null || message.replaceAll(" ", "").equals(""))
return;
}
[/SPOIL]
place
[SPOIL]
Code:
if (player.getSecurityManager().isTyping()) {
player.getSecurityManager().AddEmail(message);
return;
}
[/SPOIL]
Under the ENTER_STRING packet
[SPOIL]
Code:
} else if (player.temporaryAttribute().get("setbirthday") == Boolean.TRUE) { player.getSecurityManager().Birthday = value;
player.getDialogueManager().startDialogue("SimpleMessage",
"Thanks! You set your birthday to: " + player.getSecurityManager().Birthday + ".");
player.getSecurityManager().UpdateLastChanged();
player.temporaryAttribute().put("setbirthday", false);
} else if (player.temporaryAttribute().get("enterlogincode") == Boolean.TRUE) {
if (player.getSecurityManager().LoginCode.equalsIgnoreCase(value)) {
player.getInterfaceManager().sendTabInterfaces(false);
player.unlock();
player.getDialogueManager().startDialogue("SimpleMessage",
"The login code was correct! You can now continue playing Rain.");
} else {
Dialogue.sendNPCDialogueNoContinue(player, 1512, 9760,
"Oh no, the code was incorrect! Try again. You will be disconnected in " + "5...");
WorldTasksManager.schedule(new WorldTask() {
int disconnect = 5;
@Override
public void run() {
if (disconnect == 0) {
player.unlock();
player.getSession().getChannel().disconnect();
}
disconnect--;
Dialogue.sendNPCDialogueNoContinue(player, 1512, 9760,
"Oh no, the code was incorrect! Try again. You will be disconnected in "
+ disconnect + "...");
}
}, 0, 1);
}
player.temporaryAttribute().put("enterlogincode", false);
} else if (player.temporaryAttribute().get("setlogincode") == Boolean.TRUE) {
player.getSecurityManager().LoginCode = value;
player.getDialogueManager().startDialogue("SimpleMessage",
"Your login code has been set to " + player.getSecurityManager().LoginCode
+ ". <br>Please, screenshot this or write it down so you can remember it.");
player.temporaryAttribute().put("setlogincode", false);
player.getSecurityManager().UpdateLastChanged();
player.temporaryAttribute().put("setlogincode", false);
[/SPOIL]
I am not responsible if you mess this up. I gave instructions and if you followed the correctly, everything should be fine.