package org.pokenet.server.network; import java.sql.ResultSet; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.Queue; import java.util.Random; import org.apache.mina.core.session.IoSession; import org.pokenet.server.GameServer; import org.pokenet.server.battle.DataService; import org.pokenet.server.battle.Pokemon; import org.pokenet.server.battle.PokemonSpecies; import org.pokenet.server.battle.mechanics.PokemonNature; import org.pokenet.server.battle.mechanics.moves.MoveListEntry; /** * Handles registrations * @author shadowkanji * */ public class RegistrationManager implements Runnable { private Queue<IoSession> m_queue; private Thread m_thread; private boolean m_isRunning; private MySqlManager m_database; /** * Constructor */ public RegistrationManager() { m_database = new MySqlManager(); m_thread = null; m_queue = new LinkedList<IoSession>(); } /** * Queues a registration * @param session * @param packet */ public void queueRegistration(IoSession session, String packet) { if(m_thread == null || !m_thread.isAlive()) start(); if(!m_queue.contains(session)) { session.setAttribute("reg", packet); m_queue.offer(session); } session.suspendRead(); session.suspendWrite(); } /** * Registers a new player * @param session */ public void register(IoSession session) throws Exception { if(!session.isConnected() || session.isClosing()) { return; } int region = Integer.parseInt(String.valueOf (((String) session.getAttribute("reg")).charAt(0))); String [] info = ((String) session.getAttribute("reg")).substring(1).split(","); /* Check the username */ if(info[0].equalsIgnoreCase("NULL") || info[0].equalsIgnoreCase("!NPC!")) { //Invalid - resevered for NPCs session.write("r4"); return; } if(info[0].startsWith(" ") || info[0].endsWith(" ") || info[0].contains("!") || info[0].contains("&") || info[0].contains("%") || info[0].contains("(") || info[0].contains(")") || info[0].contains("[") || info[0].contains("]") || info[0].contains("~") || info[0].contains("#") || info[0].contains("|") || info[0].contains("?") || info[0].contains("/") || info[0].contains("\"")) { //Invalid session.write("r4"); return; } m_database = new MySqlManager(); if(m_database.connect(GameServer.getDatabaseHost(), GameServer.getDatabaseUsername(), GameServer.getDatabasePassword())) { m_database.selectDatabase(GameServer.getDatabaseName()); int s = Integer.parseInt(info[4]); /* * Check if the user exists */ ResultSet data = m_database.query("SELECT * FROM pn_members WHERE username='" + MySqlManager.parseSQL(info[0]) + "'"); data.first(); try { if(data != null && data.getString("username") != null && data.getString("username").equalsIgnoreCase(MySqlManager.parseSQL(info[0]))) { session.resumeRead(); session.resumeWrite(); session.write("r2"); return; } } catch (Exception e) {} /* * Check if an account is already registered with the email */ data = m_database.query("SELECT * FROM pn_members WHERE email='" + MySqlManager.parseSQL(info[2]) + "'"); data.first(); try { if(data != null && data.getString("email") != null && data.getString("email").equalsIgnoreCase(MySqlManager.parseSQL(info[2]))) { session.resumeRead(); session.resumeWrite(); session.write("r5"); return; } if(info[2].length() > 52) { session.resumeRead(); session.resumeWrite(); session.write("r6"); return; } } catch (Exception e) {} /* * Check if user is not trying to register their starter as a non-starter Pokemon */ if(!(s == 1 || s == 4 || s == 7 || s == 152 || s == 155 || s == 158 || s == 252 || s == 255 || s == 258 || s == 387 || s == 390 || s == 393)) { session.write("r4"); return; } /* * Generate badge string */ String badges = ""; for(int i = 0; i < 50; i++) badges = badges + "0"; /* * Generate starting position */ int mapX = 0; int mapY = 0; int x = 256; int y = 440; switch(region) { case 0: /* Kanto */ mapX = 3; mapY = 1; x = 512; y = 440; break; case 1: /* Johto */ mapX = 0; mapY = 0; x = 256; y = 440; break; default: /* Prevent breaking the system */ mapX = 0; mapY = 0; x = 256; y = 440; break; } /* * Insert player into database */ m_database.query("INSERT INTO pn_members (username, password, dob, email, lastLoginTime, lastLoginServer, " + "sprite, money, skHerb, skCraft, skFish, skTrain, skCoord, skBreed, " + "x, y, mapX, mapY, badges, healX, healY, healMapX, healMapY, isSurfing, adminLevel, muted) VALUE " + "('" + MySqlManager.parseSQL(info[0]) + "', '" + MySqlManager.parseSQL(info[1]) + "', '" + MySqlManager.parseSQL(info[3]) + "', '" + MySqlManager.parseSQL(info[2]) + "', " + "'0', 'null', '" + MySqlManager.parseSQL(info[5]) + "', '0', '0', " + "'0', '0', '0', '0', '0', '" + x + "', '" + y + "', " + "'" + mapX + "', '" + mapY + "', '" + badges + "', '" + x + "', '" + y + "', '" + mapX + "', '" + mapY + "', 'false', '0', 'false')"); /* * Retrieve the player's unique id */ data = m_database.query("SELECT * FROM pn_members WHERE username='" + MySqlManager.parseSQL(info[0]) + "'"); data.first(); int playerId = data.getInt("id"); //Player's bag is now created "on the fly" as soon as player gets his first item. /* * Create the players party */ Pokemon p = this.createStarter(s); p.setOriginalTrainer(info[0]); p.setDateCaught(new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss").format(new Date())); this.saveNewPokemon(p, m_database); m_database.query("INSERT INTO pn_party (member, pokemon0, pokemon1, pokemon2, pokemon3, pokemon4, pokemon5) VALUES ('" + + playerId + "','" + p.getDatabaseID() + "','-1','-1','-1','-1','-1')"); data = m_database.query("SELECT * FROM pn_party WHERE member='" + playerId + "'"); data.first(); /* * Attach pokemon to the player */ m_database.query("UPDATE pn_members SET party='" + data.getInt("id") + "' WHERE id='" + playerId + "'"); /* Attach a bag of 5 pokeballs to the player */ m_database.query("INSERT INTO pn_bag (member,item,quantity) VALUES ('" + playerId + "', '35', '5')"); /* * Finish */ m_database.close(); session.resumeRead(); session.resumeWrite(); session.write("rs"); } else { session.resumeRead(); session.resumeWrite(); session.write("r1"); } } /** * Called by m_thread.start() */ public void run() { IoSession session; while(m_isRunning) { synchronized(m_queue) { if(m_queue.peek() != null) { session = m_queue.poll(); try { this.register(session); } catch (Exception e) { e.printStackTrace(); session.resumeRead(); session.resumeWrite(); session.write("r3"); } } } try { Thread.sleep(250); } catch (Exception e) {} } } /** * Start the registration manager */ public void start() { if(m_thread == null || !m_thread.isAlive()) { m_thread = new Thread(this); m_isRunning = true; m_thread.start(); } } /** * Stop the registration manager */ public void stop() { m_isRunning = false; } /** * Saves a pokemon to the database that didn't exist in it before * @param p */ private boolean saveNewPokemon(Pokemon p, MySqlManager db) { try { /* * Insert the Pokemon into the database */ db.query("INSERT INTO pn_pokemon" + "(name, speciesName, exp, baseExp, expType, isFainted, level, happiness, " + "gender, nature, abilityName, itemName, isShiny, currentTrainerName, originalTrainerName, date, contestStats)" + "VALUES (" + "'" + MySqlManager.parseSQL(p.getName()) +"', " + "'" + MySqlManager.parseSQL(p.getSpeciesName()) +"', " + "'" + String.valueOf(p.getExp()) +"', " + "'" + p.getBaseExp() +"', " + "'" + MySqlManager.parseSQL(p.getExpType().name()) +"', " + "'" + String.valueOf(p.isFainted()) +"', " + "'" + p.getLevel() +"', " + "'" + p.getHappiness() +"', " + "'" + p.getGender() +"', " + "'" + MySqlManager.parseSQL(p.getNature().getName()) +"', " + "'" + MySqlManager.parseSQL(p.getAbilityName()) +"', " + "'" + MySqlManager.parseSQL(p.getItemName()) +"', " + "'" + String.valueOf(p.isShiny()) +"', " + "'" + MySqlManager.parseSQL(p.getOriginalTrainer()) + "', " + "'" + MySqlManager.parseSQL(p.getOriginalTrainer()) + "', " + "'" + MySqlManager.parseSQL(p.getDateCaught()) + "', " + "'" + p.getContestStatsAsString() + "')"); /* * Get the pokemon's database id and attach it to the pokemon. * This needs to be done so it can be attached to the player in the database later. */ ResultSet result = db.query("SELECT * FROM pn_pokemon WHERE originalTrainerName='" + MySqlManager.parseSQL(p.getOriginalTrainer()) + "' AND date='" + MySqlManager.parseSQL(p.getDateCaught()) + "'"); result.first(); p.setDatabaseID(result.getInt("id")); db.query("UPDATE pn_pokemon SET move0='" + MySqlManager.parseSQL(p.getMove(0).getName()) + "', move1='" + (p.getMove(1) == null ? "null" : MySqlManager.parseSQL(p.getMove(1).getName())) + "', move2='" + (p.getMove(2) == null ? "null" : MySqlManager.parseSQL(p.getMove(2).getName())) + "', move3='" + (p.getMove(3) == null ? "null" : MySqlManager.parseSQL(p.getMove(3).getName())) + "', hp='" + p.getHealth() + "', atk='" + p.getStat(1) + "', def='" + p.getStat(2) + "', speed='" + p.getStat(3) + "', spATK='" + p.getStat(4) + "', spDEF='" + p.getStat(5) + "', evHP='" + p.getEv(0) + "', evATK='" + p.getEv(1) + "', evDEF='" + p.getEv(2) + "', evSPD='" + p.getEv(3) + "', evSPATK='" + p.getEv(4) + "', evSPDEF='" + p.getEv(5) + "' WHERE id='" + p.getDatabaseID() + "'"); db.query("UPDATE pn_pokemon SET ivHP='" + p.getIv(0) + "', ivATK='" + p.getIv(1) + "', ivDEF='" + p.getIv(2) + "', ivSPD='" + p.getIv(3) + "', ivSPATK='" + p.getIv(4) + "', ivSPDEF='" + p.getIv(5) + "', pp0='" + p.getPp(0) + "', pp1='" + p.getPp(1) + "', pp2='" + p.getPp(2) + "', pp3='" + p.getPp(3) + "', maxpp0='" + p.getMaxPp(0) + "', maxpp1='" + p.getMaxPp(1) + "', maxpp2='" + p.getMaxPp(2) + "', maxpp3='" + p.getMaxPp(3) + "', ppUp0='" + p.getPpUpCount(0) + "', ppUp1='" + p.getPpUpCount(1) + "', ppUp2='" + p.getPpUpCount(2) + "', ppUp3='" + p.getPpUpCount(3) + "' WHERE id='" + p.getDatabaseID() + "'"); return true; } catch (Exception e) { e.printStackTrace(); return false; } } /** * Creates a starter Pokemon * @param speciesIndex * @return * @throws Exception */ private Pokemon createStarter(int speciesIndex) throws Exception { /* * Get the Pokemon species. Use getPokemonByName as once the * species array gets to gen 3 it loses the pokedex numbering */ PokemonSpecies species = null; switch(speciesIndex) { case 1: species = PokemonSpecies.getDefaultData().getPokemonByName("Bulbasaur"); break; case 4: species = PokemonSpecies.getDefaultData().getPokemonByName("Charmander"); break; case 7: species = PokemonSpecies.getDefaultData().getPokemonByName("Squirtle"); break; case 152: species = PokemonSpecies.getDefaultData().getPokemonByName("Chikorita"); break; case 155: species = PokemonSpecies.getDefaultData().getPokemonByName("Cyndaquil"); break; case 158: species = PokemonSpecies.getDefaultData().getPokemonByName("Totodile"); break; case 252: species = PokemonSpecies.getDefaultData().getPokemonByName("Treecko"); break; case 255: species = PokemonSpecies.getDefaultData().getPokemonByName("Torchic"); break; case 258: species = PokemonSpecies.getDefaultData().getPokemonByName("Mudkip"); break; case 387: species = PokemonSpecies.getDefaultData().getPokemonByName("Turtwig"); break; case 390: species = PokemonSpecies.getDefaultData().getPokemonByName("Chimchar"); break; case 393: species = PokemonSpecies.getDefaultData().getPokemonByName("Piplup"); break; default: species = PokemonSpecies.getDefaultData().getPokemonByName("Mudkip"); } ArrayList<MoveListEntry> possibleMoves = new ArrayList<MoveListEntry>(); MoveListEntry[] moves = new MoveListEntry[4]; Random random = DataService.getBattleMechanics().getRandom(); for (int i = 0; i < species.getStarterMoves().length; i++) { possibleMoves.add(DataService.getMovesList().getMove( species.getStarterMoves()[i])); } for (int i = 1; i <= 5; i++) { if (species.getLevelMoves().containsKey(i)) { possibleMoves.add(DataService.getMovesList().getMove( species.getLevelMoves().get(i))); } } /* * possibleMoves sometimes has null moves stored in it, get rid of them */ for(int i = 0; i < possibleMoves.size(); i++) { if(possibleMoves.get(i) == null) possibleMoves.remove(i); } /* * Now the store the final set of moves for the Pokemon */ if (possibleMoves.size() <= 4) { for (int i = 0; i < possibleMoves.size(); i++) { moves[i] = possibleMoves.get(i); } } else { MoveListEntry m = null; for (int i = 0; i < 4; i++) { if (possibleMoves.size() == 0) { moves[i] = null; } else { while(m == null) { m = possibleMoves.get(random.nextInt(possibleMoves .size())); } moves[i] = m; possibleMoves.remove(m); m = null; } } } /* * Get all possible abilities */ String [] abilities = species.getAbilities(); /* First select an ability randomly */ String ab = abilities[random.nextInt(abilities.length)]; /* * Unfortunately, all Pokemon have two possible ability slots but some only have one. * If the null slot was selected, select the other slot */ while(ab == null || ab.equalsIgnoreCase("")) { ab = abilities[random.nextInt(abilities.length)]; } /* * Create the Pokemon object */ Pokemon starter = new Pokemon( DataService.getBattleMechanics(), species, PokemonNature.N_QUIRKY, ab, null, (random.nextInt(100) > 87 ? Pokemon.GENDER_FEMALE : Pokemon.GENDER_MALE), 5, new int[] { random.nextInt(32), // IVs random.nextInt(32), random.nextInt(32), random.nextInt(32), random.nextInt(32), random.nextInt(32) }, new int[] { 0, 0, 0, 0, 0, 0 }, //EVs moves, new int[] { 0, 0, 0, 0 }); /* Attach their growth rate */ starter.setExpType(species.getGrowthRate()); /* Attach base experience */ starter.setBaseExp(species.getBaseEXP()); /* Set their current exp */ starter.setExp(DataService.getBattleMechanics().getExpForLevel(starter, 5)); /* Set their happiness */ starter.setHappiness(species.getHappiness()); /* Set their name as their species */ starter.setName(starter.getSpeciesName()); return starter; } }