Jump to content
Existing user? Sign In

Sign In



Sign Up

Flub

Members
  • Posts

    66
  • Joined

  • Last visited

  • Days Won

    13

Everything posted by Flub

  1. This looks terrible - Revived leak from 2018. [Hidden Content]
  2. Flub

    [OSRS] OSPK Release

    This is a revived leak from 2019. Seems to have been lost, so here it is [Hidden Content]
  3. An old one here, but it's still better than most of the themes guys are using these days [Hidden Content]
  4. Hey guys.. Had the need to re-write SlayerTasks.java for someone, figured I'd share it. It includes a kill requirement - if your server doesn't have that, just set the KC requirement to 0 or properly remove it if you know what you're doing package com.arlania.world.content.skill.impl.slayer; import com.arlania.model.Position; import com.arlania.model.Skill; import com.arlania.model.definitions.NpcDefinition; import com.arlania.util.Misc; import com.arlania.world.entity.impl.player.Player; import lombok.Getter; import java.util.ArrayList; import java.util.List; /** * @author Flub * [Hidden Content] */ public enum SlayerTasks { NO_TASK(null, -1, null, -1, null, 0), /** * Easy tasks */ NPC(SlayerMaster.VANNAKA, 1234, "Desc", 2100, new Position(3298, 2799, 0), 0), /** * Medium tasks */ NPC_2(SlayerMaster.DURADEL, 1234, "Desc", 6600, new Position(2724, 9821), 10), /** * Hard tasks */ NPC_3(SlayerMaster.KURADEL, 1234, "Desc", 16000, new Position(1761, 5329, 1), 1000), /** * Elite */ NPC_4(SlayerMaster.SUMONA, 1234, "Desc", 40000, new Position(3226, 2844), 2500), /** * Extreme - Bravek */ NPC_5(SlayerMaster.BRAVEK, 1234, "Desc", 100000, new Position(3176, 3029), 6500); public static List<SlayerTasks> EASY_TASKS = new ArrayList<>(); public static List<SlayerTasks> MEDIUM_TASKS = new ArrayList<>(); public static List<SlayerTasks> HARD_TASKS = new ArrayList<>(); public static List<SlayerTasks> ELITE_TASKS = new ArrayList<>(); public static List<SlayerTasks> EXTREME_TASKS = new ArrayList<>(); @Getter private SlayerMaster taskMaster; @Getter private int npcId; @Getter private String npcLocation; @Getter private int XP; @Getter private Position taskPosition; @Getter private int kcReq; SlayerTasks(SlayerMaster taskMaster, int npcId, String npcLocation, int XP, Position taskPosition, int kcReq) { this.taskMaster = taskMaster; this.npcId = npcId; this.npcLocation = npcLocation; this.XP = XP; this.taskPosition = taskPosition; this.kcReq = kcReq; } public static SlayerTasks forId(int id) { for (SlayerTasks tasks : SlayerTasks.values()) { if (tasks.ordinal() == id) { return tasks; } } return null; } /** * Add into your server start up code. * It fills the sets with up-to-date * task information. */ public static void fillSetsOnStartup() { int counter = 0; for (SlayerTasks task : SlayerTasks.values()) { counter++; if (task.getTaskMaster() == SlayerMaster.VANNAKA) EASY_TASKS.add(task); else if (task.getTaskMaster() == SlayerMaster.DURADEL) MEDIUM_TASKS.add(task); else if (task.getTaskMaster() == SlayerMaster.KURADEL) HARD_TASKS.add(task); else if (task.getTaskMaster() == SlayerMaster.SUMONA) ELITE_TASKS.add(task); else if (task.getTaskMaster() == SlayerMaster.BRAVEK) EXTREME_TASKS.add(task); System.out.println("Successfully added " + counter + " Slayer tasks"); } } private static boolean meetsTaskKC(Player player, SlayerTasks selectedTask) { return selectedTask != null && selectedTask.kcReq <= player.getNpcKillCount(selectedTask.getNpcId()); } private static boolean easyTaskAvailable(Player player) { int easyTasks = EASY_TASKS.size(); for (SlayerTasks easyTask : EASY_TASKS) { if (!meetsTaskKC(player, easyTask)) { easyTasks--; } } return easyTasks >= 1; } private static boolean medTaskAvailable(Player player) { int mediumTasks = MEDIUM_TASKS.size(); for (SlayerTasks mediumTask : MEDIUM_TASKS) { if (!meetsTaskKC(player, mediumTask)) { mediumTasks--; } } return mediumTasks >= 1; } private static boolean hardTaskAvailable(Player player) { int hardTasks = HARD_TASKS.size(); for (SlayerTasks hardTask : HARD_TASKS) { if (!meetsTaskKC(player, hardTask)) { hardTasks--; } } return hardTasks >= 1; } private static boolean eliteTaskAvailable(Player player) { int eliteTasks = ELITE_TASKS.size(); for (SlayerTasks eliteTask : ELITE_TASKS) { if (!meetsTaskKC(player, eliteTask)) { eliteTasks--; } } return eliteTasks >= 1; } private static boolean extremeTaskAvailable(Player player) { int extremeTasks = EXTREME_TASKS.size(); for (SlayerTasks extremeTask : EXTREME_TASKS) { if (!meetsTaskKC(player, extremeTask)) { extremeTasks--; } } return extremeTasks >= 1; } private static boolean repeatTask(Player player, SlayerTasks chosenTask) { return chosenTask != null && chosenTask.npcId == player.getSlayer().getLastTask().getNpcId(); } private static boolean meetsSlayerReq(Player player, SlayerTasks chosenTask) { return chosenTask.npcId > 0 && NpcDefinition.forId(chosenTask.getNpcId()).getSlayerLevel() <= player.getSkillManager().getMaxLevel(Skill.SLAYER); } private static boolean shouldGiveTask(Player player) { boolean giveTask = false; SlayerMaster currentSlayerMaster = player.getSlayer().getSlayerMaster(); switch (currentSlayerMaster) { case VANNAKA: if (easyTaskAvailable(player)) giveTask = true; else player.getPacketSender().sendMessage("No easy tasks available"); break; case DURADEL: if (medTaskAvailable(player)) giveTask = true; else player.getPacketSender().sendMessage("No medium tasks available"); break; case KURADEL: if (hardTaskAvailable(player)) giveTask = true; else player.getPacketSender().sendMessage("No hard tasks available"); break; case SUMONA: if (eliteTaskAvailable(player)) giveTask = true; else player.getPacketSender().sendMessage("No elite tasks available"); break; case BRAVEK: if (extremeTaskAvailable(player)) giveTask = true; else player.getPacketSender().sendMessage("No extreme tasks available"); break; } return giveTask; } public static int amountToKill(Player player) { int amount = Misc.random(15, 30); SlayerMaster currentSlayerMaster = player.getSlayer().getSlayerMaster(); switch (currentSlayerMaster) { case VANNAKA: amount += Misc.random(5, 10); break; case DURADEL: amount += Misc.random(5, 25); break; case KURADEL: amount += Misc.random(5, 60); break; case SUMONA: amount += Misc.random(5, 100); break; case BRAVEK: amount += Misc.random(10, 160); break; } return amount; } public static SlayerTasks getTask(Player player) { SlayerTasks selectedTask = null; SlayerMaster currentSlayerMaster = player.getSlayer().getSlayerMaster(); if (shouldGiveTask(player)) while ((!meetsTaskKC(player, selectedTask) || !meetsSlayerReq(player, selectedTask) || repeatTask(player, selectedTask))) { switch (currentSlayerMaster) { case VANNAKA: selectedTask = (SlayerTasks) Misc.randomFromList(EASY_TASKS); break; case DURADEL: selectedTask = (SlayerTasks) Misc.randomFromList(MEDIUM_TASKS); break; case KURADEL: selectedTask = (SlayerTasks) Misc.randomFromList(HARD_TASKS); break; case SUMONA: selectedTask = (SlayerTasks) Misc.randomFromList(ELITE_TASKS); break; case BRAVEK: selectedTask = (SlayerTasks) Misc.randomFromList(EXTREME_TASKS); break; } System.out.println("SELECTED TASK = " + selectedTask.name()); } return selectedTask; } @Override public String toString() { return Misc.ucFirst(name().toLowerCase().replaceAll("_", " ")); } } Adapted Slayer.java assignTask() Method to use the new data.. This is lazy work since I just changed where it gets the info from public void assignTask() { player.getPacketSender().sendRichPresenceState("Doing Slayer " + duoPartner + "!"); player.getPacketSender().sendSmallImageKey("slayer"); player.getPacketSender().sendRichPresenceSmallPictureText("Lvl: " + player.getSkillManager().getCurrentLevel(Skill.SLAYER)); boolean hasTask = getSlayerTask() != SlayerTasks.NO_TASK && player.getSlayer().getLastTask() != getSlayerTask(); if(hasTask) { player.getPacketSender().sendInterfaceRemoval(); return; } SlayerTasks chosenTask = SlayerTasks.getTask(player); player.getPacketSender().sendInterfaceRemoval(); this.amountToSlay = SlayerTasks.amountToKill(player); this.slayerTask = chosenTask; DialogueManager.start(player, SlayerDialogues.receivedTask(player, getSlayerMaster(), getSlayerTask())); PlayerPanel.refreshPanel(player); }
  5. Flub

    Request

    Lol wrong section This is more for requesting help from a developer.
  6. Glad I could help My fav editor by far
  7. I always forget about this tip. In Client.java, search for: for (int j = 0; j < 5; j++) { if (!parsePacket()) { break; } } Change the 5 to around 35-40. for (int j = 0; j < 35; j++) { if (!parsePacket()) { break; } } Try to login / open an interface before and after - It's a huge difference! Essentially the client was limited to just 5 packets per tick, now it's 35
  8. Hey guys, this tut is for a system I created for the now leaked Platinum PS. It is a boss which is triggered when the server hits a global XP target. It then spawns in an instanced area, but the players can leaver / enter smoothly. Adapt as required, this wasn't ever intended to be a tutorial so it's more involved than others I've done. The rewards are currently XP in the chosen boss skill. Players are ranked based on damage caused to the boss. Positions 1-5 are rewarded. They are then shown a crappy interface, but it does the trick I made a new package in src.com.platinum.world.content.skillingboss Then there are two files: SkillBossConfig: package com.platinum.world.content.skillingboss; import com.platinum.model.Position; public class SkillBossConfig { // NPC ID Of the boss public static final int npcID = 6306; // The amount of time we add to the timer after it runs out public static final long timeDelay = 300000; // 5 minutes // How often will the server update players on the current XP count? public static long xpUpdateTimer = System.currentTimeMillis() + timeDelay; // 5 minutes // The spawn location of the boss public static final Position spawnPos = new Position(1861, 5222, 4); // The value that holds the global XP public static long serverXPCounter; // How much XP requred until the boss will spawn? public static long requiredServerXP = 1000000000; public static void resetTimer() { xpUpdateTimer = System.currentTimeMillis() + timeDelay; } } And SkillBossHandler package com.platinum.world.content.skillingboss; import com.platinum.model.Skill; import com.platinum.util.Misc; import com.platinum.world.World; import com.platinum.world.content.combat.CombatBuilder; import com.platinum.world.content.combat.CombatFactory; import com.platinum.world.content.discord.DiscordMessenger; import com.platinum.world.entity.impl.npc.NPC; import com.platinum.world.entity.impl.player.Player; import java.text.NumberFormat; import java.util.*; public class SkillBossHandler { private static Skill selectedSkill; public static NPC skillBoss = new NPC(SkillBossConfig.npcID, SkillBossConfig.spawnPos);; public static void handleServerXP(long XP) { if (World.getNpcs().contains(skillBoss)) { return; } if (System.currentTimeMillis() > SkillBossConfig.xpUpdateTimer && SkillBossConfig.serverXPCounter < SkillBossConfig.requiredServerXP) { SkillBossConfig.resetTimer(); long remainder = SkillBossConfig.requiredServerXP - SkillBossConfig.serverXPCounter; World.sendMessageDiscord("Global XP is currently: " + formatNumber(SkillBossConfig.serverXPCounter) + "! We need " + formatNumber(remainder) + " until the skilling boss spawns!"); } if (SkillBossConfig.serverXPCounter < SkillBossConfig.requiredServerXP) { SkillBossConfig.serverXPCounter += XP; } else { SkillBossConfig.serverXPCounter = 0; spawnSkillBoss(); } } public static String formatNumber(long number) { return NumberFormat.getInstance().format(number); } /** Spawns the Skilling Boss **/ private static void spawnSkillBoss() { selectedSkill = selectSkill(); World.register(skillBoss); World.sendMessageNonDiscord("@blu@The Skilling Boss has just spawned! Skill Selected: @red@" + selectedSkill.getFormatName() + "@blu@!"); DiscordMessenger.sendInGameMessage("The Skilling Boss has just spawned! Skill Selected: " + selectedSkill.getFormatName() + "!"); } /** Chooses a random Skill **/ private static Skill selectSkill() { return Skill.values()[Misc.exclusiveRandom(Skill.values().length)]; } /** After the NPC is killed, we calculate the damage **/ public static void calculateDamage(NPC npc) { if (npc.getCombatBuilder().getDamageMap().size() == 0) { return; } Map<Player, Integer> killers = new HashMap<>(); for (Map.Entry<Player, CombatBuilder.CombatDamageCache> entry : npc.getCombatBuilder().getDamageMap().entrySet()) { if (entry == null) { continue; } long timeout = entry.getValue().getStopwatch().elapsed(); if (timeout > CombatFactory.DAMAGE_CACHE_TIMEOUT) { continue; } Player player = entry.getKey(); if (player.getConstitution() <= 0 || !player.isRegistered()) { continue; } killers.put(player, entry.getValue().getDamage()); } npc.getCombatBuilder().getDamageMap().clear(); List<Map.Entry<Player, Integer>> result = sortEntries(killers); int count = 0; Player[] topFive = {null, null, null, null, null}; int[] topFiveDmg = {0, 0, 0, 0, 0}; int i = 0; for (Map.Entry<Player, Integer> entry : result) { Player killer = entry.getKey(); int damage = entry.getValue(); if (!Arrays.asList(topFive).equals(killer) && i <= 4) { topFive[i] = killer; topFiveDmg[i] = damage; System.out.println("Added " + killer.getUsername() + " who had dmg " + damage); } else { topFive[i] = null; topFiveDmg[i] = 0; } if (++count >= 20) { break; } i++; } String winners = ""; String fir = ""; String sec = ""; String thi = ""; String fou = ""; String fif = ""; int xpReward = 0; for (int t = 0; t <= 4; t++) { if (topFive[t] != null) { String username = topFive[t].getUsername(); String dmg = " dmg: " + Misc.formatAmount(topFiveDmg[t]); topFive[t].getPacketSender().sendInterface(297); topFive[t].getPacketSender().sendString(299, "@bla@Congratulations " + username + "!") .sendString(6158, selectedSkill.getFormatName() + " XP!") .sendString(303, "") .sendString(304, ""); switch (t) { case 0: fir = "1st: " + username + dmg; xpReward = topFiveDmg[t]; topFive[t].getPacketSender().sendString(301, "@bla@First Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 1: sec = "2nd: " + username + dmg; xpReward = topFiveDmg[t] / 2; topFive[t].getPacketSender().sendString(301, "@bla@Second Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 2: thi = "3rd: " + username + dmg; xpReward = topFiveDmg[t] / 3; topFive[t].getPacketSender().sendString(301, "@bla@Third Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 3: fou = "4th: " + username + dmg; xpReward = topFiveDmg[t] / 4; topFive[t].getPacketSender().sendString(301, "@bla@Fourth Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; case 4: fif = "5th: " + username + dmg; xpReward = topFiveDmg[t] / 5; topFive[t].getPacketSender().sendString(301, "@bla@Fifth Place!") .sendString(4444, "@gre@" + Misc.formatAmount(xpReward)); break; } reward(topFive[t], xpReward, selectedSkill); } winners = fir + sec + thi + fou + fif; } World.sendMessageDiscord("[Skill Boss] " + winners); World.deregister(skillBoss); } private static void reward(Player player, int xpReward, Skill skill) { if (player != null && skill != null) { player.getSkillManager().addExperience(skill, xpReward); player.getPacketSender().sendMessage("You have gained @blu@" + Misc.formatAmount(xpReward) + " @bla@" + selectedSkill.getFormatName() + " XP!"); } } static <K, V extends Comparable<? super V>> List<Map.Entry<K, V>> sortEntries(Map<K, V> map) { List<Map.Entry<K, V>> sortedEntries = new ArrayList<Map.Entry<K, V>>(map.entrySet()); Collections.sort(sortedEntries, new Comparator<Map.Entry<K, V>>() { @Override public int compare(Map.Entry<K, V> e1, Map.Entry<K, V> e2) { return e2.getValue().compareTo(e1.getValue()); } }); return sortedEntries; } } To count the global XP, add this into SkillManager.java (Inside the addExperience method) Ensure you add it after any multipliers / XP reductions so that 2x XP is included. SkillBossHandler.handleServerXP(experience); I used a location for our implementation since it's the cleanest way and keeps things organized (Locations.java) SKILLING_BOSS(new int[] { 1856, 1867 }, new int[] { 5214, 5229 }, true, true, true, false, true, true) { @Override public void logout(Player player) { if (player.getPosition().getZ() == 4) { player.moveTo(player.getPosition().getX(), player.getPosition().getY(), 0); } } @Override public void leave(Player player) { if (player.getPosition().getZ() == 4) { player.moveTo(player.getPosition().getX(), player.getPosition().getY(), 0); } } @Override public void enter(Player player) { if (World.getNpcs().contains(SkillBossHandler.skillBoss)) { player.moveTo(player.getPosition().getX(), player.getPosition().getY(), 4); } } @Override public boolean handleKilledNPC(Player killer, NPC npc) { if (npc == SkillBossHandler.skillBoss) { SkillBossHandler.calculateDamage(SkillBossHandler.skillBoss); return true; } return false; } }, Thanks bois
  9. Hey guys! I'm here with a little tutorial! The RSPS Scene has some notoriously shady characters. It's almost impossible to perm ban people these days because there's always a way to circumvent the standard IP / Mac bans. Well, today you'll learn how to scan a users IP address and retrieve quality metrics such as; If they're using a VPN If they're on the TOR network If they're using a Proxy A 'Fraud Score' (Based on location, previous suspicious behaviour across the internet etc) And plenty more such as their estimated location, ISP and timezone. So, let's get started! First of all, you're going to need an amazing Java Library called Simple JSON <- Download here! Once you've added the Jar to your project libraries, you're ready to start! First of all, let's create a new java class dedicated to our new IP scanner. All changes in this tutorial are done server sided, however it could easily be converted to a client side tool if you wanted to change logon behaviour based on the responses from the scanner. In my example, I created IPVerification.java An ideal location would be: 'src/com/ruse/net/login/' The next step is to head over to IPQualityScore.com and select 'Get a free API key' After you've signed up, find your API key. Example: 'FnT1NcQRfDrhqDn43lb3srxnjOmZj2CC' Now, back to IPVerification.java.. Go ahead and paste in the example from below. I have tried my best to annotate everything! package com.platinum.net.login; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.util.Scanner; import com.platinum.GameSettings; import com.platinum.world.content.discord.DiscordMessenger; import com.platinum.world.entity.impl.player.Player; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; public final class IPVerification { private final static String API_KEY = "key here"; private final static String baseURL = "[Hidden Content]" + API_KEY + "/"; public static void manualIPCheck(Player initiator, Player suspect) { try { //Getting the target IP Address as a string to use in the URL String IP = suspect.getHostAddress(); //The URl that will show the required information. URL url = new URL(baseURL + IP); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //Connecting to the URL conn.setRequestMethod("GET"); //Sending a 'GET' Request to the URL. This is the same thing that happens when you open a webpage on your PC conn.connect(); //Connecting to the session //Getting Response Code int responseCode = conn.getResponseCode(); //Response code 200 means a webpage responded to our GET request successfully. if (responseCode != 200) { throw new RuntimeException("HttpResponseCode: " + responseCode); } else { Scanner sc = new Scanner(url.openStream()); //Scanner is a class which reads the results from a website response StringBuilder inline = new StringBuilder(); //Setting a blank string. We will add the responses to the string to build up our results while(sc.hasNext()) //While there are still responses, we add them to the blank string 'inline' { inline.append(sc.nextLine()); //Adding the response to nextline blank string } //System.out.println(inline); //If you want to see the full result in the console, uncomment this line (Good for debugging) sc.close(); //Closes the connection to prevent mem leaks! JSONParser parse = new JSONParser(); //Starting a new JSONParses session JSONObject obj = (JSONObject) parse.parse(inline.toString()); //Creating a new JSONObject and setting it equal to everything inside 'inline' //Using data from JSON String ip = obj.get("host").toString(); boolean VPN = obj.get("vpn").toString().equals("true"); boolean tor = obj.get("tor").toString().equals("true"); boolean proxy = obj.get("proxy").toString().equals("true"); boolean bot_status = obj.get("bot_status").toString().equals("true"); int fraudScore = Integer.parseInt(obj.get("fraud_score").toString()); String country = obj.get("country_code").toString(); String region = obj.get("region").toString(); String city = obj.get("city").toString(); String isp = obj.get("ISP").toString(); //Adding asterisks either side to make them bold in Discord String susUser = "**" + suspect.getUsername() + "**"; String initUser = "**" + initiator.getUsername() + "**"; //Formatting the results. \n is an expression that creates a new line. Purely for formatting because I have aids level OCD String results = "IP Scan on " + susUser + "\nIP: " + ip + "\nVPN: " + VPN + "\nTor: " + tor + "\nProxy: " + proxy + "\nBot Status: " + bot_status + "\nFraud Score: " + fraudScore + "\nCountry: " + country + "\nRegion: " + region + "\nCity: " + city + "\nISP: " + isp + "\nScan Requested by: " + initUser; System.out.println(results); DiscordMessenger.sendStaffMessage(results); //This is the location that I sent the results to, this should be changed to whatever is most relevant for you! } } catch (IOException | ParseException e) { e.printStackTrace(); } } public static boolean autoIPCheck(Player suspect, String IP) { boolean shouldBlock = false; try { //The URl that will show the required information. URL url = new URL(baseURL + IP); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //Connecting to the URL conn.setRequestMethod("GET"); //Sending a 'GET' Request to the URL. This is the same thing that happens when you open a webpage on your PC conn.connect(); //Connecting to the session //Getting Response Code int responseCode = conn.getResponseCode(); //Response code 200 means a webpage responded to our GET request successfully. if (responseCode != 200) { throw new RuntimeException("HttpResponseCode: " + responseCode); } else { Scanner sc = new Scanner(url.openStream()); //Scanner is a class which reads the results from a website response StringBuilder inline = new StringBuilder(); //Setting a blank string. We will add the responses to the string to build up our results while(sc.hasNext()) {//While there are still responses, we add them to the blank string 'inline' inline.append(sc.nextLine()); //Adding the response to nextline blank string } //System.out.println(inline); //If you want to see the full result in the console, uncomment this line (Good for debugging) sc.close(); //Closes the connection to prevent mem leaks! JSONParser parse = new JSONParser(); //Starting a new JSONParses session JSONObject obj = (JSONObject) parse.parse(inline.toString()); //Creating a new JSONObject and setting it equal to everything inside 'inline' //Using data from JSON String ip = obj.get("host").toString(); boolean VPN = obj.get("vpn").toString().equals("true"); boolean tor = obj.get("tor").toString().equals("true"); boolean proxy = obj.get("proxy").toString().equals("true"); boolean bot_status = obj.get("bot_status").toString().equals("true"); int fraudScore = Integer.parseInt(obj.get("fraud_score").toString()); String country = obj.get("country_code").toString(); String region = obj.get("region").toString(); String city = obj.get("city").toString(); String isp = obj.get("ISP").toString(); //Adding asterisks either side to make them bold in Discord String susUser = "**" + suspect.getUsername() + "**"; //Formatting the results. \n is an expression that creates a new line. Purely for formatting because I have aids level OCD String results = "LOGON BLOCKED FOR " + susUser + "\nIP: " + ip +"\nVPN: " + VPN + "\nTor: " + tor + "\nProxy: " + proxy + "\nBot Status: " + bot_status + "\nFraud Score: " + fraudScore + "\nCountry: " + country + "\nRegion: " + region + "\nCity: " + city + "\nISP: " + isp; if ((VPN || tor || (proxy && fraudScore > 90) || bot_status) && !GameSettings.DEVELOPERSERVER && !suspect.getRights().isSeniorStaff() //Excluding senior staff && !suspect.getRights().isMember()) { //Only sending the info to staff if these prereqs are met DiscordMessenger.sendStaffMessage(results); //This is the location that I sent the results to, this should be changed to whatever is most relevant for you! shouldBlock = true; } } } catch (IOException | ParseException e) { e.printStackTrace(); } return shouldBlock; } } Be sure that the JSONParser and JSONObject methods are imported from the SimpleJson lib 'org.json.simple.*' An example command where you'd use the method.. if (command[0].equals("checkip")) { try { Player target = World.getPlayerByName(wholeCommand.substring(command[0].length() + 1)); assert target != null; IPVerification.manualIPCheck(player, target); } catch (Exception e) { e.printStackTrace(); } } Of course you can use this anywhere, including in your login responses if you wanted to block access to anyone using a VPN! Here's the final result send into Discord. Now, blocking VPN Logins.. Under ConnectionHandler.java you'll find the 'getResponse' method. Add in: if (IPVerification.autoIPCheck(player, host) && !GameSettings.DEVELOPERSERVER){ PlayerPunishment.addBannedIP(host); //Also ban the IP once flagged return LoginResponses.LOGIN_REJECT_VPN; } //Remove the !GameSettings.DEVELOPERSERVER if you don't have that. //The autocheck method ignores local IP addresses anyway. Next, you'll want to repurpose an unused LoginResponse found in 'LoginResponses.java' I used response code 10. Refactor it to match the 'LOGIN_REJECT_VPN' response name featured above! (Ctrl + F6 whilst the old name is highlighted) Finally, in Client.java, search for loginCode == (The number you chose) Then update the message if (loginCode == 10) { //VPN Block loginMessages = new String[] { "VPN or Proxy Dedected!", "You cannot login using either!" }; return; }
  10. Hey guys, Today I'm making a guide on how you can encrypt your player(s) passwords! I made this initially for PlatinumPS (Now leaked) Note: We will be saving the encryption key as plaintext in the server files for this tutorial. This is obviously a terrible idea for most applications, however you can adapt the code to store the key somewhere else if you want to. The purpose of doing this is to stop people who gain unauthorised access to your player files from using the passwords nefariously. First step - Creating Encryptor.java in your server files. I have left an example key as you'll see. Change this! Encryptor.java package com.platinum.tools; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; public class Encryptor { private static SecretKeySpec secretKey; private static byte[] key; public static String globalKey = "uHyowSN7^QmDss!!PP"; <-- CHANGE public static void setKey(String myKey) { MessageDigest sha = null; try { key = myKey.getBytes(StandardCharsets.UTF_8); sha = MessageDigest.getInstance("SHA-1"); key = sha.digest(key); key = Arrays.copyOf(key, 16); secretKey = new SecretKeySpec(key, "AES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } public static String encrypt(String strToEncrypt, String secret) { try { setKey(secret); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8))); } catch (Exception e) { System.out.println("Error while encrypting: " + e); } return null; } public static String decrypt(String strToDecrypt, String secret) { try { setKey(secret); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); cipher.init(Cipher.DECRYPT_MODE, secretKey); return new String(cipher.doFinal(Base64.getDecoder().decode(strToDecrypt))); } catch (Exception e) { System.out.println("Error while decrypting: " + e); } return null; } //This is a test method to prove the concept. /*public static void main(String[] args) { final String secretKey = "my super amazing key"; String originalString = "rspshub.com"; String encryptedString = Encryptor.encrypt(originalString, secretKey) ; String decryptedString = Encryptor.decrypt(encryptedString, secretKey) ; System.out.println(originalString); System.out.println(encryptedString); System.out.println(decryptedString); }*/ } Next - Using the methods So, we want to encrypt a players password, and then upon login, we also want to decrypt it. Go ahead and open PlayerLoading.java and PlayerSaving.java. In your PlayerSaving file, replace your previous password line with: PlayerSaving.java object.addProperty("password", Encryptor.encrypt(player.getPassword().trim(), Encryptor.globalKey)); Now, in your player loading file, replace your previous password loading with this; (If your code didn't have the bottom part, just take the top parts that actually handle the encryption) PlayerLoading.java if (reader.has("password")) { String password = reader.get("password").getAsString(); byte[] passBytes = password.getBytes(); if (passBytes.length >= 16) { //This is included to check if the password is already encrypted. If it's not, it will not try to decrypt, and will handle as plaintext. password = Encryptor.decrypt(password, Encryptor.globalKey); System.out.println("Decryption Success"); } if(!force) { if (!player.getPassword().equals(password)) { return LoginResponses.LOGIN_INVALID_CREDENTIALS; } } player.setPassword(password); } The code above allows you to implement this onto a server without deleting all of the old accounts that don't have an encrypted password. Please note - You can NEVER change the encryption key without decrypting all passwords first! You could edit the method to decrypt with the current, and then re-encrypt with a new key if you really wanted to. If anyone finds out your key, you're a moron. Be safe, respect your players privacy. Before: After: I also made a command that I recommend only for server owners. This allows you to recover a decrypted password from a player, even when offline. if (command[0].equals("getpass")) { String targetName = wholeCommand.substring(command[0].length() + 1); DiscordMessenger.sendStaffMessage("**" + player.getUsername() + " just requested " + targetName + "'s password!**"); File playerFile = new File("data/saves/characters/" + targetName + ".json"); if (!playerFile.exists()) { player.sendMessage("Player file not found!"); return; } try (FileReader fileReader = new FileReader(playerFile)) { JsonParser fileParser = new JsonParser(); JsonObject reader = (JsonObject) fileParser.parse(fileReader); if (reader.has("password")) { String password = reader.get("password").getAsString(); byte[] passBytes = password.getBytes(); if (passBytes.length >= 16) { //This is included so that it can encrypt passwords that are not currently encrypted. password = Encryptor.decrypt(password, Encryptor.globalKey); } player.sendMessage(targetName + "'s pass is: " + password); } } catch (Exception e) { System.out.println("Error getting pass " + e); } }
  11. Thanks Anything to clean up some of the messes I see
  12. Welcome! Today I'll be showing a SUPER simple way to replace the old, outdated and frankly terrible way that most Ruse servers handle launching URLs. First off, go ahead and create a new packet in your PacketSender (May be called PacketHandler). public PacketSender openURL(String url) { return this; } I called mine openURL. (Big brain, I know!) Next, you'll want to head over to your Client Configuration file. Scroll to the bottom, and you'll see a load of seemingly confusing numbers. You can usually find them easily: public static final int[] packetSizes = {... Find one that is currently 0 I have chosen packet 220. Next, do a search in Client.java for: case (*the packet number you selected*): E.g. If you don't find anything, open up your PacketHandler / PacketSender again. Search for the packet number you've selected. Again, hopefully nothing is found.. Great! If you did find that the packet you selected is already in use, select a new number and try again. Once you find the unused number, change the 0 to -1. This allows the packet to accept non specific data. Bare in mind that the first number of each row ends in a 0. E.g... 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //110 ^ Would be 110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //120 ^ Would be 127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 //130 ^ Would be 139 Now, we need to finish the packet code in PacketSender. public PacketSender openURL(String url) { PacketBuilder out = new PacketBuilder(220, PacketType.BYTE); // The Packet And Output Type out.putString(url); //Generating a string to send to the client player.getSession().queueMessage(out); //Send the packet to the client return this; } That's the packet done! You'll be able to use this anywhere. E.g: String url = "[Hidden Content]" player.getPacketSender().openURL(url); Now, head back to your Client.java file and do another search. This time, we're searching for: switch (opcode) This is where your client handles the information that it receives from packets. We'll need to make a new case for the packet number that you selected (As shown in the image above). Now, here is the code annotated: case 220://OPENING URLS //Assigning the received string to a new string called url String url = inStream.readString(); //This code uses the native java.awt.Desktop library. if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { System.out.println("URL: " + url); Desktop.getDesktop().browse(new URI(url)); } //Setting to match the change we made to the packet in configuration.java opCode = -1; return true; //Returns true once handled That's it! You should be good to go. I would suggest wrapping the above code in a try / catch block in case you pass a non-valid URL. Here is an example command that utilises this new ability.. if (command[0].equals("google")) { String query = (wholeCommand.substring(command[0].length() + 1)).replace(" ", "%20"); player.getPacketSender().openURL("[Hidden Content]=" + query); } You should update any existing command such as ::donate or ::store so that they open using the native way! Done
  13. Hey guys, commands below.. adapt as required for other sites! if (command[0].equals("google")) { String query = (wholeCommand.substring(command[0].length() + 1)).replace(" ", "%20"); player.getPacketSender().openURL("[Hidden Content]=" + query); } if (command[0].equals("youtube")) { String query = (wholeCommand.substring(command[0].length() + 1)).replace(" ", "%20"); player.getPacketSender().openURL("[Hidden Content]=" + query); } If you'd like the same openURL method, checkout my other tut:
  14. Hi guys, Here is a command I created to discover what NPC's drop an item. Main code (I put mine inside ItemDefinition so that I can use ItemDefinition.whatDrops(player, name))``` public static void whatDrops(Player player, String name) { int itemID = getItemId(name); if (itemID == -1) { player.getPacketSender().sendMessage("Item not found!"); return; } ItemDefinition itemDef = ItemDefinition.forId(itemID); List<Integer> previouslyListed = new ArrayList<>(); try { for (NPCDrops npcDrops : NPCDrops.getDrops().values()) { if (npcDrops != null) { for (NPCDrops.NpcDropItem item : npcDrops.getDropList()) { if (item != null && item.getId() == itemID) { for (int npcId : npcDrops.getNpcIds()) { if (npcId == -1) return; NpcDefinition npcDef = NpcDefinition.forId(npcId); if (npcDef != null && !npcDef.getName().equalsIgnoreCase("null") && !previouslyListed.contains(npcId)) { previouslyListed.add(npcId); player.getPacketSender().sendMessage(itemDef.getName() + " are dropped by " + npcDef.getName() + "! Noted: " + (itemDef.isNoted() ? "True" : "False")); break; } } } } } } } catch (Exception ignored) { } if (previouslyListed.isEmpty()) { player.getPacketSender().sendMessage("Unable to find an NPC that drops: " + itemDef.getName()); } previouslyListed.clear(); } Command code: if (command[0].equals("whatdrops")) { String item = wholeCommand.substring(command[0].length() + 1); player.getPacketSender().sendMessage("Searching for " + item); ItemDefinition.whatDrops(player, item); } Usage: ::whatdrops Rune Platebody
  15. Hey everyone. I bet all of you have come across the need to select a random item from a group before. You'll see this in many areas of your server. Most prominently in your mystery / donator box files, raid rewards and crystal chest too! An example of an item group is: Item[] items = {new Item(113, 1) , newI Item(333,4)}; Now, we have a group that includes two items. The most common way of selecting a random reward (You'll see this EVERYWHERE) is; Item reward = (items[Misc.getRandom(items.length - 1)], 1); This will work. However, it's ugly! There are always ways to improve. Here is a new method for you.. I've added mine into Misc.java. public static Item randomItem(final Item[] collection) { return collection[random(collection.length - 1)]; } Now, lets select a random item from our group using this new method! (If added in Misc.java) Item reward = Misc.randomItem(Items); How much cleaner is that! You can then use the item however you want. E.g. player.getInventory().add(item); Thank you!
  16. Hey everyone. This is a better way to select a random entry from an enum An example of an enum group is: @AllArgsConstructor public enum SlayerTasks { DARKWIZARDS(SlayerMaster.SUMONA, 9203, "Find Darkblue Wizards at ::wizards", 1500, new Position(2903, 5203)), HEATED_PYRO(SlayerMaster.SUMONA, 172, "Heated Pyro can be found in the Elite Teleports", 1500, new Position(2863, 5354, 2)), PURPLE_WYRM(SlayerMaster.SUMONA, 9935, "Purple Wyrm can be found in the Elite Teleports", 1500, new Position(2602, 5713)), TRINITY(SlayerMaster.SUMONA, 170, "Trinity can be found in the Elite Teleports", 1500, new Position(2273, 4680, 1)), CLOUD(SlayerMaster.SUMONA, 169, "Cloud can be found in the Elite Teleports", 1500, new Position(1908, 4367)); private SlayerMaster taskMaster; private int npcId; private String npcLocation; private int XP; private Position taskPosition; } Enums are incredibly useful for storing multiple types of data. You'll see them used in a load of places! Now, the usual way to select a random entry from your enum list would be; SlayerTasks task = SlayerTasks.values()[Misc.random(SlayerTasks.values().length - 1)]; Of course - this does work. However, why not improve it! Here is a new method for you.. I've added mine into Misc.java along with my randomItem method! public static <T extends Enum<?>> T randomEnum(Class<T> clazz){ SecureRandom random = new SecureRandom(); int x = random.nextInt(clazz.getEnumConstants().length); return clazz.getEnumConstants()[x]; } Now, lets select a entry from our enum using this new method! (If added in Misc.java) SlayerTasks task = Misc.randomEnum(SlayerTasks.class); How much cleaner is that! You **must** add .class to the end of the name in this bracket. You can then use the entry as required! E.g. SlayerMaster master = task.taskMaster; int npcId = task.npcId; String npcLocation = task.npcLocation; int XP = task.XP; Position taskPosition = task.taskPosition; Hopefully you can use this to clean up some code 😛
  17. Always been my favourite cache editor.. If you have a PC with a tiny amount of RAM, it may struggle to open index1 on custom servers.. [Hidden Content]
  18. [Hidden Content] Features: Cache/Texture Loading for all/most 317 caches(tested like 5 or 6 different ones with no issues) Texture viewing(the image itself, data about it) Texture Adding Texture Replacing Texture Dumping Texture removing(gotta fix a small issue) Drag / Drop for loading the cache/textures Drag / Drop for adding new textures Mass packing works with both, so you can pack 100 textures @ once if you wish to. Checks that'll ensure that the textures archive won't corrupt(for example adding a texture with more than 255 unique colors)

Contact

[email protected]

astra.security

What is a RSPS?

A RSPS, also known as RuneScape private server, is an online game based on RuneScape, and controlled by independent individuals.

Popular RSPS Servers

Runewild Ikov RedemptionRSPS

Disclaimer

Runesuite is not affiliated with runescape, jagex in any way & exists solely for educational purposes.

×
×
  • Create New...