/** @author Lazaro */ public class NPCXMLDefinition { private static final Logger logger = Logging.log(); private static Map<Integer, NPCXMLDefinition> xmlDefinitions = null; public static void load() throws IOException { xmlDefinitions = Static.xml.readObject(Static.parseString("%WORK_DIR%/npcdefs.xml")); logger.info("Loaded " + xmlDefinitions.size() + " XML NPC definitions"); } public static Map<Integer, NPCXMLDefinition> getXMLDefinitions() { return xmlDefinitions; } public int hp = -1; public String examine = "Nothing interesting."; public boolean aggressive = false; public int attackSpeed = 5; public int attackEmote = -1; public int defenceEmote = -1; public int deathEmote = -1; public int meleeMaxHit = 10; public int rangedMaxHit = 10; public int magicMaxHit = 10; public String loopScript = null; public String dialogueScript = null; public double[] bonuses = null; public int[] levels = null; public boolean poisonous = false; public static enum AttackType { MELEE(true, false, false), MELEE_MAGIC(true, true, false), MELEE_RANGE(true, false, true), MELEE_MAGIC_RANGE(true, true, true), MAGIC(false, true, false), MAGIC_RANGE(false, true, true), RANGE(false, false, true); public boolean usesMelee; public boolean usesMagic; public boolean usesRanged; private AttackType(boolean melee, boolean magic, boolean ranged) { this.usesMelee = melee; this.usesMagic = magic; this.usesRanged = ranged; } } public static enum MeleeStyle { SLASH, CRUSH, STAB } protected AttackType attackType = null; protected MeleeStyle meleeStyle = null; protected int aggressiveRange = 0; protected boolean uniqueBehaviour = false; protected String behaviourScript = null; protected boolean attackable = false; }
public class NPCCombatHandlerTick extends Tick { @SuppressWarnings("unused") private static final Logger LOGGER = Logging.log(); private Combat combat; public NPCCombatHandlerTick(Combat combat) { super("CombatTick", 1, TickPolicy.PERSISTENT); this.combat = combat; } @Override public boolean execute() { try { CombatAction ca = combat.scheduledAction; if (ca != null) { if (ca.victim instanceof Player) if (((Player) ca.victim).isDestroyed()) { return false; } if (ca.victim != null && !ca.victim.isDead() && ca.victim.inGame() && ca.attacker != null && !ca.attacker.isDead() && ca.attacker.inGame()) { NPC npc = (NPC) ca.attacker; npc.setMovementType(MovementType.CONTROLLED); boolean correctPosition; if (!(correctPosition = CombatUtilities.inCorrectPosition(ca.attacker, ca.victim, ca.type))) { if (!combat.isFrozen()) CombatUtilities.moveToCorrectPosition(ca.attacker, ca.victim, ca.type, true); correctPosition = CombatUtilities.inCorrectFollowPosition(ca.attacker, ca.victim, ca.type); } combat.attackFromInitiateDistance = !correctPosition; if (correctPosition) { if (combat.canAttack(ca.victim)) { if (combat.isReadyToAttack(ca.attackDelay, ca.spellDelay, ca.type)) { if (correctPosition) { ca.attacker.getPathProcessor().reset(); } boolean succesful = ca.executeAction(); if (succesful) { switch (ca.type) { case MAGIC: combat.setNextSpellTime(ca.spellDelay); break; case MELEE: case RANGED: combat.setNextSpellTime(4); break; } combat.appendAttackTime(); ca.victim.getCombat().appendDefenceTime(); combat.setNextAttackTime(ca.attackDelay); combat.lastVictim = ca.victim; ca.victim.getCombat().setLastAttacker(ca.attacker); return true; } else { combat.stop(false); return false; } } else { return true; } } else { combat.stop(true); return false; } } else { if (npc.getDefinition().aggressiveRange > npc.getLocation().distance(ca.victim.getLocation()) || !npc.getLocation().withinRange(npc.getSpawn().location, npc.getSpawn().range)) { combat.stop(true); return false; } return true; } } else { combat.stop(true); return false; } } else { combat.stop(true); return false; } } catch (Exception e) { e.printStackTrace(); combat.stop(true); return false; } } }
/** @author Lazaro */ public class DatabaseLoaderAdapter implements DatabaseLoader { private static final Logger logger = Logging.log(); @Override public void banIP(String ip) {} @Override public boolean isBanned(String userName) { return false; } @Override public boolean isIPBanned(String ip) { return false; } @Override public LoginResponse loadPlayer(String userName, String password, PlayerSave player) { userName = Text.formatNameForProtocol(userName); Pool<SQLSession> pool = Static.currentLink().getSQLPool(); SQLSession sql = null; try { sql = pool.acquire(); Statement st = sql.createStatement(); ResultSet rs = st.executeQuery( "SELECT * FROM prothieu_members WHERE " + "members_seo_name='" + userName.replace("_", "-") + "' LIMIT 1"); if (!rs.next()) { return LoginResponse.INVALID_DETAILS; } if (password != null) { String passwordHash = rs.getString("members_pass_hash"); String passwordSalt = rs.getString("members_pass_salt"); if (!verifyPassword(password, passwordHash, passwordSalt)) { return LoginResponse.INVALID_DETAILS; } } int userId = rs.getInt("member_id"); player.userId = userId; int[] userGroups = new int[1]; userGroups[0] = rs.getInt("member_group_id"); if (userGroups[0] == 5 || userGroups[0] == 1 || userGroups[0] == 2) { return LoginResponse.BANNED; } if (userGroups[0] == 1 || userGroups[0] == 2) { return LoginResponse.ERROR; } applyGroupData(player, userGroups); player.email = rs.getString("email"); if (player.email != null && player.email.length() == 0) { player.email = null; } player.unreadMessages = rs.getInt("msg_count_new"); rs.close(); player.subscriptionEnd = 0; rs = st.executeQuery( "SELECT * FROM subscription_trans WHERE subtrans_member_id='" + userId + "'"); while (rs.next()) { String state = rs.getString("subtrans_state"); if (state.equalsIgnoreCase("paid") || state.equalsIgnoreCase("canceled")) { long end = rs.getLong("subtrans_end_date") * 1000; if (end > player.subscriptionEnd) { player.subscriptionEnd = end; } } } rs.close(); // if(player.rights == 0 && player.subscriptionEnd < System.currentTimeMillis()) { // return LoginResponse.MEMBERS_REQUIRED; // } for (int attempt = 0; attempt < 2; attempt++) { rs = st.executeQuery("SELECT * FROM playersave WHERE id='" + userId + "' LIMIT 1"); if (!rs.next()) { rs.close(); st.executeUpdate( "INSERT INTO playersave (id, name) VALUES ('" + userId + "', '" + userName + "')"); continue; } else { attempt++; } player.lastLoggedIn = rs.getLong("lastLoggedIn"); player.lastIPs = toArray(rs.getString("lastIPs"), new String[3]); player.isMuted = rs.getInt("muted") == 1; player.x = rs.getInt("x"); player.y = rs.getInt("y"); player.z = rs.getInt("z"); player.runToggled = rs.getBoolean("runToggled"); player.runEnergy = rs.getInt("runEnergy"); player.inv = primitive(toArray(rs.getString("inv"), new Short[28])); player.invN = primitive(toArray(rs.getString("invN"), new Integer[28])); player.equip = primitive(toArray(rs.getString("equip"), new Short[14])); player.equipN = primitive(toArray(rs.getString("equipN"), new Integer[14])); String bankS = rs.getString("bank"); if (bankS == null) { player.bank = new int[0][3]; } else { short[] bank = primitive(toArray(bankS, new Short[0])); int[] bankN = primitive(toArray(rs.getString("bankN"), new Integer[0])); byte[] bankT = primitive(toArray(rs.getString("bankT"), new Byte[0])); player.bank = new int[bank.length][3]; for (int i = 0; i < bank.length; i++) { int[] entry = player.bank[i]; entry[0] = bank[i]; entry[1] = bankN[i]; entry[2] = bankT[i]; } } player.level = primitive(toArray(rs.getString("level"), new Byte[Levels.SKILL_COUNT])); player.exp = primitive(toArray(rs.getString("exp"), new Double[Levels.SKILL_COUNT])); player.xpCounter = rs.getInt("xpCounter"); player.autoRetaliate = rs.getInt("autoRetaliate") == 1; player.attackStyle = rs.getInt("attackStyle"); player.prayerBook = rs.getInt("prayerBook") == 1; String quickPrayers = rs.getString("quickPrayers"); if (quickPrayers.length() == 0) quickPrayers = player.prayerBook ? "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0" : "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0"; player.quickPrayers = primitive(toArray(quickPrayers, new Byte[player.prayerBook ? 20 : 30])); player.spellBook = rs.getInt("spellBook"); player.specialEnergy = rs.getInt("specialEnergy"); String looks = rs.getString("looks"); if (looks.length() == 0) looks = "310;307;443;599;390;646;438"; player.looks = primitive(toArray(looks, new Integer[7])); String colours = rs.getString("colors"); if (colours.length() == 0) colours = "6;40;216;4;0"; player.colours = primitive(toArray(colours, new Integer[5])); player.isMuted = rs.getInt("muted") == 1; player.isSkulled = rs.getInt("skulled") == 1; player.skullTimer = rs.getInt("skullTimer"); player.friends = toArray(rs.getString("friends"), new String[0]); player.ignores = toArray(rs.getString("ignores"), new String[0]); player.privateChatSetting = rs.getInt("pmSetting"); player.privateChatColor = rs.getInt("pmColor"); player.lastClan = rs.getString("lastClan"); rs.close(); Clan clan = new Clan(userName); if (loadClan(userName, clan, st)) { player.ownClan = clan; } st.close(); return LoginResponse.LOGIN; } } catch (SQLException e) { logger.error("Error loading player [name=" + userName + "]", e); } finally { if (sql != null) { pool.release(sql); } } return LoginResponse.ERROR; } @Override public void savePlayer(String userName, boolean lobby, PlayerSave player) { Pool<SQLSession> pool = Static.currentLink().getSQLPool(); SQLSession sql = null; try { sql = pool.acquire(); StringBuilder query = new StringBuilder(); query.append("UPDATE playersave SET"); query.append(" lastIPs='").append(ArrayUtilities.toString(player.lastIPs)).append("'"); query.append(", muted='").append(player.isMuted ? 1 : 0).append("'"); query.append(", lastLoggedIn='").append(System.currentTimeMillis()).append("'"); query.append(", friends='").append(ArrayUtilities.toString(player.friends)).append("'"); query.append(", ignores='").append(ArrayUtilities.toString(player.ignores)).append("'"); query.append(", pmSetting='").append(player.privateChatSetting).append("'"); query.append(", pmColor='").append(player.privateChatColor).append("'"); if (!lobby) { query.append(", x='").append(player.x).append("'"); query.append(", y='").append(player.y).append("'"); query.append(", z='").append(player.z).append("'"); query.append(", runToggled='").append(player.runToggled ? 1 : 0).append("'"); query.append(", runEnergy='").append(player.runEnergy).append("'"); query.append(", inv='").append(ArrayUtilities.toString(player.inv)).append("'"); query.append(", invN='").append(ArrayUtilities.toString(player.invN)).append("'"); query.append(", equip='").append(ArrayUtilities.toString(player.equip)).append("'"); query.append(", equipN='").append(ArrayUtilities.toString(player.equipN)).append("'"); int[] bank = new int[player.bank.length]; for (int i = 0; i < bank.length; i++) { bank[i] = player.bank[i][0]; } query.append(", bank='").append(ArrayUtilities.toString(bank)).append("'"); for (int i = 0; i < bank.length; i++) { bank[i] = player.bank[i][1]; } query.append(", bankN='").append(ArrayUtilities.toString(bank)).append("'"); for (int i = 0; i < bank.length; i++) { bank[i] = player.bank[i][2]; } query.append(", bankT='").append(ArrayUtilities.toString(bank)).append("'"); query.append(", level='").append(ArrayUtilities.toString(player.level)).append("'"); query.append(", exp='").append(ArrayUtilities.toString(player.exp)).append("'"); query.append(", xpCounter='").append(player.xpCounter).append("'"); query.append(", autoRetaliate='").append(player.autoRetaliate ? 1 : 0).append("'"); query.append(", attackStyle='").append(player.attackStyle).append("'"); query.append(", prayerBook='").append(player.prayerBook ? 1 : 0).append("'"); query .append(", quickPrayers='") .append(ArrayUtilities.toString(player.quickPrayers)) .append("'"); query.append(", spellBook='").append(player.spellBook).append("'"); query.append(", specialEnergy='").append(player.specialEnergy).append("'"); query.append(", looks='").append(ArrayUtilities.toString(player.looks)).append("'"); query.append(", colors='").append(ArrayUtilities.toString(player.colours)).append("'"); query.append(", muted='").append(player.isMuted ? 1 : 0).append("'"); query.append(", skulled='").append(player.isSkulled ? 1 : 0).append("'"); query.append(", skullTimer='").append(player.skullTimer).append("'"); query.append(", lastClan="); if (player.lastClan == null) { query.append("NULL"); } else { query.append("'").append(player.lastClan).append("'"); } } query.append(" WHERE id='").append(player.userId).append("'"); Statement st = sql.createStatement(); st.executeUpdate(query.toString()); st.close(); } catch (SQLException e) { logger.error("Error saving player [name=" + userName + "]", e); } finally { if (sql != null) { pool.release(sql); } } } @Override public void registerClan(String owner, String name) { Pool<SQLSession> pool = Static.currentLink().getSQLPool(); SQLSession sql = null; try { sql = pool.acquire(); Statement st = sql.createStatement(); st.executeUpdate("INSERT INTO clans (owner, name) VALUES ('" + owner + "', '" + name + "')"); st.close(); } catch (SQLException e) { logger.error("Error registering clan [owner=" + owner + "]"); } finally { if (sql != null) { pool.release(sql); } } } @Override public boolean loadClan(String owner, Clan clan) { Pool<SQLSession> pool = Static.currentLink().getSQLPool(); SQLSession sql = null; try { sql = pool.acquire(); Statement st = sql.createStatement(); boolean success = loadClan(owner, clan, st); st.close(); return success; } catch (SQLException e) { logger.error("Error loading clan [owner=" + owner + "]", e); } finally { if (sql != null) { pool.release(sql); } } return false; } private boolean loadClan(String owner, Clan clan, Statement st) throws SQLException { ResultSet rs = st.executeQuery("SELECT * FROM clans WHERE owner='" + owner + "' LIMIT 1"); if (!rs.next()) { rs.close(); return false; } clan.setName(rs.getString("name")); clan.setEnabled(rs.getBoolean("enabled")); clan.setEnterRequirement(Rank.forValue(rs.getInt("enterReq"))); clan.setTalkRequirement(Rank.forValue(rs.getInt("talkReq"))); clan.setKickRequirement(Rank.forValue(rs.getInt("kickReq"))); clan.setLootShareRequirement(Rank.forValue(rs.getInt("lootShareReq"))); String[] rankedMembers; rankedMembers = toArray(rs.getString("recruits"), new String[0]); for (String member : rankedMembers) { clan.getRanks().put(member, Rank.RECRUIT); } rankedMembers = toArray(rs.getString("corporals"), new String[0]); for (String member : rankedMembers) { clan.getRanks().put(member, Rank.CORPORAL); } rankedMembers = toArray(rs.getString("sergeants"), new String[0]); for (String member : rankedMembers) { clan.getRanks().put(member, Rank.SERGEANT); } rankedMembers = toArray(rs.getString("lieutenants"), new String[0]); for (String member : rankedMembers) { clan.getRanks().put(member, Rank.LIEUTENANT); } rankedMembers = toArray(rs.getString("captains"), new String[0]); for (String member : rankedMembers) { clan.getRanks().put(member, Rank.CAPTAIN); } rankedMembers = toArray(rs.getString("generals"), new String[0]); for (String member : rankedMembers) { clan.getRanks().put(member, Rank.GENERAL); } rs.close(); return true; } @SuppressWarnings({"rawtypes", "unchecked"}) @Override public void saveClan(Clan clan) { Pool<SQLSession> pool = Static.currentLink().getSQLPool(); SQLSession sql = null; try { sql = pool.acquire(); Statement st = sql.createStatement(); ResultSet rs = st.executeQuery("SELECT * FROM clans WHERE owner='" + clan.getOwner() + "' LIMIT 1"); if (!rs.next()) { st.executeUpdate("INSERT INTO clans (owner) VALUES ('" + clan.getOwner() + "')"); } rs.close(); StringBuilder query = new StringBuilder(); query.append("UPDATE clans SET"); query.append(" name='").append(clan.getName()).append("'"); query.append(", enabled='").append(clan.isEnabled() ? 1 : 0).append("'"); query.append(", enterReq='").append(clan.getEnterRequirement().intValue()).append("'"); query.append(", talkReq='").append(clan.getTalkRequirement().intValue()).append("'"); query.append(", kickReq='").append(clan.getKickRequirement().intValue()).append("'"); query .append(", lootShareReq='") .append(clan.getLootShareRequirement().intValue()) .append("'"); List[] ranks = new List[9]; for (Map.Entry<String, Rank> ranked : clan.getRanks().entrySet()) { List rankList = ranks[ranked.getValue().intValue() + 1]; if (rankList == null) { rankList = ranks[ranked.getValue().intValue() + 1] = new ArrayList(); } rankList.add(ranked.getKey()); } List curList; query .append(", recruits='") .append( (curList = ranks[Rank.RECRUIT.intValue() + 1]) != null ? ArrayUtilities.toString(curList.toArray(new String[0])) : "") .append("'"); query .append(", corporals='") .append( (curList = ranks[Rank.CORPORAL.intValue() + 1]) != null ? ArrayUtilities.toString(curList.toArray(new String[0])) : "") .append("'"); query .append(", sergeants='") .append( (curList = ranks[Rank.SERGEANT.intValue() + 1]) != null ? ArrayUtilities.toString(curList.toArray(new String[0])) : "") .append("'"); query .append(", lieutenants='") .append( (curList = ranks[Rank.LIEUTENANT.intValue() + 1]) != null ? ArrayUtilities.toString(curList.toArray(new String[0])) : "") .append("'"); query .append(", captains='") .append( (curList = ranks[Rank.CAPTAIN.intValue() + 1]) != null ? ArrayUtilities.toString(curList.toArray(new String[0])) : "") .append("'"); query .append(", generals='") .append( (curList = ranks[Rank.GENERAL.intValue() + 1]) != null ? ArrayUtilities.toString(curList.toArray(new String[0])) : "") .append("'"); query.append(" WHERE owner='").append(clan.getOwner()).append("'"); st.executeUpdate(query.toString()); st.close(); } catch (SQLException e) { logger.error("Error saving clan [owner=" + clan + "]", e); } finally { if (sql != null) { pool.release(sql); } } } @Override public void reload() {} private boolean verifyPassword( String inputPassword, String storedPasswordHash, String storedSalt) { MessageDigest digest; try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { logger.error("MD5 is an invalid algorithm!", e); return false; } byte[] inputPasswordHash = digest.digest(inputPassword.getBytes()); digest.reset(); byte[] storedSaltHash = digest.digest(storedSalt.getBytes()); digest.reset(); byte[] finalHash = digest.digest( new StringBuilder() .append(toHexString(storedSaltHash)) .append(toHexString(inputPasswordHash)) .toString() .getBytes()); return toHexString(finalHash).equalsIgnoreCase(storedPasswordHash); } private void applyGroupData(PlayerSave player, int[] groups) { for (int groupId : groups) { switch (groupId) { case 9: // Donator if (player.rights < 3) { player.rights = 3; } break; case 8: // In-Game Staff case 7: // Global Moderator case 20: // Trial moderator if (player.rights < 1) { player.rights = 1; } break; case 3: case 14: // ChatBox Moderator case 10: // GFX Designer case 6: // Forum Moderator if (player.rights > 1) { player.rights = 0; } break; case 12: // Developer case 11: // Owner case 4: // Director if (player.rights < 2) { player.rights = 2; } break; } } } private String toHexString(byte[] data) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < data.length; i++) { int halfByte = (data[i] >>> 4) & 0x0F; int twoHalfs = 0; do { if ((0 <= halfByte) && (halfByte <= 9)) buf.append((char) ('0' + halfByte)); else buf.append((char) ('a' + (halfByte - 10))); halfByte = data[i] & 0x0F; } while (twoHalfs++ < 1); } return buf.toString(); } }