Added cash shop name changes and world transfers. (#495)
* Name changes * World transfers. Fix NPE. Applied Arnuh's suggestions. More logging.
This commit is contained in:
@@ -103,6 +103,7 @@ import server.life.MaplePlayerNPCFactory;
|
||||
import server.quest.MapleQuest;
|
||||
import tools.AutoJCE;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.FilePrinter;
|
||||
import tools.Pair;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
|
||||
@@ -881,7 +882,8 @@ public class Server {
|
||||
} catch (SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
|
||||
applyAllNameChanges(); //name changes can be missed by INSTANT_NAME_CHANGE
|
||||
applyAllWorldTransfers();
|
||||
MaplePet.clearMissingPetsFromDb();
|
||||
MapleCashidGenerator.loadExistentCashIdsFromDb();
|
||||
|
||||
@@ -1554,6 +1556,82 @@ public class Server {
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyAllNameChanges() {
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM namechanges WHERE completionTime IS NULL")) {
|
||||
ResultSet rs = ps.executeQuery();
|
||||
List<Pair<String, String>> changedNames = new LinkedList<Pair<String, String>>(); //logging only
|
||||
while(rs.next()) {
|
||||
con.setAutoCommit(false);
|
||||
int nameChangeId = rs.getInt("id");
|
||||
int characterId = rs.getInt("characterId");
|
||||
String oldName = rs.getString("old");
|
||||
String newName = rs.getString("new");
|
||||
boolean success = MapleCharacter.doNameChange(con, characterId, oldName, newName, nameChangeId);
|
||||
if(!success) con.rollback(); //discard changes
|
||||
else changedNames.add(new Pair<String, String>(oldName, newName));
|
||||
con.setAutoCommit(true);
|
||||
}
|
||||
//log
|
||||
for(Pair<String, String> namePair : changedNames) {
|
||||
FilePrinter.print(FilePrinter.CHANGE_CHARACTER_NAME, "Name change applied : from \"" + namePair.getLeft() + "\" to \"" + namePair.getRight() + "\" at " + Calendar.getInstance().getTime().toString());
|
||||
}
|
||||
} catch(SQLException e) {
|
||||
e.printStackTrace();
|
||||
FilePrinter.printError(FilePrinter.CHANGE_CHARACTER_NAME, e, "Failed to retrieve list of pending name changes.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyAllWorldTransfers() {
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM worldtransfers WHERE completionTime IS NULL")) {
|
||||
ResultSet rs = ps.executeQuery();
|
||||
List<Integer> removedTransfers = new LinkedList<Integer>();
|
||||
while(rs.next()) {
|
||||
int nameChangeId = rs.getInt("id");
|
||||
int characterId = rs.getInt("characterId");
|
||||
int oldWorld = rs.getInt("from");
|
||||
int newWorld = rs.getInt("to");
|
||||
String reason = MapleCharacter.checkWorldTransferEligibility(con, characterId, oldWorld, newWorld); //check if character is still eligible
|
||||
if(reason != null) {
|
||||
removedTransfers.add(nameChangeId);
|
||||
FilePrinter.print(FilePrinter.WORLD_TRANSFER, "World transfer cancelled : Character ID " + characterId + " at " + Calendar.getInstance().getTime().toString() + ", Reason : " + reason);
|
||||
try (PreparedStatement delPs = con.prepareStatement("DELETE FROM worldtransfers WHERE id = ?")) {
|
||||
delPs.setInt(1, nameChangeId);
|
||||
delPs.executeUpdate();
|
||||
} catch(SQLException e) {
|
||||
e.printStackTrace();
|
||||
FilePrinter.printError(FilePrinter.WORLD_TRANSFER, e, "Failed to delete world transfer for character ID " + characterId);
|
||||
}
|
||||
}
|
||||
}
|
||||
rs.beforeFirst();
|
||||
List<Pair<Integer, Pair<Integer, Integer>>> worldTransfers = new LinkedList<Pair<Integer, Pair<Integer, Integer>>>(); //logging only <charid, <oldWorld, newWorld>>
|
||||
while(rs.next()) {
|
||||
con.setAutoCommit(false);
|
||||
int nameChangeId = rs.getInt("id");
|
||||
if(removedTransfers.contains(nameChangeId)) continue;
|
||||
int characterId = rs.getInt("characterId");
|
||||
int oldWorld = rs.getInt("from");
|
||||
int newWorld = rs.getInt("to");
|
||||
boolean success = MapleCharacter.doWorldTransfer(con, characterId, oldWorld, newWorld, nameChangeId);
|
||||
if(!success) con.rollback();
|
||||
else worldTransfers.add(new Pair<Integer, Pair<Integer, Integer>>(characterId, new Pair<Integer, Integer>(oldWorld, newWorld)));
|
||||
con.setAutoCommit(true);
|
||||
}
|
||||
//log
|
||||
for(Pair<Integer, Pair<Integer, Integer>> worldTransferPair : worldTransfers) {
|
||||
int charId = worldTransferPair.getLeft();
|
||||
int oldWorld = worldTransferPair.getRight().getLeft();
|
||||
int newWorld = worldTransferPair.getRight().getRight();
|
||||
FilePrinter.print(FilePrinter.WORLD_TRANSFER, "World transfer applied : Character ID " + charId + " from World " + oldWorld + " to World " + newWorld + " at " + Calendar.getInstance().getTime().toString());
|
||||
}
|
||||
} catch(SQLException e) {
|
||||
e.printStackTrace();
|
||||
FilePrinter.printError(FilePrinter.WORLD_TRANSFER, e, "Failed to retrieve list of pending world transfers.");
|
||||
}
|
||||
}
|
||||
|
||||
public void loadAccountCharacters(MapleClient c) {
|
||||
Integer accId = c.getAccID();
|
||||
if (!isFirstAccountLogin(accId)) {
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import server.CashShop;
|
||||
import server.CashShop.CashItem;
|
||||
import server.CashShop.CashItemFactory;
|
||||
@@ -343,7 +344,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
slea.readByte();
|
||||
MapleCharacter partner = c.getChannelServer().getPlayerStorage().getCharacterByName(sentTo);
|
||||
if (partner == null) {
|
||||
chr.dropMessage(5, "The partner you specified cannot be found. Please make sure your partner is online and in the same channel.");
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0xBE));
|
||||
} else {
|
||||
// Need to check to make sure its actually an equip and the right SN...
|
||||
if(itemRing.toItem() instanceof Equip) {
|
||||
@@ -351,7 +352,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
Pair<Integer, Integer> rings = MapleRing.createRing(itemRing.getItemId(), chr, partner);
|
||||
eqp.setRingId(rings.getLeft());
|
||||
cs.addToInventory(eqp);
|
||||
c.announce(MaplePacketCreator.showBoughtCashItem(eqp, c.getAccID()));
|
||||
c.announce(MaplePacketCreator.showBoughtCashRing(eqp, partner.getName(), c.getAccID()));
|
||||
cs.gift(partner.getId(), chr.getName(), text, eqp.getSN(), rings.getRight());
|
||||
cs.gainCash(payment, -itemRing.getPrice());
|
||||
chr.addFriendshipRing(MapleRing.loadFromDb(rings.getLeft()));
|
||||
@@ -368,6 +369,65 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
|
||||
} else if (action == 0x2E) { //name change
|
||||
CashItem cItem = CashItemFactory.getItem(slea.readInt());
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(4))) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
}
|
||||
if(cItem.getSN() == 50600000 && ServerConstants.ALLOW_CASHSHOP_NAME_CHANGE) {
|
||||
slea.readMapleAsciiString(); //old name
|
||||
String newName = slea.readMapleAsciiString();
|
||||
if(!MapleCharacter.canCreateChar(newName) || chr.getLevel() < 10) { //(longest ban duration isn't tracked currently)
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
} else if(c.getTempBanCalendar() != null && c.getTempBanCalendar().getTimeInMillis() + (30*24*60*60*1000) > Calendar.getInstance().getTimeInMillis()) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
}
|
||||
if(chr.registerNameChange(newName)) { //success
|
||||
Item item = cItem.toItem();
|
||||
c.announce(MaplePacketCreator.showNameChangeSuccess(item, c.getAccID()));
|
||||
cs.addToInventory(item);
|
||||
cs.gainCash(4, cItem, chr.getWorld());
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0));
|
||||
}
|
||||
}
|
||||
c.enableCSActions();
|
||||
} else if(action == 0x31) { //world transfer
|
||||
CashItem cItem = CashItemFactory.getItem(slea.readInt());
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(4))) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
}
|
||||
if(cItem.getSN() == 50600001 && ServerConstants.ALLOW_CASHSHOP_WORLD_TRANSFER) {
|
||||
int newWorldSelection = slea.readInt();
|
||||
|
||||
int worldTransferError = chr.checkWorldTransferEligibility();
|
||||
if(worldTransferError != 0 || newWorldSelection >= Server.getInstance().getWorldsSize() || Server.getInstance().getWorldsSize() <= 1) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0));
|
||||
return;
|
||||
} else if(newWorldSelection == c.getWorld()) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0xDC));
|
||||
return;
|
||||
} else if(c.getAvailableCharacterWorldSlots(newWorldSelection) < 1 || Server.getInstance().getAccountWorldCharacterCount(c.getAccID(), newWorldSelection) >= 3) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0xDF));
|
||||
return;
|
||||
} else if(chr.registerWorldTransfer(newWorldSelection)) {
|
||||
Item item = cItem.toItem();
|
||||
c.announce(MaplePacketCreator.showWorldTransferSuccess(item, c.getAccID()));
|
||||
cs.addToInventory(item);
|
||||
cs.gainCash(4, cItem, chr.getWorld());
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte)0));
|
||||
}
|
||||
}
|
||||
c.enableCSActions();
|
||||
} else {
|
||||
System.out.println("Unhandled action: " + action + "\n" + slea);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,25 @@
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Calendar;
|
||||
import java.sql.Connection;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import constants.ServerConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
* @author Ubaware
|
||||
*/
|
||||
public final class TransferNameHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -40,7 +51,37 @@ public final class TransferNameHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(4));
|
||||
if(!ServerConstants.ALLOW_CASHSHOP_NAME_CHANGE) {
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(4));
|
||||
return;
|
||||
}
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
if(chr.getLevel() < 10) {
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(4));
|
||||
return;
|
||||
} else if(c.getTempBanCalendar() != null && c.getTempBanCalendar().getTimeInMillis() + (30*24*60*60*1000) < Calendar.getInstance().getTimeInMillis()) {
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(2));
|
||||
return;
|
||||
}
|
||||
//sql queries
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT completionTime FROM namechanges WHERE characterid=?")) { //double check, just in case
|
||||
ps.setInt(1, chr.getId());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
Timestamp completedTimestamp = rs.getTimestamp("completionTime");
|
||||
if(completedTimestamp == null) { //has pending name request
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(1));
|
||||
return;
|
||||
} else if(completedTimestamp.getTime() + ServerConstants.NAME_CHANGE_COOLDOWN > System.currentTimeMillis()) {
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(3));
|
||||
return;
|
||||
};
|
||||
}
|
||||
} catch(SQLException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(0));
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,6 @@ public final class TransferNameResultHandler extends AbstractMaplePacketHandler
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
String name = slea.readMapleAsciiString();
|
||||
c.announce(MaplePacketCreator.sendNameTransferCheck(MapleCharacter.canCreateChar(name)));
|
||||
c.announce(MaplePacketCreator.sendNameTransferCheck(name, MapleCharacter.canCreateChar(name)));
|
||||
}
|
||||
}
|
||||
@@ -20,14 +20,25 @@
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import constants.ServerConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
* @author Ubaware
|
||||
*/
|
||||
public final class TransferWorldHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -40,7 +51,34 @@ public final class TransferWorldHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.sendWorldTransferRules(9));
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
if(!ServerConstants.ALLOW_CASHSHOP_WORLD_TRANSFER || Server.getInstance().getWorldsSize() <= 1) {
|
||||
c.announce(MaplePacketCreator.sendWorldTransferRules(9, c));
|
||||
return;
|
||||
}
|
||||
int worldTransferError = chr.checkWorldTransferEligibility();
|
||||
if(worldTransferError != 0) {
|
||||
c.announce(MaplePacketCreator.sendWorldTransferRules(worldTransferError, c));
|
||||
return;
|
||||
}
|
||||
try (Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT completionTime FROM worldtransfers WHERE characterid=?")) {
|
||||
ps.setInt(1, chr.getId());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
Timestamp completedTimestamp = rs.getTimestamp("completionTime");
|
||||
if(completedTimestamp == null) { //has pending world transfer
|
||||
c.announce(MaplePacketCreator.sendWorldTransferRules(6, c));
|
||||
return;
|
||||
} else if(completedTimestamp.getTime() + ServerConstants.WORLD_TRANSFER_COOLDOWN > System.currentTimeMillis()) {
|
||||
c.announce(MaplePacketCreator.sendWorldTransferRules(7, c));
|
||||
return;
|
||||
};
|
||||
}
|
||||
} catch(SQLException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
c.announce(MaplePacketCreator.sendWorldTransferRules(0, c));
|
||||
}
|
||||
}
|
||||
@@ -423,6 +423,24 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
}, 1000 * 10);
|
||||
remove(c, position, itemId);
|
||||
} else if (itemType == 540) {
|
||||
slea.readByte();
|
||||
slea.readInt();
|
||||
if(itemId == 5400000) { //name change
|
||||
if(player.cancelPendingNameChange()) {
|
||||
player.dropMessage(1, "Successfully canceled pending name change.");
|
||||
} else {
|
||||
player.dropMessage(1, "You do not have a pending name change.");
|
||||
}
|
||||
} else if(itemId == 5401000) { //world transfer
|
||||
if(player.cancelPendingWorldTranfer()) {
|
||||
player.dropMessage(1, "Successfully canceled pending world transfer.");
|
||||
} else {
|
||||
player.dropMessage(1, "You do not have a pending world transfer.");
|
||||
}
|
||||
}
|
||||
remove(c, position, itemId);
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
} else if (itemType == 543) {
|
||||
if(itemId == 5432000 && !c.gainCharacterSlot()) {
|
||||
player.dropMessage(1, "You have already used up all 12 extra character slots.");
|
||||
|
||||
@@ -135,7 +135,7 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.getLoginFailed(3));
|
||||
return;
|
||||
}
|
||||
Calendar tempban = c.getTempBanCalendar();
|
||||
Calendar tempban = c.getTempBanCalendarFromDB();
|
||||
if (tempban != null) {
|
||||
if (tempban.getTimeInMillis() > Calendar.getInstance().getTimeInMillis()) {
|
||||
c.announce(MaplePacketCreator.getTempBan(tempban.getTimeInMillis(), c.getGReason()));
|
||||
|
||||
Reference in New Issue
Block a user