GMS-like Wedding + Scissors of Karma + Maple Life + Buyback
Properly developed the Marriage feature in the source. Added TRAVEL_RATE server flag, a modifier for the travel frequency rate. Corrected stance for players in 3rd party view when entering a map to work similarly as GMS. Fixed mobs spamming skills incoherently. Added code support for old GMS-like PQ NPCs, where party leaders just need to click once to start a new PQ. Implemented podium system for the Hall of Fame PlayerNPCs. Improved character load-out system, now using way less queries to the DB in the process. Fixed birthday field for accounts not being read correctly. Further implemented the incomplete yet-existing Scissors of Karma mechanic. Fixed Duey not propagating item flags when packaging an item. Added a custom buyback system. Refactored the character creation system, now offering support for Maple Life. Fixed some issues with the PlayerNPC positioning system. Added server flag allowing AP assignment for novices (beginners under level 11). Fixed Strategy Time (GPQ) announcement being sent twice to guilds in certain cases. Tweaked mount EXP system now awarding it accordingly with the amount of tiredness healed. Removed the randomness aspect of closeness gain when feeding the pet, now acting accordingly with amount of fullness gained. Fixed an exploit with Arwen script. Fixed travel-back from Florina forcefully sending players to Lith Harbor in certain situations. Thoroughly reviewed job skill questlines for Explorers and Aran. Localhost edit: removed MTS block in certain maps (useful for the buyback system). Localhost edit: removed party blocks for novices. Localhost edit: removed AP assigning block for novices. Localhost edit: removed speed cap. Localhost edit: removed Maker block popping up when inputting ATK gems on non-weapons.
This commit is contained in:
@@ -104,6 +104,7 @@ public class Server {
|
||||
private final List<MapleClient> processDiseaseAnnouncePlayers = new LinkedList<>();
|
||||
private final List<MapleClient> registeredDiseaseAnnouncePlayers = new LinkedList<>();
|
||||
|
||||
private boolean availableDeveloperRoom = false;
|
||||
private boolean online = false;
|
||||
public static long uptime = System.currentTimeMillis();
|
||||
|
||||
@@ -133,6 +134,14 @@ public class Server {
|
||||
public NewYearCardRecord removeNewYearCard(int cardid) {
|
||||
return newyears.remove(cardid);
|
||||
}
|
||||
|
||||
public void setAvailableDeveloperRoom() {
|
||||
availableDeveloperRoom = true;
|
||||
}
|
||||
|
||||
public boolean canEnterDeveloperRoom() {
|
||||
return availableDeveloperRoom;
|
||||
}
|
||||
|
||||
private void loadPlayerNpcMapStepFromDb() {
|
||||
try {
|
||||
@@ -141,8 +150,8 @@ public class Server {
|
||||
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while(rs.next()) {
|
||||
int world = rs.getInt("world"), map = rs.getInt("map"), step = rs.getInt("step");
|
||||
worlds.get(world).setPlayerNpcMapStep(map, step, true);
|
||||
int world = rs.getInt("world"), map = rs.getInt("map"), step = rs.getInt("step"), podium = rs.getInt("podium");
|
||||
worlds.get(world).setPlayerNpcMapData(map, step, podium);
|
||||
}
|
||||
|
||||
rs.close();
|
||||
@@ -401,9 +410,10 @@ public class Server {
|
||||
worldRecommendedList.add(new Pair<>(i, p.getProperty("whyamirecommended" + i)));
|
||||
worlds.add(world);
|
||||
channels.add(new HashMap<Integer, String>());
|
||||
long bootTime = System.currentTimeMillis();
|
||||
for (int j = 0; j < Integer.parseInt(p.getProperty("channels" + i)); j++) {
|
||||
int channelid = j + 1;
|
||||
Channel channel = new Channel(i, channelid);
|
||||
Channel channel = new Channel(i, channelid, bootTime);
|
||||
world.addChannel(channel);
|
||||
channels.get(i).put(channelid, channel.getIP());
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ package net.server.channel;
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -41,6 +42,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
import net.MapleServerHandler;
|
||||
import net.mina.MapleCodecFactory;
|
||||
import net.server.Server;
|
||||
import net.server.world.World;
|
||||
import net.server.PlayerStorage;
|
||||
import net.server.world.MapleParty;
|
||||
import net.server.world.MaplePartyCharacter;
|
||||
@@ -65,6 +68,7 @@ import server.maps.MapleMap;
|
||||
import server.maps.MapleMapFactory;
|
||||
import server.maps.MapleMiniDungeon;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import client.MapleCharacter;
|
||||
import constants.ServerConstants;
|
||||
import server.maps.MapleMiniDungeonInfo;
|
||||
@@ -92,15 +96,30 @@ public final class Channel {
|
||||
private Map<Integer, Integer> dojoParty = new HashMap<>();
|
||||
private Map<Integer, MapleMiniDungeon> dungeons = new HashMap<>();
|
||||
|
||||
private List<Integer> chapelReservationQueue = new LinkedList<>();
|
||||
private List<Integer> cathedralReservationQueue = new LinkedList<>();
|
||||
private ScheduledFuture<?> chapelReservationTask;
|
||||
private ScheduledFuture<?> cathedralReservationTask;
|
||||
|
||||
private Integer ongoingChapel = null;
|
||||
private Boolean ongoingChapelType = null;
|
||||
private Set<Integer> ongoingChapelGuests = null;
|
||||
private Integer ongoingCathedral = null;
|
||||
private Boolean ongoingCathedralType = null;
|
||||
private Set<Integer> ongoingCathedralGuests = null;
|
||||
private long ongoingStartTime;
|
||||
|
||||
private ReentrantReadWriteLock merchantLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.MERCHANT, true);
|
||||
private ReadLock merchRlock = merchantLock.readLock();
|
||||
private WriteLock merchWlock = merchantLock.writeLock();
|
||||
|
||||
private Lock lock = new MonitoredReentrantLock(MonitoredLockType.CHANNEL, true);
|
||||
|
||||
public Channel(final int world, final int channel) {
|
||||
public Channel(final int world, final int channel, long startTime) {
|
||||
this.world = world;
|
||||
this.channel = channel;
|
||||
|
||||
this.ongoingStartTime = startTime + 10000; // rude approach to a world's last channel boot time, placeholder for the 1st wedding reservation ever
|
||||
this.mapFactory = new MapleMapFactory(null, MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Map.wz")), MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/String.wz")), world, channel);
|
||||
try {
|
||||
eventSM = new EventScriptManager(this, getEvents());
|
||||
@@ -528,4 +547,297 @@ public final class Channel {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<Boolean, Pair<Integer, Set<Integer>>> getNextWeddingReservation(boolean cathedral) {
|
||||
Integer ret;
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
List<Integer> weddingReservationQueue = (cathedral ? cathedralReservationQueue : chapelReservationQueue);
|
||||
if(weddingReservationQueue.isEmpty()) return null;
|
||||
|
||||
ret = weddingReservationQueue.remove(0);
|
||||
if(ret == null) return null;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
World wserv = Server.getInstance().getWorld(world);
|
||||
|
||||
Pair<Integer, Integer> coupleId = wserv.getMarriageQueuedCouple(ret);
|
||||
Pair<Boolean, Set<Integer>> typeGuests = wserv.removeMarriageQueued(ret);
|
||||
|
||||
Pair<String, String> couple = new Pair<>(MapleCharacter.getNameById(coupleId.getLeft()), MapleCharacter.getNameById(coupleId.getRight()));
|
||||
wserv.dropMessage(6, couple.getLeft() + " and " + couple.getRight() + "'s wedding is going to be started at " + (cathedral ? "Cathedral" : "Chapel") + " on Channel " + channel + ".");
|
||||
|
||||
return new Pair<>(typeGuests.getLeft(), new Pair<>(ret, typeGuests.getRight()));
|
||||
}
|
||||
|
||||
public boolean isWeddingReserved(Integer weddingId) {
|
||||
World wserv = Server.getInstance().getWorld(world);
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
return wserv.isMarriageQueued(weddingId) || weddingId.equals(ongoingCathedral) || weddingId.equals(ongoingChapel);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getWeddingReservationStatus(Integer weddingId, boolean cathedral) {
|
||||
if(weddingId == null) return -1;
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
if(cathedral) {
|
||||
if(weddingId.equals(ongoingCathedral)) return 0;
|
||||
|
||||
for(int i = 0; i < cathedralReservationQueue.size(); i++) {
|
||||
if(weddingId.equals(cathedralReservationQueue.get(i))) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(weddingId.equals(ongoingChapel)) return 0;
|
||||
|
||||
for(int i = 0; i < chapelReservationQueue.size(); i++) {
|
||||
if(weddingId.equals(chapelReservationQueue.get(i))) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int pushWeddingReservation(Integer weddingId, boolean cathedral, boolean premium, Integer groomId, Integer brideId) {
|
||||
if(weddingId == null || isWeddingReserved(weddingId)) return -1;
|
||||
|
||||
World wserv = Server.getInstance().getWorld(world);
|
||||
wserv.putMarriageQueued(weddingId, cathedral, premium, groomId, brideId);
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
List<Integer> weddingReservationQueue = (cathedral ? cathedralReservationQueue : chapelReservationQueue);
|
||||
|
||||
int delay = ServerConstants.WEDDING_RESERVATION_DELAY - 1 - weddingReservationQueue.size();
|
||||
for(int i = 0; i < delay; i++) {
|
||||
weddingReservationQueue.add(null); // push empty slots to fill the waiting time
|
||||
}
|
||||
|
||||
weddingReservationQueue.add(weddingId);
|
||||
return weddingReservationQueue.size();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOngoingWeddingGuest(boolean cathedral, int playerId) {
|
||||
lock.lock();
|
||||
try {
|
||||
if(cathedral) {
|
||||
return ongoingCathedralGuests != null && ongoingCathedralGuests.contains(playerId);
|
||||
} else {
|
||||
return ongoingChapelGuests != null && ongoingChapelGuests.contains(playerId);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getOngoingWedding(boolean cathedral) {
|
||||
lock.lock();
|
||||
try {
|
||||
return cathedral ? ongoingCathedral : ongoingChapel;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getOngoingWeddingType(boolean cathedral) {
|
||||
lock.lock();
|
||||
try {
|
||||
return cathedral ? ongoingCathedralType : ongoingChapelType;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void closeOngoingWedding(boolean cathedral) {
|
||||
lock.lock();
|
||||
try {
|
||||
if(cathedral) {
|
||||
ongoingCathedral = null;
|
||||
ongoingCathedralType = null;
|
||||
ongoingCathedralGuests = null;
|
||||
} else {
|
||||
ongoingChapel = null;
|
||||
ongoingChapelType = null;
|
||||
ongoingChapelGuests = null;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setOngoingWedding(final boolean cathedral, Boolean premium, Integer weddingId, Set<Integer> guests) {
|
||||
lock.lock();
|
||||
try {
|
||||
if(cathedral) {
|
||||
ongoingCathedral = weddingId;
|
||||
ongoingCathedralType = premium;
|
||||
ongoingCathedralGuests = guests;
|
||||
} else {
|
||||
ongoingChapel = weddingId;
|
||||
ongoingChapelType = premium;
|
||||
ongoingChapelGuests = guests;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
ongoingStartTime = System.currentTimeMillis();
|
||||
if(weddingId != null) {
|
||||
ScheduledFuture<?> weddingTask = TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
closeOngoingWedding(cathedral);
|
||||
}
|
||||
}, ServerConstants.WEDDING_RESERVATION_TIMEOUT * 60 * 1000);
|
||||
|
||||
if(cathedral) {
|
||||
cathedralReservationTask = weddingTask;
|
||||
} else {
|
||||
chapelReservationTask = weddingTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean acceptOngoingWedding(final boolean cathedral) { // couple succeeded to show up and started the ceremony
|
||||
if(cathedral) {
|
||||
if(cathedralReservationTask == null) return false;
|
||||
|
||||
cathedralReservationTask.cancel(false);
|
||||
cathedralReservationTask = null;
|
||||
} else {
|
||||
if(chapelReservationTask == null) return false;
|
||||
|
||||
chapelReservationTask.cancel(false);
|
||||
chapelReservationTask = null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String getTimeLeft(long futureTime) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
long leftTime = futureTime - System.currentTimeMillis();
|
||||
|
||||
if(leftTime < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte mode = 0;
|
||||
if(leftTime / (60*1000) > 0) {
|
||||
mode++; //counts minutes
|
||||
|
||||
if(leftTime / (60*60*1000) > 0)
|
||||
mode++; //counts hours
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case 2:
|
||||
int hours = (int) ((leftTime / (1000*60*60)));
|
||||
str.append(hours + " hours, ");
|
||||
|
||||
case 1:
|
||||
int minutes = (int) ((leftTime / (1000*60)) % 60);
|
||||
str.append(minutes + " minutes, ");
|
||||
|
||||
default:
|
||||
int seconds = (int) (leftTime / 1000) % 60 ;
|
||||
str.append(seconds + " seconds");
|
||||
}
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public long getWeddingTicketExpireTime(int resSlot) {
|
||||
return ongoingStartTime + getRelativeWeddingTicketExpireTime(resSlot);
|
||||
}
|
||||
|
||||
public static long getRelativeWeddingTicketExpireTime(int resSlot) {
|
||||
return (resSlot * ServerConstants.WEDDING_RESERVATION_INTERVAL * 60 * 1000);
|
||||
}
|
||||
|
||||
public String getWeddingReservationTimeLeft(Integer weddingId) {
|
||||
if(weddingId == null) return null;
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
boolean cathedral = true;
|
||||
|
||||
int resStatus;
|
||||
resStatus = getWeddingReservationStatus(weddingId, true);
|
||||
if(resStatus < 0) {
|
||||
cathedral = false;
|
||||
resStatus = getWeddingReservationStatus(weddingId, false);
|
||||
|
||||
if(resStatus < 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String venue = (cathedral ? "Cathedral" : "Chapel");
|
||||
if(resStatus == 0) {
|
||||
return venue + " - RIGHT NOW";
|
||||
}
|
||||
|
||||
return venue + " - " + getTimeLeft(ongoingStartTime + (resStatus * ServerConstants.WEDDING_RESERVATION_INTERVAL * 60 * 1000)) + " from now";
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getWeddingCoupleForGuest(int guestId, boolean cathedral) {
|
||||
lock.lock();
|
||||
try {
|
||||
return (isOngoingWeddingGuest(cathedral, guestId)) ? Server.getInstance().getWorld(world).getRelationshipCouple(getOngoingWedding(cathedral)) : null;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void dropMessage(int type, String message) {
|
||||
for (MapleCharacter player : getPlayerStorage().getAllCharacters()) {
|
||||
player.dropMessage(type, message);
|
||||
}
|
||||
}
|
||||
|
||||
public void debugMarriageStatus() {
|
||||
System.out.println(" ----- WORLD DATA -----");
|
||||
Server.getInstance().getWorld(world).debugMarriageStatus();
|
||||
|
||||
System.out.println(" ----- CH. " + channel + " -----");
|
||||
System.out.println(" ----- CATHEDRAL -----");
|
||||
System.out.println("Current Queue: " + cathedralReservationQueue);
|
||||
System.out.println("Cancel Task: " + (cathedralReservationTask != null));
|
||||
System.out.println("Ongoing wid: " + ongoingCathedral);
|
||||
System.out.println();
|
||||
System.out.println("Ongoing wid: " + ongoingCathedral + " isPremium: " + ongoingCathedralType);
|
||||
System.out.println("Guest list: " + ongoingCathedralGuests);
|
||||
System.out.println();
|
||||
System.out.println(" ----- CHAPEL -----");
|
||||
System.out.println("Current Queue: " + chapelReservationQueue);
|
||||
System.out.println("Cancel Task: " + (chapelReservationTask != null));
|
||||
System.out.println("Ongoing wid: " + ongoingChapel);
|
||||
System.out.println();
|
||||
System.out.println("Ongoing wid: " + ongoingChapel + " isPremium: " + ongoingChapelType);
|
||||
System.out.println("Guest list: " + ongoingChapelGuests);
|
||||
System.out.println();
|
||||
System.out.println("Starttime: " + ongoingStartTime);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.life.MapleLifeFactory;
|
||||
import server.life.MapleMonster;
|
||||
@@ -39,6 +38,7 @@ import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
|
||||
public final class AdminCommandHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ import net.AbstractMaplePacketHandler;
|
||||
import server.CashShop;
|
||||
import server.CashShop.CashItem;
|
||||
import server.CashShop.CashItemFactory;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
@@ -72,6 +72,11 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
|
||||
if (action == 0x03) { // Item
|
||||
if(ItemConstants.isMapleLife(cItem.getItemId()) && chr.getLevel() < 30) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
Item item = cItem.toItem();
|
||||
cs.addToInventory(item);
|
||||
c.announce(MaplePacketCreator.showBoughtCashItem(item, c.getAccID()));
|
||||
@@ -165,6 +170,9 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
if (chr.getStorage().gainSlots(4)) {
|
||||
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " bought 4 slots to their account storage.\r\n");
|
||||
chr.setUsedStorage();
|
||||
|
||||
c.announce(MaplePacketCreator.showBoughtStorageSlots(chr.getStorage().getSlots()));
|
||||
cs.gainCash(cash, -4000);
|
||||
c.announce(MaplePacketCreator.showCash(chr));
|
||||
@@ -196,6 +204,10 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.showBoughtCharacterSlot(c.getCharacterSlots()));
|
||||
cs.gainCash(cash, -cItem.getPrice());
|
||||
c.announce(MaplePacketCreator.showCash(chr));
|
||||
} else {
|
||||
chr.dropMessage(1, "You have already used up all 12 extra character slots.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
} else if (action == 0x0D) { // Take from Cash Inventory
|
||||
Item item = cs.findByCashId(slea.readInt());
|
||||
@@ -208,15 +220,11 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.takeFromCashInventory(item));
|
||||
|
||||
if(item instanceof Equip) {
|
||||
Equip equip = (Equip) item;
|
||||
if(equip.getRingId() >= 0) {
|
||||
MapleRing ring = MapleRing.loadFromDb(equip.getRingId());
|
||||
if (ring.getItemId() > 1112012) {
|
||||
chr.addFriendshipRing(ring);
|
||||
} else {
|
||||
chr.addCrushRing(ring);
|
||||
}
|
||||
}
|
||||
Equip equip = (Equip) item;
|
||||
if(equip.getRingId() >= 0) {
|
||||
MapleRing ring = MapleRing.loadFromDb(equip.getRingId());
|
||||
chr.addPlayerRing(ring);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (action == 0x0E) { // Put into Cash Inventory
|
||||
@@ -236,8 +244,8 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
mi.removeSlot(item.getPosition());
|
||||
c.announce(MaplePacketCreator.putIntoCashInventory(item, c.getAccID()));
|
||||
} else if (action == 0x1D) { //crush ring (action 28)
|
||||
slea.readInt();//Birthday
|
||||
// if (checkBirthday(c, birthday)) { //We're using a default birthday, so why restrict rings to only people who know of it?
|
||||
int birthday = slea.readInt();
|
||||
if (checkBirthday(c, birthday)) {
|
||||
int toCharge = slea.readInt();
|
||||
int SN = slea.readInt();
|
||||
String recipientName = slea.readMapleAsciiString();
|
||||
@@ -271,9 +279,10 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
partner.showNote();
|
||||
}
|
||||
}
|
||||
/* } else {
|
||||
chr.dropMessage("The birthday you entered was incorrect.");
|
||||
}*/
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
|
||||
} else if (action == 0x20) { // everything is 1 meso...
|
||||
@@ -288,8 +297,8 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
|
||||
} else if (action == 0x23) { //Friendship :3
|
||||
slea.readInt(); //Birthday
|
||||
// if (checkBirthday(c, birthday)) {
|
||||
int birthday = slea.readInt();
|
||||
if (checkBirthday(c, birthday)) {
|
||||
int payment = slea.readByte();
|
||||
slea.skip(3); //0s
|
||||
int snID = slea.readInt();
|
||||
@@ -320,17 +329,18 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
partner.showNote();
|
||||
}
|
||||
}
|
||||
/* } else {
|
||||
chr.dropMessage("The birthday you entered was incorrect.");
|
||||
} */
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
|
||||
} else {
|
||||
System.out.println(slea);
|
||||
System.out.println("Unhandled action: " + action + "\n" + slea);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkBirthday(MapleClient c, int idate) {
|
||||
public static boolean checkBirthday(MapleClient c, int idate) {
|
||||
int year = idate / 10000;
|
||||
int month = (idate - year * 10000) / 100;
|
||||
int day = idate - year * 10000 - month * 100;
|
||||
@@ -339,7 +349,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
cal.set(year, month - 1, day);
|
||||
return c.checkBirthDate(cal);
|
||||
}
|
||||
|
||||
|
||||
public static boolean canBuy(CashItem item, int cash) {
|
||||
return item != null && item.isOnSale() && item.getPrice() <= cash;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MaplePortal;
|
||||
import server.MapleTrade;
|
||||
import server.maps.MapleMap;
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
@@ -61,6 +61,7 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(mc.getId(), mc.getAllBuffs());
|
||||
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(mc.getId(), mc.getAllDiseases());
|
||||
mc.setAwayFromWorld(true);
|
||||
mc.notifyMapTransferToPartner(-1);
|
||||
mc.cancelAllBuffs(true);
|
||||
mc.cancelAllDebuffs();
|
||||
mc.cancelBuffExpireTask();
|
||||
|
||||
@@ -21,10 +21,6 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@@ -33,118 +29,138 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import constants.ServerConstants;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
import client.processor.BuybackProcessor;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import server.MTSItemInfo;
|
||||
import server.maps.FieldLimit;
|
||||
import server.maps.MapleMiniDungeonInfo;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
|
||||
public final class EnterMTSHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
if (!ServerConstants.USE_MTS){
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if(MapleMiniDungeonInfo.isDungeonMap(c.getPlayer().getMapId())) {
|
||||
c.announce(MaplePacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
if (!chr.isAlive()) {
|
||||
|
||||
if(!chr.isAlive() && ServerConstants.USE_BUYBACK_SYSTEM) {
|
||||
BuybackProcessor.processBuyback(c);
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (chr.getLevel() < 10) {
|
||||
c.announce(MaplePacketCreator.blockedMessage2(5));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
chr.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
|
||||
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
|
||||
chr.setAwayFromWorld(true);
|
||||
chr.cancelAllBuffs(true);
|
||||
chr.cancelAllDebuffs();
|
||||
chr.cancelBuffExpireTask();
|
||||
chr.cancelDiseaseExpireTask();
|
||||
chr.cancelSkillCooldownTask();
|
||||
chr.cancelExpirationTask();
|
||||
|
||||
chr.forfeitExpirableQuests();
|
||||
chr.cancelQuestExpirationTask();
|
||||
|
||||
chr.saveToDB();
|
||||
chr.getMap().removePlayer(c.getPlayer());
|
||||
try {
|
||||
c.announce(MaplePacketCreator.openCashShop(c, true));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
chr.getCashShop().open(true);// xD
|
||||
c.announce(MaplePacketCreator.enableCSUse());
|
||||
c.announce(MaplePacketCreator.MTSWantedListingOver(0, 0));
|
||||
c.announce(MaplePacketCreator.showMTSCash(c.getPlayer()));
|
||||
List<MTSItemInfo> items = new ArrayList<>();
|
||||
int pages = 0;
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM mts_items WHERE tab = 1 AND transfer = 0 ORDER BY id DESC LIMIT 16, 16");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
if (rs.getInt("type") != 1) {
|
||||
Item i = new Item(rs.getInt("itemid"), (short) 0, (short) rs.getInt("quantity"));
|
||||
i.setOwner(rs.getString("owner"));
|
||||
items.add(new MTSItemInfo(i, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
} else {
|
||||
Equip equip = new Equip(rs.getInt("itemid"), (byte) rs.getInt("position"), -1);
|
||||
equip.setOwner(rs.getString("owner"));
|
||||
equip.setQuantity((short) 1);
|
||||
equip.setAcc((short) rs.getInt("acc"));
|
||||
equip.setAvoid((short) rs.getInt("avoid"));
|
||||
equip.setDex((short) rs.getInt("dex"));
|
||||
equip.setHands((short) rs.getInt("hands"));
|
||||
equip.setHp((short) rs.getInt("hp"));
|
||||
equip.setInt((short) rs.getInt("int"));
|
||||
equip.setJump((short) rs.getInt("jump"));
|
||||
equip.setVicious((short) rs.getInt("vicious"));
|
||||
equip.setFlag((byte) rs.getInt("flag"));
|
||||
equip.setLuk((short) rs.getInt("luk"));
|
||||
equip.setMatk((short) rs.getInt("matk"));
|
||||
equip.setMdef((short) rs.getInt("mdef"));
|
||||
equip.setMp((short) rs.getInt("mp"));
|
||||
equip.setSpeed((short) rs.getInt("speed"));
|
||||
equip.setStr((short) rs.getInt("str"));
|
||||
equip.setWatk((short) rs.getInt("watk"));
|
||||
equip.setWdef((short) rs.getInt("wdef"));
|
||||
equip.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
|
||||
equip.setLevel((byte) rs.getInt("level"));
|
||||
items.add(new MTSItemInfo((Item) equip, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
}
|
||||
} else {
|
||||
if (!ServerConstants.USE_MTS) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if(MapleMiniDungeonInfo.isDungeonMap(c.getPlayer().getMapId())) {
|
||||
c.announce(MaplePacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
|
||||
ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items");
|
||||
rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
pages = (int) Math.ceil(rs.getInt(1) / 16);
|
||||
if (FieldLimit.CANNOTMIGRATE.check(chr.getMap().getFieldLimit())) {
|
||||
chr.dropMessage(1, "You can't do it here in this map.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (!chr.isAlive()) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (chr.getLevel() < 10) {
|
||||
c.announce(MaplePacketCreator.blockedMessage2(5));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
chr.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
|
||||
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
|
||||
chr.setAwayFromWorld(true);
|
||||
chr.notifyMapTransferToPartner(-1);
|
||||
chr.cancelAllBuffs(true);
|
||||
chr.cancelAllDebuffs();
|
||||
chr.cancelBuffExpireTask();
|
||||
chr.cancelDiseaseExpireTask();
|
||||
chr.cancelSkillCooldownTask();
|
||||
chr.cancelExpirationTask();
|
||||
|
||||
chr.forfeitExpirableQuests();
|
||||
chr.cancelQuestExpirationTask();
|
||||
|
||||
chr.saveToDB();
|
||||
chr.getMap().removePlayer(c.getPlayer());
|
||||
try {
|
||||
c.announce(MaplePacketCreator.openCashShop(c, true));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
chr.getCashShop().open(true);// xD
|
||||
c.announce(MaplePacketCreator.enableCSUse());
|
||||
c.announce(MaplePacketCreator.MTSWantedListingOver(0, 0));
|
||||
c.announce(MaplePacketCreator.showMTSCash(c.getPlayer()));
|
||||
List<MTSItemInfo> items = new ArrayList<>();
|
||||
int pages = 0;
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT * FROM mts_items WHERE tab = 1 AND transfer = 0 ORDER BY id DESC LIMIT 16, 16");
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
if (rs.getInt("type") != 1) {
|
||||
Item i = new Item(rs.getInt("itemid"), (short) 0, (short) rs.getInt("quantity"));
|
||||
i.setOwner(rs.getString("owner"));
|
||||
items.add(new MTSItemInfo(i, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
} else {
|
||||
Equip equip = new Equip(rs.getInt("itemid"), (byte) rs.getInt("position"), -1);
|
||||
equip.setOwner(rs.getString("owner"));
|
||||
equip.setQuantity((short) 1);
|
||||
equip.setAcc((short) rs.getInt("acc"));
|
||||
equip.setAvoid((short) rs.getInt("avoid"));
|
||||
equip.setDex((short) rs.getInt("dex"));
|
||||
equip.setHands((short) rs.getInt("hands"));
|
||||
equip.setHp((short) rs.getInt("hp"));
|
||||
equip.setInt((short) rs.getInt("int"));
|
||||
equip.setJump((short) rs.getInt("jump"));
|
||||
equip.setVicious((short) rs.getInt("vicious"));
|
||||
equip.setFlag((byte) rs.getInt("flag"));
|
||||
equip.setLuk((short) rs.getInt("luk"));
|
||||
equip.setMatk((short) rs.getInt("matk"));
|
||||
equip.setMdef((short) rs.getInt("mdef"));
|
||||
equip.setMp((short) rs.getInt("mp"));
|
||||
equip.setSpeed((short) rs.getInt("speed"));
|
||||
equip.setStr((short) rs.getInt("str"));
|
||||
equip.setWatk((short) rs.getInt("watk"));
|
||||
equip.setWdef((short) rs.getInt("wdef"));
|
||||
equip.setUpgradeSlots((byte) rs.getInt("upgradeslots"));
|
||||
equip.setLevel((byte) rs.getInt("level"));
|
||||
items.add(new MTSItemInfo((Item) equip, rs.getInt("price") + 100 + (int) (rs.getInt("price") * 0.1), rs.getInt("id"), rs.getInt("seller"), rs.getString("sellername"), rs.getString("sell_ends")));
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
|
||||
ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items");
|
||||
rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
pages = (int) Math.ceil(rs.getInt(1) / 16);
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
c.announce(MaplePacketCreator.sendMTS(items, 1, 0, 0, pages));
|
||||
c.announce(MaplePacketCreator.transferInventory(getTransfer(chr.getId())));
|
||||
c.announce(MaplePacketCreator.notYetSoldInv(getNotYetSold(chr.getId())));
|
||||
}
|
||||
c.announce(MaplePacketCreator.sendMTS(items, 1, 0, 0, pages));
|
||||
c.announce(MaplePacketCreator.transferInventory(getTransfer(chr.getId())));
|
||||
c.announce(MaplePacketCreator.notYetSoldInv(getNotYetSold(chr.getId())));
|
||||
}
|
||||
|
||||
private List<MTSItemInfo> getNotYetSold(int cid) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
* @author Jay Estrella
|
||||
*/
|
||||
public final class FamilyAddHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
if (!ServerConstants.USE_FAMILY_SYSTEM){
|
||||
return;
|
||||
|
||||
@@ -21,17 +21,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.autoban.AutobanFactory;
|
||||
import client.command.Commands;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
public final class GeneralChatHandler extends AbstractMaplePacketHandler {
|
||||
private static boolean isCommandIssue(char heading, MapleCharacter chr) {
|
||||
if(chr.gmLevel() > 1 && heading == '!') {
|
||||
return true;
|
||||
@@ -59,7 +60,7 @@ public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
String[] sp = s.split(" ");
|
||||
sp[0] = sp[0].toLowerCase().substring(1);
|
||||
|
||||
if(Commands.executeHeavenMSPlayerCommand(c, sp, heading)) {
|
||||
if(Commands.executeHeavenMsPlayerCommand(c, sp, heading)) {
|
||||
String command = "";
|
||||
for (String used : sp) {
|
||||
command += used + " ";
|
||||
@@ -85,4 +86,3 @@ public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,9 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import net.server.guild.MapleGuildResponse;
|
||||
import net.server.guild.MapleGuildCharacter;
|
||||
import net.server.guild.MapleGuild;
|
||||
import constants.GameConstants;
|
||||
import constants.ServerConstants;
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
@@ -107,8 +108,8 @@ public final class GuildOperationHandler extends AbstractMaplePacketHandler {
|
||||
c.getPlayer().dropMessage(1, "You cannot create a new Guild while in one.");
|
||||
return;
|
||||
}
|
||||
if (mc.getMeso() < MapleGuild.CREATE_GUILD_COST) {
|
||||
c.getPlayer().dropMessage(1, "You do not have enough mesos to create a Guild.");
|
||||
if (mc.getMeso() < ServerConstants.CREATE_GUILD_COST) {
|
||||
c.getPlayer().dropMessage(1, "You do not have " + GameConstants.numberWithCommas(ServerConstants.CREATE_GUILD_COST) + " mesos to create a Guild.");
|
||||
return;
|
||||
}
|
||||
String guildName = slea.readMapleAsciiString();
|
||||
@@ -122,7 +123,7 @@ public final class GuildOperationHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.genericGuildMessage((byte) 0x1c));
|
||||
return;
|
||||
}
|
||||
mc.gainMeso(-MapleGuild.CREATE_GUILD_COST, true, false, true);
|
||||
mc.gainMeso(-ServerConstants.CREATE_GUILD_COST, true, false, true);
|
||||
|
||||
mc.getMGC().setGuildId(gid);
|
||||
Server.getInstance().getGuild(mc.getGuildId(), mc.getWorld(), mc); // initialize guild structure
|
||||
@@ -254,8 +255,8 @@ public final class GuildOperationHandler extends AbstractMaplePacketHandler {
|
||||
System.out.println("[hax] " + mc.getName() + " tried to change guild emblem without being the guild leader.");
|
||||
return;
|
||||
}
|
||||
if (mc.getMeso() < MapleGuild.CHANGE_EMBLEM_COST) {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "You do not have enough mesos to change the Guild emblem."));
|
||||
if (mc.getMeso() < ServerConstants.CHANGE_EMBLEM_COST) {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "You do not have " + GameConstants.numberWithCommas(ServerConstants.CHANGE_EMBLEM_COST) + " mesos to change the Guild emblem."));
|
||||
return;
|
||||
}
|
||||
short bg = slea.readShort();
|
||||
@@ -269,7 +270,7 @@ public final class GuildOperationHandler extends AbstractMaplePacketHandler {
|
||||
Server.getInstance().allianceMessage(alliance.getId(), MaplePacketCreator.getGuildAlliances(alliance, c.getWorld()), -1, -1);
|
||||
}
|
||||
|
||||
mc.gainMeso(-MapleGuild.CHANGE_EMBLEM_COST, true, false, true);
|
||||
mc.gainMeso(-ServerConstants.CHANGE_EMBLEM_COST, true, false, true);
|
||||
respawnPlayer(mc);
|
||||
break;
|
||||
case 0x10:
|
||||
|
||||
@@ -23,7 +23,7 @@ package net.server.channel.handlers;
|
||||
|
||||
import constants.ServerConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import client.MapleCharacter;
|
||||
|
||||
@@ -24,7 +24,7 @@ package net.server.channel.handlers;
|
||||
import client.MapleClient;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import constants.ItemConstants;
|
||||
import java.util.List;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MapleItemInformationProvider.RewardItem;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
@@ -33,7 +33,7 @@ import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
import server.MTSItemInfo;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
@@ -50,6 +50,8 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
// TODO add karma-to-untradeable flag on sold items here
|
||||
|
||||
if (!c.getPlayer().getCashShop().isOpened()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,29 +21,9 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import constants.ItemConstants;
|
||||
import client.MapleClient;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import constants.EquipType;
|
||||
import constants.ServerConstants;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import client.processor.MakerProcessor;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MakerItemFactory;
|
||||
import server.MakerItemFactory.MakerItemCreateEntry;
|
||||
import tools.FilePrinter;
|
||||
import tools.Pair;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
@@ -51,423 +31,9 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
* @author Jay Estrella, Ronan
|
||||
*/
|
||||
public final class MakerSkillHandler extends AbstractMaplePacketHandler {
|
||||
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
int type = slea.readInt();
|
||||
int toCreate = slea.readInt();
|
||||
int toDisassemble = -1, pos = -1;
|
||||
boolean makerSucceeded = true;
|
||||
|
||||
MakerItemCreateEntry recipe;
|
||||
Map<Integer, Short> reagentids = new LinkedHashMap<>();
|
||||
int stimulantid = -1;
|
||||
|
||||
if(type == 3) { // building monster crystal
|
||||
int fromLeftover = toCreate;
|
||||
toCreate = ii.getMakerCrystalFromLeftover(toCreate);
|
||||
if(toCreate == -1) {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal conversion."));
|
||||
return;
|
||||
}
|
||||
|
||||
recipe = MakerItemFactory.generateLeftoverCrystalEntry(fromLeftover);
|
||||
} else if(type == 4) { // disassembling
|
||||
slea.readInt(); // 1... probably inventory type
|
||||
pos = slea.readInt();
|
||||
|
||||
Item it = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((short) pos);
|
||||
if(it != null && it.getItemId() == toCreate) {
|
||||
Pair<Integer, Integer> p;
|
||||
|
||||
if((p = generateDisassemblyInfo(toCreate)) != null) {
|
||||
recipe = MakerItemFactory.generateDisassemblyCrystalEntry(p.getLeft(), p.getRight());
|
||||
toDisassemble = toCreate;
|
||||
toCreate = ii.getMakerCrystalFromEquip(toCreate);
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal disassembly."));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "An unknown error occurred when trying to apply that item for disassembly."));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(ItemConstants.isEquipment(toCreate)) { // only equips uses stimulant and reagents
|
||||
if(slea.readByte() != 0) { // stimulant
|
||||
stimulantid = getMakerStimulant(toCreate);
|
||||
if(!c.getAbstractPlayerInteraction().haveItem(stimulantid)) {
|
||||
stimulantid = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int reagents = Math.min(slea.readInt(), getMakerReagentSlots(toCreate));
|
||||
for(int i = 0; i < reagents; i++) { // crystals
|
||||
int reagentid = slea.readInt();
|
||||
if(ItemConstants.isMakerReagent(reagentid)) {
|
||||
Short rs = reagentids.get(reagentid);
|
||||
if(rs == null) {
|
||||
reagentids.put(reagentid, (short) 1);
|
||||
} else {
|
||||
reagentids.put(reagentid, (short) (rs + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Pair<Integer, Short>> toUpdate = new LinkedList<>();
|
||||
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||
int qty = c.getAbstractPlayerInteraction().getItemQuantity(r.getKey());
|
||||
|
||||
if(qty < r.getValue()) {
|
||||
toUpdate.add(new Pair<>(r.getKey(), (short) qty));
|
||||
}
|
||||
}
|
||||
|
||||
// remove those not present on player inventory
|
||||
if(!toUpdate.isEmpty()) {
|
||||
for(Pair<Integer, Short> rp : toUpdate) {
|
||||
if(rp.getRight() > 0) {
|
||||
reagentids.put(rp.getLeft(), rp.getRight());
|
||||
} else {
|
||||
reagentids.remove(rp.getLeft());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!reagentids.isEmpty()) removeOddMakerReagents(toCreate, reagentids);
|
||||
}
|
||||
|
||||
recipe = MakerItemFactory.getItemCreateEntry(toCreate, stimulantid, reagentids);
|
||||
}
|
||||
|
||||
short createStatus = getCreateStatus(c, recipe);
|
||||
|
||||
switch(createStatus) {
|
||||
case -1:// non-available for Maker itemid has been tried to forge
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS, "Player " + c.getPlayer().getName() + " tried to craft itemid " + toCreate + " using the Maker skill.");
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "The requested item could not be crafted on this operation."));
|
||||
break;
|
||||
|
||||
case 1: // no items
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "You don't have all required items in your inventory to make " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
|
||||
break;
|
||||
|
||||
case 2: // no meso
|
||||
NumberFormat nf = new DecimalFormat("#,###,###,###");
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough mesos (" + nf.format(recipe.getCost()) + ") to complete this operation."));
|
||||
break;
|
||||
|
||||
case 3: // no req level
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough level to complete this operation."));
|
||||
break;
|
||||
|
||||
case 4: // no req skill level
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough Maker level to complete this operation."));
|
||||
break;
|
||||
|
||||
default:
|
||||
if (MapleInventoryManipulator.checkSpace(c, toCreate, (short) recipe.getRewardAmount(), "")) {
|
||||
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
|
||||
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), (short) -p.getRight());
|
||||
}
|
||||
|
||||
if(toDisassemble != -1) {
|
||||
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (short) pos, (short) 1, false);
|
||||
c.announce(MaplePacketCreator.getShowItemGain(toDisassemble, (short) -1, true));
|
||||
}
|
||||
|
||||
int cost = recipe.getCost();
|
||||
if(stimulantid == -1 && reagentids.isEmpty()) {
|
||||
if(cost > 0) c.getPlayer().gainMeso(-cost);
|
||||
|
||||
c.getPlayer().setCS(true);
|
||||
c.getAbstractPlayerInteraction().gainItem(toCreate, (short) recipe.getRewardAmount());
|
||||
c.getPlayer().setCS(false);
|
||||
} else {
|
||||
if(stimulantid != -1) c.getAbstractPlayerInteraction().gainItem(stimulantid, (short) -1);
|
||||
if(!reagentids.isEmpty()) {
|
||||
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||
c.getAbstractPlayerInteraction().gainItem(r.getKey(), (short) (-1 * r.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
if(cost > 0) c.getPlayer().gainMeso(-cost);
|
||||
makerSucceeded = addBoostedMakerItem(c, toCreate, stimulantid, reagentids);
|
||||
}
|
||||
|
||||
if(makerSucceeded) c.announce(MaplePacketCreator.serverNotice(1, "You have successfully created " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
|
||||
else c.getPlayer().dropMessage(5, "The Maker skill lights up, but the skill winds up as if nothing happened.");
|
||||
|
||||
c.announce(MaplePacketCreator.showMakerEffect(makerSucceeded));
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignMakerEffect(c.getPlayer().getId(), makerSucceeded), false);
|
||||
|
||||
if(toCreate == 4260003 && c.getPlayer().getQuestStatus(6033) == 1) {
|
||||
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
|
||||
}
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checks and prevents hackers from PE'ing Maker operations with invalid operations
|
||||
private static void removeOddMakerReagents(int toCreate, Map<Integer, Short> reagentids) {
|
||||
Map<Integer, Integer> reagentType = new LinkedHashMap<>();
|
||||
List<Integer> toRemove = new LinkedList<>();
|
||||
|
||||
boolean isWeapon = ItemConstants.isWeapon(toCreate);
|
||||
|
||||
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||
int curRid = r.getKey();
|
||||
int type = r.getKey() / 100;
|
||||
|
||||
if(type < 42502 && !isWeapon) { // only weapons should gain w.att/m.att from these.
|
||||
toRemove.add(curRid);
|
||||
} else {
|
||||
Integer tableRid = reagentType.get(type);
|
||||
|
||||
if(tableRid != null) {
|
||||
if(tableRid < curRid) {
|
||||
toRemove.add(tableRid);
|
||||
reagentType.put(type, curRid);
|
||||
} else {
|
||||
toRemove.add(curRid);
|
||||
}
|
||||
} else {
|
||||
reagentType.put(type, curRid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// removing less effective gems of repeated type
|
||||
for(Integer i : toRemove) {
|
||||
reagentids.remove(i);
|
||||
}
|
||||
|
||||
// only quantity 1 of each gem will be accepted by the Maker skill
|
||||
for(Integer i : reagentids.keySet()) {
|
||||
reagentids.put(i, (short) 1);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMakerReagentSlots(int itemId) {
|
||||
try {
|
||||
int eqpLevel = ii.getEquipStats(itemId).get("reqLevel");
|
||||
|
||||
if(eqpLevel < 78) {
|
||||
return 1;
|
||||
} else if(eqpLevel >= 78 && eqpLevel < 108) {
|
||||
return 2;
|
||||
} else {
|
||||
return 3;
|
||||
}
|
||||
} catch(NullPointerException npe) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getMakerStimulant(int itemId) {
|
||||
EquipType et = EquipType.getEquipTypeById(itemId);
|
||||
|
||||
switch(et) {
|
||||
case GLOVES:
|
||||
return 4130000;
|
||||
|
||||
case SHOES:
|
||||
return 4130001;
|
||||
|
||||
case SWORD:
|
||||
return 4130002;
|
||||
|
||||
case AXE:
|
||||
return 4130003;
|
||||
|
||||
case MACE:
|
||||
return 4130004;
|
||||
|
||||
case SWORD_2H:
|
||||
return 4130005;
|
||||
|
||||
case AXE_2H:
|
||||
return 4130006;
|
||||
|
||||
case MACE_2H:
|
||||
return 4130007;
|
||||
|
||||
case SPEAR:
|
||||
return 4130008;
|
||||
|
||||
case POLEARM:
|
||||
return 4130009;
|
||||
|
||||
case WAND:
|
||||
return 4130010;
|
||||
|
||||
case STAFF:
|
||||
return 4130011;
|
||||
|
||||
case BOW:
|
||||
return 4130012;
|
||||
|
||||
case CROSSBOW:
|
||||
return 4130013;
|
||||
|
||||
case DAGGER:
|
||||
return 4130014;
|
||||
|
||||
case CLAW:
|
||||
return 4130015;
|
||||
|
||||
case KNUCKLER:
|
||||
return 4130016;
|
||||
|
||||
case PISTOL:
|
||||
return 4130017;
|
||||
|
||||
case CAP:
|
||||
return 4130018;
|
||||
|
||||
case COAT:
|
||||
return 4130019;
|
||||
|
||||
case PANTS:
|
||||
return 4130020;
|
||||
|
||||
case LONGCOAT:
|
||||
return 4130021;
|
||||
|
||||
case SHIELD:
|
||||
return 4130022;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static Pair<Integer, Integer> generateDisassemblyInfo(int itemId) {
|
||||
int recvFee = ii.getMakerDisassembledFee(itemId);
|
||||
if(recvFee > -1) {
|
||||
int recvQty = ii.getMakerDisassembledQuantity(itemId);
|
||||
if(recvQty > 0) {
|
||||
return new Pair<>(recvFee, recvQty);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static short getCreateStatus(MapleClient c, MakerItemCreateEntry recipe) {
|
||||
if(recipe == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!hasItems(c, recipe)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(c.getPlayer().getMeso() < recipe.getCost()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if(c.getPlayer().getLevel() < recipe.getReqLevel()) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if(c.getPlayer().getSkillLevel((c.getPlayer().getJob().getId() / 1000) * 10000000 + 1007) < recipe.getReqSkillLevel()) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static boolean hasItems(MapleClient c, MakerItemCreateEntry recipe) {
|
||||
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
|
||||
int itemId = p.getLeft();
|
||||
if (c.getPlayer().getInventory(ItemConstants.getInventoryType(itemId)).countById(itemId) < p.getRight()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean addBoostedMakerItem(MapleClient c, int itemid, int stimulantid, Map<Integer, Short> reagentids) {
|
||||
if(stimulantid != -1 && !ii.rollSuccessChance(90.0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Item item = ii.getEquipById(itemid);
|
||||
if(item == null) return false;
|
||||
|
||||
Equip eqp = (Equip)item;
|
||||
if(ItemConstants.isAccessory(item.getItemId()) && eqp.getUpgradeSlots() <= 0) eqp.setUpgradeSlots(3);
|
||||
|
||||
if(ServerConstants.USE_ENHANCED_CRAFTING == true) {
|
||||
if(!(c.getPlayer().isGM() && ServerConstants.USE_PERFECT_GM_SCROLL)) {
|
||||
eqp.setUpgradeSlots((byte)(eqp.getUpgradeSlots() + 1));
|
||||
}
|
||||
item = MapleItemInformationProvider.getInstance().scrollEquipWithId(eqp, 2049100, true, 2049100, c.getPlayer().isGM());
|
||||
}
|
||||
|
||||
if(!reagentids.isEmpty()) {
|
||||
Map<String, Integer> stats = new LinkedHashMap<>();
|
||||
List<Short> randOption = new LinkedList<>();
|
||||
List<Short> randStat = new LinkedList<>();
|
||||
|
||||
for(Entry<Integer, Short> r : reagentids.entrySet()) {
|
||||
Pair<String, Integer> reagentBuff = ii.getMakerReagentStatUpgrade(r.getKey());
|
||||
|
||||
if(reagentBuff != null) {
|
||||
String s = reagentBuff.getLeft();
|
||||
|
||||
if(s.substring(0, 4).contains("rand")) {
|
||||
if(s.substring(4).equals("Stat")) {
|
||||
randStat.add((short) (reagentBuff.getRight() * r.getValue()));
|
||||
} else {
|
||||
randOption.add((short) (reagentBuff.getRight() * r.getValue()));
|
||||
}
|
||||
} else {
|
||||
String stat = s.substring(3);
|
||||
|
||||
if(!stat.equals("ReqLevel")) { // improve req level... really?
|
||||
switch (stat) {
|
||||
case "MaxHP":
|
||||
stat = "MHP";
|
||||
break;
|
||||
|
||||
case "MaxMP":
|
||||
stat = "MMP";
|
||||
break;
|
||||
}
|
||||
|
||||
Integer d = stats.get(stat);
|
||||
if(d == null) {
|
||||
stats.put(stat, reagentBuff.getRight() * r.getValue());
|
||||
} else {
|
||||
stats.put(stat, d + (reagentBuff.getRight() * r.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ii.improveEquipStats(eqp, stats);
|
||||
|
||||
for(Short sh : randStat) {
|
||||
ii.scrollOptionEquipWithChaos(eqp, sh, false);
|
||||
}
|
||||
|
||||
for(Short sh : randOption) {
|
||||
ii.scrollOptionEquipWithChaos(eqp, sh, true);
|
||||
}
|
||||
}
|
||||
|
||||
if(stimulantid != -1) {
|
||||
eqp = ii.randomizeUpgradeStats(eqp);
|
||||
}
|
||||
|
||||
MapleInventoryManipulator.addFromDrop(c, item, false, -1);
|
||||
c.announce(MaplePacketCreator.getShowItemGain(itemid, (short) 1, true));
|
||||
return true;
|
||||
MakerProcessor.makerAction(slea, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import server.life.MapleMonster;
|
||||
import server.life.MobAttackInfo;
|
||||
import server.life.MobAttackInfoFactory;
|
||||
//import server.life.MobAttackInfo;
|
||||
//import server.life.MobAttackInfoFactory;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
import server.maps.MapleMapObject;
|
||||
@@ -95,11 +95,19 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
toUse = null;
|
||||
} else if (monster.canUseSkill(toUse)) {
|
||||
toUse.applyEffect(c.getPlayer(), monster, true, banishPlayers);
|
||||
//System.out.println("Applied: " + nextCastSkill + " Level: " + nextCastSkillLevel);
|
||||
}
|
||||
} else {
|
||||
toUse = null;
|
||||
}
|
||||
} else {
|
||||
MobAttackInfo mobAttack = MobAttackInfoFactory.getMobAttackInfo(monster, attackId);
|
||||
//System.out.println("Attacked");
|
||||
long curtime = System.currentTimeMillis();
|
||||
if(curtime >= monster.getNextBasicSkillTime()) { // dont use the special attack too often, chase the player f3
|
||||
//MobAttackInfo mobAttack = MobAttackInfoFactory.getMobAttackInfo(monster, attackId);
|
||||
//monster.setNextBasicSkillTime(curtime);
|
||||
|
||||
toUse = null; // paliative measure for suspicious mob movement
|
||||
} else {
|
||||
toUse = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import client.MapleClient;
|
||||
import java.sql.Connection;
|
||||
|
||||
public final class NoteActionHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
int action = slea.readByte();
|
||||
if (action == 0 && c.getPlayer().getCashShop().getAvailableNotes() > 0) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MapleStatEffect;
|
||||
import tools.Pair;
|
||||
|
||||
@@ -27,9 +27,8 @@ import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.autoban.AutobanManager;
|
||||
import client.inventory.Item;
|
||||
import tools.Randomizer;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
@@ -71,8 +70,13 @@ public final class PetFoodHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
// 50% chance to get +1 closeness
|
||||
pet.gainClosenessFullness(chr, (Randomizer.nextInt(101) <= 50) ? 1 : 0, 30, 1);
|
||||
c.lockClient();
|
||||
try {
|
||||
pet.gainClosenessFullness(chr, (pet.getFullness() <= 75) ? 1 : 0, 30, 1); // 25+ "emptyness" to get +1 closeness
|
||||
} finally {
|
||||
c.unlockClient();
|
||||
}
|
||||
|
||||
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, pos, (short) 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,13 +26,14 @@ import client.MapleClient;
|
||||
import client.autoban.AutobanFactory;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleKarmaManipulator;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MapleTrade;
|
||||
import constants.GameConstants;
|
||||
@@ -407,7 +408,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
|
||||
if (chr.getTrade() != null) {
|
||||
if ((quantity <= item.getQuantity() && quantity >= 0) || ItemConstants.isRechargeable(item.getItemId())) {
|
||||
if (ii.isDropRestricted(item.getItemId())) { // ensure that undroppable items do not make it to the trade window
|
||||
if (!((item.getFlag() & ItemConstants.KARMA) == ItemConstants.KARMA)) {
|
||||
if (!MapleKarmaManipulator.hasKarmaFlag(item)) {
|
||||
c.announce(MaplePacketCreator.serverNotice(1, "That item is untradeable."));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
|
||||
@@ -58,6 +58,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import server.life.MobSkill;
|
||||
import tools.packets.Wedding;
|
||||
|
||||
public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -137,7 +138,9 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
c.announce(MaplePacketCreator.getCharInfo(player));
|
||||
if (!player.isHidden()) {
|
||||
player.toggleHide(true);
|
||||
if(player.isGM() && ServerConstants.USE_AUTOHIDE_GM) {
|
||||
player.toggleHide(true);
|
||||
}
|
||||
}
|
||||
player.sendKeymap();
|
||||
player.sendMacros();
|
||||
@@ -277,6 +280,16 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
player.updateCouponRates();
|
||||
|
||||
player.receivePartyMemberHP();
|
||||
|
||||
if(player.getPartnerId() > 0) {
|
||||
int partnerId = player.getPartnerId();
|
||||
final MapleCharacter partner = c.getWorldServer().getPlayerStorage().getCharacterById(partnerId);
|
||||
|
||||
if(partner != null && !partner.isAwayFromWorld()) {
|
||||
player.announce(Wedding.OnNotifyWeddingPartnerTransfer(partnerId, partner.getMapId()));
|
||||
partner.announce(Wedding.OnNotifyWeddingPartnerTransfer(player.getId(), player.getMapId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void showDueyNotification(MapleClient c, MapleCharacter player) {
|
||||
@@ -286,13 +299,13 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
con = DatabaseConnection.getConnection();
|
||||
ps = con.prepareStatement("SELECT Mesos FROM dueypackages WHERE RecieverId = ? and Checked = 1");
|
||||
ps = con.prepareStatement("SELECT Mesos FROM dueypackages WHERE ReceiverId = ? and Checked = 1");
|
||||
ps.setInt(1, player.getId());
|
||||
rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
try {
|
||||
Connection con2 = DatabaseConnection.getConnection();
|
||||
pss = con2.prepareStatement("UPDATE dueypackages SET Checked = 0 where RecieverId = ?");
|
||||
pss = con2.prepareStatement("UPDATE dueypackages SET Checked = 0 where ReceiverId = ?");
|
||||
pss.setInt(1, player.getId());
|
||||
pss.executeUpdate();
|
||||
pss.close();
|
||||
|
||||
@@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MapleStatEffect;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
@@ -25,86 +25,490 @@ package net.server.channel.handlers;
|
||||
//import java.sql.PreparedStatement;
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.processor.DueyProcessor;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
//import tools.DatabaseConnection;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
//import scripting.npc.NPCScriptManager;
|
||||
import tools.Pair;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.packets.Wedding;
|
||||
import net.server.world.World;
|
||||
import net.server.channel.Channel;
|
||||
import server.MapleItemInformationProvider;
|
||||
import client.MapleRing;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
|
||||
/**
|
||||
* @author Jvlaple
|
||||
* @author Ronan (major overhaul on Ring handling mechanics)
|
||||
*/
|
||||
public final class RingActionHandler extends AbstractMaplePacketHandler {
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
byte mode = slea.readByte();
|
||||
MapleCharacter player = c.getPlayer();
|
||||
switch (mode) {
|
||||
case 0: //Send
|
||||
String partnerName = slea.readMapleAsciiString();
|
||||
MapleCharacter partner = c.getChannelServer().getPlayerStorage().getCharacterByName(partnerName);
|
||||
if (partnerName.equalsIgnoreCase(player.getName())) {
|
||||
c.getPlayer().dropMessage(1, "You cannot put your own name in it.");
|
||||
return;
|
||||
} else if (partner == null) {
|
||||
c.getPlayer().dropMessage(1, partnerName + " was not found on this channel. If you are both logged in, please make sure you are in the same channel.");
|
||||
return;
|
||||
} else if (partner.getGender() == player.getGender()) {
|
||||
c.getPlayer().dropMessage(1, "Your partner is the same gender as you.");
|
||||
return;
|
||||
} //else if (player.isMarried() && partner.isMarried())
|
||||
// NPCScriptManager.getInstance().start(partner.getClient(), 9201002, "marriagequestion", player);
|
||||
break;
|
||||
case 1: //Cancel send
|
||||
c.getPlayer().dropMessage(1, "You've cancelled the request.");
|
||||
boolean accepted = slea.readByte() > 0;
|
||||
String proposerName = slea.readMapleAsciiString();
|
||||
if (accepted) {
|
||||
c.announce(MaplePacketCreator.sendEngagementRequest(proposerName));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
slea.readByte(); //type
|
||||
case 3: //Drop Ring
|
||||
/*
|
||||
if (player.getPartner() != null) {
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
int pid = 0;
|
||||
if (player.getGender() == 0)
|
||||
pid = player.getId();
|
||||
else
|
||||
pid = player.getPartner().getId();//we have an engagements SQL?
|
||||
PreparedStatement ps = con.prepareStatement("DELETE FROM engagements WHERE husbandid = ?");
|
||||
ps.setInt(1, pid);
|
||||
ps.executeUpdate();
|
||||
ps.close();
|
||||
ps = con.prepareStatement("UPDATE characters SET marriagequest = 0 WHERE id = ?, and WHERE id = ?");
|
||||
ps.setInt(1, player.getId());
|
||||
ps.setInt(2, player.getPartner().getId());
|
||||
ps.executeUpdate();
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
c.getPlayer().dropMessage(1, "Your engagement has been broken up.");
|
||||
break;
|
||||
}*/
|
||||
break;
|
||||
case 9: // groom's wishlist
|
||||
int amount = slea.readShort();
|
||||
if (amount > 10) {
|
||||
amount = 10;
|
||||
}
|
||||
String[] items = new String[10];
|
||||
for (int i = 0; i < amount; i++) {
|
||||
items[i] = slea.readMapleAsciiString();
|
||||
}
|
||||
c.announce(MaplePacketCreator.sendGroomWishlist()); //WTF<
|
||||
break;
|
||||
default:
|
||||
System.out.println("NEW RING ACTION " + mode);
|
||||
break;
|
||||
private static int getBoxId(int useItemId) {
|
||||
return useItemId == 2240000 ? 4031357 : (useItemId == 2240001 ? 4031359 : (useItemId == 2240002 ? 4031361 : (useItemId == 2240003 ? 4031363 : (1112300 + (useItemId - 2240004)))));
|
||||
}
|
||||
|
||||
public static void sendEngageProposal(final MapleClient c, final String name, final int itemid) {
|
||||
final int newBoxId = getBoxId(itemid);
|
||||
final MapleCharacter target = c.getChannelServer().getPlayerStorage().getCharacterByName(name);
|
||||
final MapleCharacter source = c.getPlayer();
|
||||
|
||||
// TODO: get the correct packet bytes for these popups
|
||||
if (source.isMarried()) {
|
||||
source.dropMessage(1, "You're already married!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (source.getPartnerId() > 0) {
|
||||
source.dropMessage(1, "You're already engaged!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (source.getMarriageItemId() > 0) {
|
||||
source.dropMessage(1, "You're already engaging someone!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (target == null) {
|
||||
source.dropMessage(1, "Unable to find " + name + " on this channel.");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (target == source) {
|
||||
source.dropMessage(1, "You can't engage yourself.");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if(target.getLevel() < 50) {
|
||||
source.dropMessage(1, "You can only propose to someone level 50 or higher.");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if(source.getLevel() < 50) {
|
||||
source.dropMessage(1, "You can only propose being level 50 or higher.");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (!target.getMap().equals(source.getMap())) {
|
||||
source.dropMessage(1, "Make sure your partner is on the same map!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (!source.haveItem(itemid) || itemid < 2240000 || itemid > 2240015) {
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (target.isMarried()) {
|
||||
source.dropMessage(1, "The player is already married!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (target.getPartnerId() > 0 || target.getMarriageItemId() > 0) {
|
||||
source.dropMessage(1, "The player is already engaged!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (target.getGender() != 1) {
|
||||
source.dropMessage(1, "You may only propose to a girl!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (!MapleInventoryManipulator.checkSpace(c, newBoxId, 1, "")) {
|
||||
source.dropMessage(5, "You don't have a ETC slot available right now!");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
} else if (!MapleInventoryManipulator.checkSpace(target.getClient(), newBoxId + 1, 1, "")) {
|
||||
source.dropMessage(5, "The girl you proposed doesn't have a ETC slot available right now.");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
return;
|
||||
}
|
||||
|
||||
source.setMarriageItemId(itemid);
|
||||
target.announce(Wedding.OnMarriageRequest(source.getName(), source.getId()));
|
||||
}
|
||||
|
||||
private static void eraseEngagementOffline(int characterId) {
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
eraseEngagementOffline(characterId, con);
|
||||
con.close();
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void eraseEngagementOffline(int characterId, Connection con) throws SQLException {
|
||||
PreparedStatement ps = con.prepareStatement("UPDATE characters SET marriageItemId=-1, partnerId=-1 WHERE id=?");
|
||||
ps.setInt(1, characterId);
|
||||
ps.executeUpdate();
|
||||
|
||||
ps.close();
|
||||
}
|
||||
|
||||
private static void breakEngagementOffline(int characterId) {
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("SELECT marriageItemId FROM characters WHERE id=?");
|
||||
ps.setInt(1, characterId);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
if (rs.next()) {
|
||||
int marriageItemId = rs.getInt("marriageItemId");
|
||||
|
||||
if (marriageItemId > 0) {
|
||||
PreparedStatement ps2 = con.prepareStatement("UPDATE inventoryitems SET expiration=0 WHERE itemid=? AND characterid=?");
|
||||
ps2.setInt(1, marriageItemId);
|
||||
ps2.setInt(2, characterId);
|
||||
|
||||
ps2.executeUpdate();
|
||||
ps2.close();
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
|
||||
eraseEngagementOffline(characterId, con);
|
||||
|
||||
con.close();
|
||||
} catch (SQLException ex) {
|
||||
System.out.println("Error updating offline breakup " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void breakMarriage(MapleCharacter chr) {
|
||||
int partnerid = chr.getPartnerId();
|
||||
if(partnerid <= 0) return;
|
||||
|
||||
chr.getClient().getWorldServer().deleteRelationship(chr.getId(), partnerid);
|
||||
MapleRing.removeRing(chr.getMarriageRing());
|
||||
|
||||
MapleCharacter partner = chr.getClient().getWorldServer().getPlayerStorage().getCharacterById(partnerid);
|
||||
if(partner == null) {
|
||||
eraseEngagementOffline(partnerid);
|
||||
} else {
|
||||
partner.dropMessage(5, chr.getName() + " has decided to break up the marriage.");
|
||||
|
||||
//partner.announce(Wedding.OnMarriageResult((byte) 0)); ok, how to gracefully unengage someone without the need to cc?
|
||||
partner.announce(Wedding.OnNotifyWeddingPartnerTransfer(0, 0));
|
||||
resetRingId(partner);
|
||||
partner.setPartnerId(-1);
|
||||
partner.setMarriageItemId(-1);
|
||||
partner.addMarriageRing(null);
|
||||
}
|
||||
|
||||
chr.dropMessage(5, "You have successfully break the marriage with " + MapleCharacter.getNameById(partnerid) + ".");
|
||||
|
||||
//chr.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
chr.announce(Wedding.OnNotifyWeddingPartnerTransfer(0, 0));
|
||||
resetRingId(chr);
|
||||
chr.setPartnerId(-1);
|
||||
chr.setMarriageItemId(-1);
|
||||
chr.addMarriageRing(null);
|
||||
}
|
||||
|
||||
private static void resetRingId(MapleCharacter player) {
|
||||
int ringitemid = player.getMarriageRing().getItemId();
|
||||
|
||||
Item it = player.getInventory(MapleInventoryType.EQUIP).findById(ringitemid);
|
||||
if(it == null) {
|
||||
it = player.getInventory(MapleInventoryType.EQUIPPED).findById(ringitemid);
|
||||
}
|
||||
|
||||
if(it != null) {
|
||||
Equip eqp = (Equip) it;
|
||||
eqp.setRingId(-1);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized static void breakEngagement(MapleCharacter chr) {
|
||||
int partnerid = chr.getPartnerId();
|
||||
int marriageitemid = chr.getMarriageItemId();
|
||||
|
||||
chr.getClient().getWorldServer().deleteRelationship(chr.getId(), partnerid);
|
||||
|
||||
MapleCharacter partner = chr.getClient().getWorldServer().getPlayerStorage().getCharacterById(partnerid);
|
||||
if(partner == null) {
|
||||
breakEngagementOffline(partnerid);
|
||||
} else {
|
||||
partner.dropMessage(5, chr.getName() + " has decided to break up the engagement.");
|
||||
|
||||
int partnerMarriageitemid = marriageitemid + ((chr.getGender() == 0) ? 1 : -1);
|
||||
if(partner.haveItem(partnerMarriageitemid)) {
|
||||
MapleInventoryManipulator.removeById(partner.getClient(), MapleInventoryType.ETC, partnerMarriageitemid, (short) 1, false, false);
|
||||
}
|
||||
|
||||
//partner.announce(Wedding.OnMarriageResult((byte) 0)); ok, how to gracefully unengage someone without the need to cc?
|
||||
partner.announce(Wedding.OnNotifyWeddingPartnerTransfer(0, 0));
|
||||
partner.setPartnerId(-1);
|
||||
partner.setMarriageItemId(-1);
|
||||
}
|
||||
|
||||
if(chr.haveItem(marriageitemid)) {
|
||||
MapleInventoryManipulator.removeById(chr.getClient(), MapleInventoryType.ETC, marriageitemid, (short) 1, false, false);
|
||||
}
|
||||
chr.dropMessage(5, "You have successfully break the engagement with " + MapleCharacter.getNameById(partnerid) + ".");
|
||||
|
||||
//chr.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
chr.announce(Wedding.OnNotifyWeddingPartnerTransfer(0, 0));
|
||||
chr.setPartnerId(-1);
|
||||
chr.setMarriageItemId(-1);
|
||||
}
|
||||
|
||||
public static void breakMarriageRing(MapleCharacter chr, final int wItemId) {
|
||||
final MapleInventoryType type = MapleInventoryType.getByType((byte) (wItemId / 1000000));
|
||||
final Item wItem = chr.getInventory(type).findById(wItemId);
|
||||
final boolean weddingToken = (wItem != null && type == MapleInventoryType.ETC && wItemId / 10000 == 403);
|
||||
final boolean weddingRing = (wItem != null && wItemId / 10 == 111280);
|
||||
|
||||
if (weddingRing) {
|
||||
if(chr.getPartnerId() > 0) {
|
||||
breakMarriage(chr);
|
||||
}
|
||||
|
||||
chr.getMap().disappearingItemDrop(chr, chr, wItem, chr.getPosition());
|
||||
} else if (weddingToken) {
|
||||
if (chr.getPartnerId() > 0) {
|
||||
breakEngagement(chr);
|
||||
}
|
||||
|
||||
chr.getMap().disappearingItemDrop(chr, chr, wItem, chr.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public static void giveMarriageRings(MapleCharacter player, MapleCharacter partner, int marriageRingId) {
|
||||
int ringid = MapleRing.createRing(marriageRingId, player, partner);
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
Item ringObj = ii.getEquipById(marriageRingId);
|
||||
Equip ringEqp = (Equip) ringObj;
|
||||
ringEqp.setRingId(ringid);
|
||||
player.addMarriageRing(MapleRing.loadFromDb(ringid));
|
||||
MapleInventoryManipulator.addFromDrop(player.getClient(), ringEqp, false, -1);
|
||||
player.broadcastMarriageMessage();
|
||||
|
||||
ringObj = ii.getEquipById(marriageRingId);
|
||||
ringEqp = (Equip) ringObj;
|
||||
ringEqp.setRingId(ringid + 1);
|
||||
partner.addMarriageRing(MapleRing.loadFromDb(ringid + 1));
|
||||
MapleInventoryManipulator.addFromDrop(partner.getClient(), ringEqp, false, -1);
|
||||
partner.broadcastMarriageMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
byte mode = slea.readByte();
|
||||
String name;
|
||||
byte slot;
|
||||
switch(mode) {
|
||||
case 0: // Send Proposal
|
||||
sendEngageProposal(c, slea.readMapleAsciiString(), slea.readInt());
|
||||
break;
|
||||
|
||||
case 1: // Cancel Proposal
|
||||
if(c.getPlayer().getMarriageItemId() / 1000000 != 4) {
|
||||
c.getPlayer().setMarriageItemId(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Accept/Deny Proposal
|
||||
final boolean accepted = slea.readByte() > 0;
|
||||
name = slea.readMapleAsciiString();
|
||||
final int id = slea.readInt();
|
||||
|
||||
final MapleCharacter source = c.getWorldServer().getPlayerStorage().getCharacterByName(name);
|
||||
final MapleCharacter target = c.getPlayer();
|
||||
|
||||
if (source == null) {
|
||||
target.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
final int itemid = source.getMarriageItemId();
|
||||
if (target.getPartnerId() > 0 || source.getId() != id || itemid <= 0 || !source.haveItem(itemid) || source.getPartnerId() > 0 || !source.isAlive() || !target.isAlive()) {
|
||||
target.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (accepted) {
|
||||
final int newItemId = getBoxId(itemid);
|
||||
if (!MapleInventoryManipulator.checkSpace(c, newItemId, 1, "") || !MapleInventoryManipulator.checkSpace(source.getClient(), newItemId, 1, "")) {
|
||||
target.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
MapleInventoryManipulator.removeById(source.getClient(), MapleInventoryType.USE, itemid, 1, false, false);
|
||||
|
||||
int marriageId = c.getWorldServer().createRelationship(source.getId(), target.getId());
|
||||
source.setPartnerId(target.getId()); // engage them (new marriageitemid, partnerid for both)
|
||||
target.setPartnerId(source.getId());
|
||||
|
||||
source.setMarriageItemId(newItemId);
|
||||
target.setMarriageItemId(newItemId + 1);
|
||||
|
||||
MapleInventoryManipulator.addById(source.getClient(), newItemId, (short) 1);
|
||||
MapleInventoryManipulator.addById(c, (newItemId + 1), (short) 1);
|
||||
|
||||
source.announce(Wedding.OnMarriageResult(marriageId, source, false));
|
||||
target.announce(Wedding.OnMarriageResult(marriageId, source, false));
|
||||
|
||||
source.announce(Wedding.OnNotifyWeddingPartnerTransfer(target.getId(), target.getMapId()));
|
||||
target.announce(Wedding.OnNotifyWeddingPartnerTransfer(source.getId(), source.getMapId()));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error with engagement " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
source.dropMessage(1, "She has politely declined your engagement request.");
|
||||
source.announce(Wedding.OnMarriageResult((byte) 0));
|
||||
|
||||
source.setMarriageItemId(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // Break Engagement
|
||||
breakMarriageRing(c.getPlayer(), slea.readInt());
|
||||
break;
|
||||
|
||||
case 5: // Invite %s to Wedding
|
||||
name = slea.readMapleAsciiString();
|
||||
int marriageId = slea.readInt();
|
||||
slot = slea.readByte(); // this is an int
|
||||
|
||||
int itemId;
|
||||
try {
|
||||
itemId = c.getPlayer().getInventory(MapleInventoryType.ETC).getItem(slot).getItemId();
|
||||
} catch(NullPointerException npe) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if((itemId != 4031377 && itemId != 4031395) || !c.getPlayer().haveItem(itemId)) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
String groom = c.getPlayer().getName(), bride = MapleCharacter.getNameById(c.getPlayer().getPartnerId());
|
||||
int guest = MapleCharacter.getIdByName(name);
|
||||
if (groom == null || bride == null || groom.equals("") || bride.equals("") || guest <= 0) {
|
||||
c.getPlayer().dropMessage(5, "Unable to find " + name + "!");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
World wserv = c.getWorldServer();
|
||||
Pair<Boolean, Boolean> registration = wserv.getMarriageQueuedLocation(marriageId);
|
||||
|
||||
if(registration != null) {
|
||||
if(wserv.addMarriageGuest(marriageId, guest)) {
|
||||
boolean cathedral = registration.getLeft();
|
||||
int newItemId = cathedral ? 4031407 : 4031406;
|
||||
|
||||
Channel cserv = c.getChannelServer();
|
||||
int resStatus = cserv.getWeddingReservationStatus(marriageId, cathedral);
|
||||
if(resStatus > 0) {
|
||||
long expiration = cserv.getWeddingTicketExpireTime(resStatus + 1);
|
||||
|
||||
MapleCharacter guestChr = c.getWorldServer().getPlayerStorage().getCharacterById(guest);
|
||||
if(guestChr != null && MapleInventoryManipulator.checkSpace(guestChr.getClient(), newItemId, 1, "") && MapleInventoryManipulator.addById(guestChr.getClient(), newItemId, (short) 1, expiration)) {
|
||||
guestChr.dropMessage(6, "[WEDDING] You've been invited to " + groom + " and " + bride + "'s Wedding!");
|
||||
} else {
|
||||
c.getPlayer().sendNote(name, "You've been invited to " + groom + " and " + bride + "'s Wedding! Receive your invitation from Duey!", (byte) 0);
|
||||
|
||||
Item weddingTicket = new Item(newItemId, (short) 0, (short) 1);
|
||||
weddingTicket.setExpiration(expiration);
|
||||
|
||||
DueyProcessor.addItemToDB(weddingTicket, 1, 0, groom, guest);
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(5, "Wedding is already under way. You cannot invite any more guests for the event.");
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(5, "'" + name + "' is already invited for your marriage.");
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(5, "Invitation was not sent to '" + name + "'. Either the time for your marriage reservation already came or it was not found.");
|
||||
}
|
||||
|
||||
} catch (SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
c.getAbstractPlayerInteraction().gainItem(itemId, (short) -1);
|
||||
break;
|
||||
|
||||
case 6: // Open Wedding Invitation
|
||||
slot = (byte) slea.readInt();
|
||||
int invitationid = slea.readInt();
|
||||
|
||||
if(invitationid == 4031406 || invitationid == 4031407) {
|
||||
Item item = c.getPlayer().getInventory(MapleInventoryType.ETC).getItem(slot);
|
||||
if(item == null || item.getItemId() != invitationid) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
// collision case: most soon-to-come wedding will show up
|
||||
Pair<Integer, Integer> coupleId = c.getWorldServer().getWeddingCoupleForGuest(c.getPlayer().getId(), invitationid == 4031407);
|
||||
if (coupleId != null) {
|
||||
int groomId = coupleId.getLeft(), brideId = coupleId.getRight();
|
||||
c.announce(Wedding.sendWeddingInvitation(MapleCharacter.getNameById(groomId), MapleCharacter.getNameById(brideId)));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 9: // Groom and Bride's Wishlist
|
||||
short size = slea.readShort();
|
||||
List<String> itemnames = new ArrayList<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
itemnames.add(slea.readMapleAsciiString());
|
||||
}
|
||||
|
||||
//System.out.println("G&B WISHLIST: " + itemnames);
|
||||
|
||||
/*
|
||||
if (c.getPlayer().getMarriageItemId() > -1) {
|
||||
switch(c.getPlayer().getMarriageItemId()) {
|
||||
case 10: // Premium Cathedral
|
||||
c.getAbstractPlayerInteraction().gainItem(4031375, (short)1);
|
||||
c.getAbstractPlayerInteraction().gainItem(4031395, (short)15);
|
||||
break;
|
||||
case 11: // Normal Cathedral
|
||||
c.getAbstractPlayerInteraction().gainItem(4031480, (short)1);
|
||||
c.getAbstractPlayerInteraction().gainItem(4031395, (short)15);
|
||||
break;
|
||||
case 20: // Premium Chapel
|
||||
c.getAbstractPlayerInteraction().gainItem(4031376, (short)1);
|
||||
c.getAbstractPlayerInteraction().gainItem(4031377, (short)15);
|
||||
break;
|
||||
case 21: // Normal Chapel
|
||||
c.getAbstractPlayerInteraction().gainItem(4031481, (short)1);
|
||||
c.getAbstractPlayerInteraction().gainItem(4031377, (short)15);
|
||||
break;
|
||||
default: {
|
||||
System.out.println("Invalid Wedding Type for player " + c.getPlayer().getName() + "!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//c.getPlayer().setMarriageItemId(-1); ?????
|
||||
}
|
||||
|
||||
if (c.getPlayer().getWishlist() == null) {
|
||||
c.getPlayer().registerWishlist(itemnames);
|
||||
}
|
||||
|
||||
if (c.getPlayer().getWedding() != null) {
|
||||
if (c.getPlayer().getGender() == 0 ? c.getPlayer().getWedding().isExistantGroom(c.getPlayer().getId()) : c.getPlayer().getWedding().isExistantBride(c.getPlayer().getId())) {
|
||||
c.getPlayer().getWedding().registerWishlist(c.getPlayer().getGender() == 1, itemnames);
|
||||
}
|
||||
}
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
System.out.println("Unhandled RING_ACTION Mode: " + slea.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
c.getSession().write(MaplePacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import constants.ItemConstants;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
@@ -107,11 +107,19 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
final List<ModifyInventory> mods = new ArrayList<>();
|
||||
if (scrollSuccess == Equip.ScrollResult.CURSE) {
|
||||
mods.add(new ModifyInventory(3, toScroll));
|
||||
if (dst < 0) {
|
||||
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).removeItem(toScroll.getPosition());
|
||||
if(!ItemConstants.isWeddingRing(toScroll.getItemId())) {
|
||||
mods.add(new ModifyInventory(3, toScroll));
|
||||
if (dst < 0) {
|
||||
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).removeItem(toScroll.getPosition());
|
||||
} else {
|
||||
c.getPlayer().getInventory(MapleInventoryType.EQUIP).removeItem(toScroll.getPosition());
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().getInventory(MapleInventoryType.EQUIP).removeItem(toScroll.getPosition());
|
||||
scrolled = toScroll;
|
||||
scrollSuccess = Equip.ScrollResult.FAIL;
|
||||
|
||||
mods.add(new ModifyInventory(3, scrolled));
|
||||
mods.add(new ModifyInventory(0, scrolled));
|
||||
}
|
||||
} else {
|
||||
mods.add(new ModifyInventory(3, scrolled));
|
||||
|
||||
@@ -29,7 +29,7 @@ import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import java.util.Map;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Randomizer;
|
||||
|
||||
@@ -32,7 +32,7 @@ import net.AbstractMaplePacketHandler;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
|
||||
@@ -21,36 +21,29 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
//import client.MapleCharacter;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
//import client.command.CommandProcessor;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
//import tools.MaplePacketCreator;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
public final class SpouseChatHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
System.out.println(slea.toString());
|
||||
// slea.readMapleAsciiString();//recipient
|
||||
// String msg = slea.readMapleAsciiString();
|
||||
// if (!CommandProcessor.processCommand(c, msg))
|
||||
// if (c.getPlayer().isMarried()) {
|
||||
// MapleCharacter wife = c.getChannelServer().getPlayerStorage().getCharacterById(c.getPlayer().getPartnerId());
|
||||
// if (wife != null) {
|
||||
// wife.getClient().announce(MaplePacketCreator.sendSpouseChat(c.getPlayer(), msg));
|
||||
// c.announce(MaplePacketCreator.sendSpouseChat(c.getPlayer(), msg));
|
||||
// } else
|
||||
// try {
|
||||
// if (c.getChannelServer().getWorldInterface().isConnected(wife.getName())) {
|
||||
// c.getChannelServer().getWorldInterface().sendSpouseChat(c.getPlayer().getName(), wife.getName(), msg);
|
||||
// c.announce(MaplePacketCreator.sendSpouseChat(c.getPlayer(), msg));
|
||||
// } else
|
||||
// c.getPlayer().message("You are either not married or your spouse is currently offline.");
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// c.getPlayer().message("You are either not married or your spouse is currently offline.");
|
||||
// c.getChannelServer().reconnectWorld();
|
||||
// }
|
||||
// }
|
||||
slea.readMapleAsciiString();//recipient
|
||||
String msg = slea.readMapleAsciiString();
|
||||
|
||||
int partnerId = c.getPlayer().getPartnerId();
|
||||
if (partnerId > 0) { // yay marriage
|
||||
MapleCharacter spouse = c.getWorldServer().getPlayerStorage().getCharacterById(partnerId);
|
||||
if (spouse != null) {
|
||||
spouse.announce(MaplePacketCreator.OnCoupleMessage(c.getPlayer().getName(), msg, true));
|
||||
c.announce(MaplePacketCreator.OnCoupleMessage(c.getPlayer().getName(), msg, true));
|
||||
} else {
|
||||
c.getPlayer().dropMessage(5, "Your spouse is currently offline.");
|
||||
}
|
||||
} else {
|
||||
c.getPlayer().dropMessage(5, "You don't have a spouse.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,20 +21,9 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.autoban.AutobanFactory;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
import client.processor.StorageProcessor;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MapleStorage;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
@@ -44,122 +33,6 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
public final class StorageHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
byte mode = slea.readByte();
|
||||
final MapleStorage storage = chr.getStorage();
|
||||
|
||||
if (chr.getLevel() < 15){
|
||||
chr.dropMessage(1, "You may only use the storage once you have reached level 15.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (mode == 4) { // take out
|
||||
byte type = slea.readByte();
|
||||
byte slot = slea.readByte();
|
||||
if (slot < 0 || slot > storage.getSlots()) { // removal starts at zero
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
|
||||
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to work with storage slot " + slot + "\r\n");
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
slot = storage.getSlot(MapleInventoryType.getByType(type), slot);
|
||||
Item item = storage.getItem(slot);
|
||||
if (item != null) {
|
||||
if (MapleItemInformationProvider.getInstance().isPickupRestricted(item.getItemId()) && chr.haveItemWithId(item.getItemId(), true)) {
|
||||
c.announce(MaplePacketCreator.getStorageError((byte) 0x0C));
|
||||
return;
|
||||
}
|
||||
if (chr.getMap().getId() == 910000000) {
|
||||
if (chr.getMeso() < 1000) {
|
||||
c.announce(MaplePacketCreator.getStorageError((byte) 0x0B));
|
||||
return;
|
||||
} else {
|
||||
chr.gainMeso(-1000, false);
|
||||
}
|
||||
}
|
||||
if (MapleInventoryManipulator.checkSpace(c, item.getItemId(), item.getQuantity(), item.getOwner())) {
|
||||
item = storage.takeOut(slot);//actually the same but idc
|
||||
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
|
||||
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " took out " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
|
||||
if ((item.getFlag() & ItemConstants.KARMA) == ItemConstants.KARMA) {
|
||||
item.setFlag((byte) (item.getFlag() ^ ItemConstants.KARMA)); //items with scissors of karma used on them are reset once traded
|
||||
}
|
||||
MapleInventoryManipulator.addFromDrop(c, item, false);
|
||||
storage.sendTakenOut(c, item.getInventoryType());
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.getStorageError((byte) 0x0A));
|
||||
}
|
||||
}
|
||||
} else if (mode == 5) { // store
|
||||
short slot = slea.readShort();
|
||||
int itemId = slea.readInt();
|
||||
short quantity = slea.readShort();
|
||||
MapleInventoryType slotType = ItemConstants.getInventoryType(itemId);
|
||||
MapleInventory Inv = chr.getInventory(slotType);
|
||||
if (slot < 1 || slot > Inv.getSlotLimit()) { //player inv starts at one
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
|
||||
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to store item at slot " + slot + "\r\n");
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
if (quantity < 1 || chr.getItemQuantity(itemId, false) < quantity) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (storage.isFull()) {
|
||||
c.announce(MaplePacketCreator.getStorageError((byte) 0x11));
|
||||
return;
|
||||
}
|
||||
short meso = (short) (chr.getMap().getId() == 910000000 ? -500 : -100);
|
||||
if (chr.getMeso() < meso) {
|
||||
c.announce(MaplePacketCreator.getStorageError((byte) 0x0B));
|
||||
} else {
|
||||
MapleInventoryType invType = ItemConstants.getInventoryType(itemId);
|
||||
Item item = chr.getInventory(invType).getItem(slot).copy();
|
||||
if (item.getItemId() == itemId && (item.getQuantity() >= quantity || ItemConstants.isRechargeable(itemId))) {
|
||||
if (ItemConstants.isRechargeable(itemId)) {
|
||||
quantity = item.getQuantity();
|
||||
}
|
||||
chr.gainMeso(meso, false, true, false);
|
||||
MapleInventoryManipulator.removeFromSlot(c, invType, slot, quantity, false);
|
||||
item.setQuantity(quantity);
|
||||
storage.store(item);
|
||||
storage.sendStored(c, ItemConstants.getInventoryType(itemId));
|
||||
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
|
||||
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " stored " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
|
||||
}
|
||||
}
|
||||
} else if (mode == 6) { // arrange items
|
||||
if(ServerConstants.USE_STORAGE_ITEM_SORT) storage.arrangeItems(c);
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
} else if (mode == 7) { // meso
|
||||
int meso = slea.readInt();
|
||||
int storageMesos = storage.getMeso();
|
||||
int playerMesos = chr.getMeso();
|
||||
if ((meso > 0 && storageMesos >= meso) || (meso < 0 && playerMesos >= -meso)) {
|
||||
if (meso < 0 && (storageMesos - meso) < 0) {
|
||||
meso = -2147483648 + storageMesos;
|
||||
if (meso < playerMesos) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
} else if (meso > 0 && (playerMesos + meso) < 0) {
|
||||
meso = 2147483647 - playerMesos;
|
||||
if (meso > storageMesos) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
}
|
||||
storage.setMeso(storageMesos - meso);
|
||||
chr.gainMeso(meso, false, true, false);
|
||||
FilePrinter.print(FilePrinter.STORAGE + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + (meso > 0 ? " took out " : " stored ") + Math.abs(meso) + " mesos\r\n");
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
storage.sendMeso(c);
|
||||
} else if (mode == 8) {// close
|
||||
storage.close();
|
||||
}
|
||||
StorageProcessor.storageAction(slea, c);
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleStatEffect;
|
||||
import server.life.MapleLifeFactory.loseItem;
|
||||
import server.life.MapleMonster;
|
||||
|
||||
46
src/net/server/channel/handlers/TransferNameHandler.java
Normal file
46
src/net/server/channel/handlers/TransferNameHandler.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public final class TransferNameHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.readInt(); //cid
|
||||
int birthday = slea.readInt();
|
||||
if (!CashOperationHandler.checkBirthday(c, birthday)) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.sendNameTransferRules(4));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
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)));
|
||||
}
|
||||
}
|
||||
46
src/net/server/channel/handlers/TransferWorldHandler.java
Normal file
46
src/net/server/channel/handlers/TransferWorldHandler.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public final class TransferWorldHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.readInt(); //cid
|
||||
int birthday = slea.readInt();
|
||||
if (!CashOperationHandler.checkBirthday(c, birthday)) {
|
||||
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.sendWorldTransferRules(9));
|
||||
}
|
||||
}
|
||||
@@ -27,12 +27,15 @@ import client.MapleJob;
|
||||
import client.MapleStat;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import client.creator.veteran.*;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Equip.ScrollResult;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleKarmaManipulator;
|
||||
import constants.GameConstants;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
@@ -45,7 +48,6 @@ import java.util.List;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import scripting.npc.NPCScriptManager;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.MapleShop;
|
||||
import server.MapleShopFactory;
|
||||
@@ -64,12 +66,15 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
final MapleCharacter player = c.getPlayer();
|
||||
if (System.currentTimeMillis() - player.getLastUsedCashItem() < 3000) {
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
if (timeNow - player.getLastUsedCashItem() < 3000) {
|
||||
player.dropMessage(1, "You have used a cash item recently. Wait a moment, then try again.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
player.setLastUsedCashItem(System.currentTimeMillis());
|
||||
player.setLastUsedCashItem(timeNow);
|
||||
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
slea.readShort();
|
||||
int itemId = slea.readInt();
|
||||
@@ -389,7 +394,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
||||
if (item == null) //hack
|
||||
{
|
||||
return;
|
||||
} else if (((item.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE) || ii.isDropRestricted(item.getItemId())) {
|
||||
} else if (((item.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE) || (ii.isDropRestricted(item.getItemId()) && !MapleKarmaManipulator.hasKarmaFlag(item))) {
|
||||
player.dropMessage(1, "You cannot trade this item.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
@@ -511,6 +516,56 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
}, 1000 * 10);
|
||||
remove(c, itemId);
|
||||
} else if (itemType == 543) {
|
||||
if(itemId == 5432000 && !c.gainCharacterSlot()) {
|
||||
player.dropMessage(1, "You have already used up all 12 extra character slots.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
String name = slea.readMapleAsciiString();
|
||||
int face = slea.readInt();
|
||||
int hair = slea.readInt();
|
||||
int haircolor = slea.readInt();
|
||||
int skin = slea.readInt();
|
||||
int gender = slea.readInt();
|
||||
int jobid = slea.readInt();
|
||||
int improveSp = slea.readInt();
|
||||
|
||||
int createStatus;
|
||||
switch(jobid) {
|
||||
case 0:
|
||||
createStatus = WarriorCreator.createCharacter(c, name, face, hair + haircolor, skin, gender, improveSp);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
createStatus = MagicianCreator.createCharacter(c, name, face, hair + haircolor, skin, gender, improveSp);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
createStatus = BowmanCreator.createCharacter(c, name, face, hair + haircolor, skin, gender, improveSp);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
createStatus = ThiefCreator.createCharacter(c, name, face, hair + haircolor, skin, gender, improveSp);
|
||||
break;
|
||||
|
||||
default:
|
||||
createStatus = PirateCreator.createCharacter(c, name, face, hair + haircolor, skin, gender, improveSp);
|
||||
}
|
||||
|
||||
if(createStatus == 0) {
|
||||
c.announce(MaplePacketCreator.sendMapleLifeError(0)); // success!
|
||||
|
||||
player.showHint("#bSuccess#k on creation of the new character through the Maple Life card.");
|
||||
remove(c, itemId);
|
||||
} else {
|
||||
if(createStatus == -1) { // check name
|
||||
c.announce(MaplePacketCreator.sendMapleLifeNameError());
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.sendMapleLifeError(-1 * createStatus));
|
||||
}
|
||||
}
|
||||
} else if (itemType == 545) { // MiuMiu's travel store
|
||||
if (player.getShop() == null) {
|
||||
MapleShop shop = MapleShopFactory.getInstance().getShop(1338);
|
||||
@@ -527,14 +582,18 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
|
||||
MapleInventoryType type = MapleInventoryType.getByType((byte) slea.readInt());
|
||||
short slot = (short) slea.readInt();
|
||||
Item item = c.getPlayer().getInventory(type).getItem(slot);
|
||||
if (item == null || item.getQuantity() <= 0 || (item.getFlag() & ItemConstants.KARMA) > 0 && ii.isKarmaAble(item.getItemId())) {
|
||||
if (item == null || item.getQuantity() <= 0 || MapleKarmaManipulator.hasKarmaFlag(item) || !ii.isKarmaAble(item.getItemId())) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (!type.equals(MapleInventoryType.USE)) {
|
||||
item.setFlag((byte) ItemConstants.KARMA);
|
||||
|
||||
if(MapleKarmaManipulator.hasUsedKarmaFlag(item)) {
|
||||
c.getPlayer().dropMessage(6, "Scissors of Karma was already used on this item.");
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
MapleKarmaManipulator.setKarmaFlag(item);
|
||||
c.getPlayer().forceUpdateItem(item);
|
||||
remove(c, itemId);
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
|
||||
@@ -27,7 +27,7 @@ import client.inventory.MapleInventoryType;
|
||||
import client.autoban.AutobanManager;
|
||||
import constants.ItemConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.life.MapleMonster;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
@@ -29,7 +29,7 @@ import client.inventory.MapleInventoryType;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
@@ -21,6 +19,7 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
@@ -28,10 +27,28 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jay Estrella
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class UseMapleLifeHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
c.announce(MaplePacketCreator.charNameResponse(slea.readMapleAsciiString(), false));
|
||||
MapleCharacter player = c.getPlayer();
|
||||
long timeNow = System.currentTimeMillis();
|
||||
|
||||
if(timeNow - player.getLastUsedCashItem() < 3000) {
|
||||
player.dropMessage(5, "Please wait a moment before trying again.");
|
||||
c.announce(MaplePacketCreator.sendMapleLifeError(3));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
player.setLastUsedCashItem(timeNow);
|
||||
|
||||
String name = slea.readMapleAsciiString();
|
||||
if(MapleCharacter.canCreateChar(name)) {
|
||||
c.announce(MaplePacketCreator.sendMapleLifeCharacterInfo());
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.sendMapleLifeNameError());
|
||||
}
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,30 +22,51 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleMount;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import constants.ExpTable;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
* @author PurpleMadness
|
||||
* @author Ronan
|
||||
*/
|
||||
public final class UseMountFoodHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
slea.skip(6);
|
||||
slea.skip(4);
|
||||
short pos = slea.readShort();
|
||||
int itemid = slea.readInt();
|
||||
if (c.getPlayer().getInventory(MapleInventoryType.USE).findById(itemid) != null) {
|
||||
if (c.getPlayer().getMount() != null && c.getPlayer().getMount().getTiredness() > 0) {
|
||||
c.getPlayer().getMount().setTiredness(Math.max(c.getPlayer().getMount().getTiredness() - 30, 0));
|
||||
c.getPlayer().getMount().setExp(2 * c.getPlayer().getMount().getLevel() + 6 + c.getPlayer().getMount().getExp());
|
||||
int level = c.getPlayer().getMount().getLevel();
|
||||
boolean levelup = c.getPlayer().getMount().getExp() >= ExpTable.getMountExpNeededForLevel(level) && level < 31;
|
||||
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
MapleMount mount = chr.getMount();
|
||||
Item item = chr.getInventory(MapleInventoryType.USE).getItem(pos);
|
||||
if (item != null && item.getItemId() == itemid && mount != null) {
|
||||
float healedFactor;
|
||||
c.lockClient();
|
||||
try {
|
||||
int curTiredness = mount.getTiredness();
|
||||
int healedTiredness = Math.min(curTiredness, 30);
|
||||
|
||||
healedFactor = (float) healedTiredness / 30;
|
||||
mount.setTiredness(curTiredness - healedTiredness);
|
||||
} finally {
|
||||
c.unlockClient();
|
||||
}
|
||||
|
||||
if (healedFactor > 0.0f) {
|
||||
mount.setExp(mount.getExp() + (int) Math.ceil(healedFactor * (2 * mount.getLevel() + 6)));
|
||||
int level = mount.getLevel();
|
||||
boolean levelup = mount.getExp() >= ExpTable.getMountExpNeededForLevel(level) && level < 31;
|
||||
if (levelup) {
|
||||
c.getPlayer().getMount().setLevel(level + 1);
|
||||
mount.setLevel(level + 1);
|
||||
}
|
||||
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.updateMount(c.getPlayer().getId(), c.getPlayer().getMount(), levelup));
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.updateMount(chr.getId(), mount, levelup));
|
||||
MapleInventoryManipulator.removeById(c, MapleInventoryType.USE, itemid, 1, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import client.MapleClient;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
@@ -26,7 +26,7 @@ import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import tools.Randomizer;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import server.MapleInventoryManipulator;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.life.MapleLifeFactory;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
@@ -1,39 +1,93 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import constants.ItemConstants;
|
||||
import tools.DatabaseConnection;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import tools.packets.Wedding;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Kevin
|
||||
* @author Eric
|
||||
*/
|
||||
public class WeddingHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
//System.out.println("Wedding Packet: " + slea);
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
byte operation = slea.readByte();
|
||||
switch (operation) {
|
||||
case 0x06://Add an item to the Wedding Registry
|
||||
short slot = slea.readShort();
|
||||
int itemid = slea.readInt();
|
||||
short quantity = slea.readShort();
|
||||
MapleInventoryType type = ItemConstants.getInventoryType(itemid);
|
||||
Item item = chr.getInventory(type).getItem(slot);
|
||||
if (itemid == item.getItemId() && quantity <= item.getQuantity()) {
|
||||
c.announce(MaplePacketCreator.addItemToWeddingRegistry(chr, item));
|
||||
public final class WeddingHandler extends AbstractMaplePacketHandler {
|
||||
/*
|
||||
public static final void OnWeddingProgress(byte action, MapleClient c) {
|
||||
// -- Pelvis Bebop:
|
||||
// 0x00: "We are gathered here today..."
|
||||
// 0x01: "Very well! I pronounce you..."
|
||||
// 0x02: "You two truly are a sight to..."
|
||||
// 0x03: Wedding Ceremony Ended, initialize the Wedding Effect upon the two married characters
|
||||
// -- High Priest John: (Unknown action bytes)
|
||||
// 0x00: " "
|
||||
// 0x01: " "
|
||||
// 0x02: "Do you wish to bless this couple?..."
|
||||
// 0x03: Wedding Ceremony Ended, initialize the Wedding Effect upon the two married characters
|
||||
if (c.getPlayer().getWedding() != null) {
|
||||
if (c.getPlayer().getGender() == 0 ? c.getPlayer().getWedding().isExistantGroom(c.getPlayer().getId()) : c.getPlayer().getWedding().isExistantBride(c.getPlayer().getId())) {
|
||||
c.getPlayer().getMap().broadcastMessage(Wedding.OnWeddingProgress(action == 2, c.getPlayer().getId(), c.getPlayer().getPartnerId(), (byte)(action+1)));
|
||||
c.getPlayer().getWedding().incrementStage();
|
||||
c.getPlayer().getPartner().getWedding().incrementStage(); // pls don't b a bitch and throw npe ):<
|
||||
if (action == 2) {
|
||||
c.getPlayer().setMarried(true);
|
||||
c.getChannelServer().getPlayerStorage().getCharacterById(c.getPlayer().getPartnerId()).setMarried(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
|
||||
public static final void OnWeddingGiftResult(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
System.out.println("New WEDDING_GIFT_RESULT: " + slea.toString());
|
||||
byte mode = slea.readByte();
|
||||
switch(mode) {
|
||||
case 0x06: // "SEND ITEM"
|
||||
short slot = slea.readShort(); // isn't this a byte? o.O
|
||||
int itemId = slea.readInt();
|
||||
short quantity = slea.readShort();
|
||||
if (c.getPlayer().getInventory(ItemConstants.getInventoryType(itemId)).getItem((byte)slot).getItemId() == itemId && c.getPlayer().getInventory(InventoryConstants.getInventoryType(itemId)).getItem((byte)slot).getQuantity() >= quantity) {
|
||||
if (c.getPlayer().getWedding() == null) {
|
||||
c.getPlayer().startWedding(); // TODO
|
||||
}
|
||||
List<String> itemnames = new ArrayList<>();
|
||||
Item item = c.getPlayer().getInventory(ItemConstants.getInventoryType(itemId)).getItem((byte)slot);
|
||||
boolean bride = false;
|
||||
c.getPlayer().getWedding().registerWishlistItem(item, bride);
|
||||
c.announce(Wedding.OnWeddingGiftResult((byte)11, itemnames, c.getPlayer().getWedding().getWishlistItems(bride))); // todo: remove item from inventory if success
|
||||
}
|
||||
case 0x08: // "EXIT"
|
||||
if (slea.available() != 0) {
|
||||
System.out.println("WEDDING_GIFT_RESULT: " + slea.toString());
|
||||
}
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
break;
|
||||
default: {
|
||||
System.out.println("Unknown Mode Found: " + mode + " : " + slea.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
53
src/net/server/channel/handlers/WeddingTalkHandler.java
Normal file
53
src/net/server/channel/handlers/WeddingTalkHandler.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import tools.packets.Wedding;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public final class WeddingTalkHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
byte action = slea.readByte();
|
||||
if(action == 1) {
|
||||
EventInstanceManager eim = c.getPlayer().getEventInstance();
|
||||
|
||||
if(eim != null && !(c.getPlayer().getId() == eim.getIntProperty("groomId") || c.getPlayer().getId() == eim.getIntProperty("brideId"))) {
|
||||
c.announce(Wedding.OnWeddingProgress(false, 0, 0, (byte) 2));
|
||||
} else {
|
||||
c.announce(Wedding.OnWeddingProgress(true, 0, 0, (byte) 3));
|
||||
}
|
||||
} else {
|
||||
c.announce(Wedding.OnWeddingProgress(true, 0, 0, (byte) 3));
|
||||
}
|
||||
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
47
src/net/server/channel/handlers/WeddingTalkMoreHandler.java
Normal file
47
src/net/server/channel/handlers/WeddingTalkMoreHandler.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2016 - 2018 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import scripting.event.EventInstanceManager;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import tools.packets.Wedding;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public final class WeddingTalkMoreHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
EventInstanceManager eim = c.getPlayer().getEventInstance();
|
||||
if(eim != null && !(c.getPlayer().getId() == eim.getIntProperty("groomId") || c.getPlayer().getId() == eim.getIntProperty("brideId"))) {
|
||||
eim.gridInsert(c.getPlayer(), 1);
|
||||
c.getPlayer().dropMessage(5, "High Priest John: Your blessings have been added to their love. What a noble act for a lovely couple!");
|
||||
}
|
||||
|
||||
c.announce(Wedding.OnWeddingProgress(true, 0, 0, (byte) 3));
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
@@ -45,9 +45,7 @@ import tools.MaplePacketCreator;
|
||||
import tools.locks.MonitoredLockType;
|
||||
|
||||
public class MapleGuild {
|
||||
public final static int CREATE_GUILD_COST = 1500000;
|
||||
public final static int CHANGE_EMBLEM_COST = 5000000;
|
||||
|
||||
|
||||
private enum BCOp {
|
||||
NONE, DISBAND, EMBLEMCHANGE
|
||||
}
|
||||
|
||||
@@ -21,20 +21,12 @@
|
||||
*/
|
||||
package net.server.handlers.login;
|
||||
|
||||
import client.MapleClient;
|
||||
import client.creator.novice.*;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.MapleJob;
|
||||
import client.MapleSkinColor;
|
||||
import client.autoban.AutobanFactory;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
|
||||
public final class CreateCharHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -60,83 +52,43 @@ public final class CreateCharHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
String name = slea.readMapleAsciiString();
|
||||
if (!MapleCharacter.canCreateChar(name)) {
|
||||
return;
|
||||
}
|
||||
MapleCharacter newchar = MapleCharacter.getDefault(c);
|
||||
newchar.setWorld(c.getWorld());
|
||||
|
||||
int job = slea.readInt();
|
||||
String name = slea.readMapleAsciiString();
|
||||
int job = slea.readInt();
|
||||
int face = slea.readInt();
|
||||
|
||||
int hair = slea.readInt();
|
||||
int hairColor = slea.readInt();
|
||||
int haircolor = slea.readInt();
|
||||
int skincolor = slea.readInt();
|
||||
|
||||
newchar.setSkinColor(MapleSkinColor.getById(skincolor));
|
||||
int top = slea.readInt();
|
||||
int bottom = slea.readInt();
|
||||
int shoes = slea.readInt();
|
||||
int weapon = slea.readInt();
|
||||
newchar.setGender(slea.readByte());
|
||||
newchar.setName(name);
|
||||
newchar.setHair(hair + hairColor);
|
||||
newchar.setFace(face);
|
||||
|
||||
int [] items = new int [] {weapon, top, bottom, shoes, hair, face};
|
||||
int gender = slea.readByte();
|
||||
|
||||
int [] items = new int [] {weapon, top, bottom, shoes, hair, face};
|
||||
for (int i = 0; i < items.length; i++){
|
||||
if (!isLegal(items[i])) {
|
||||
AutobanFactory.PACKET_EDIT.alert(newchar, name + " tried to packet edit in character creation.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + newchar + ".txt", "Tried to packet edit in char creation.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + name + ".txt", "Owner from account '" + c.getAccountName() + "' tried to packet edit in char creation.");
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (job == 0) { // Knights of Cygnus
|
||||
newchar.setJob(MapleJob.NOBLESSE);
|
||||
newchar.setMapId(130030000);
|
||||
newchar.getInventory(MapleInventoryType.ETC).addItem(new Item(4161047, (short) 0, (short) 1));
|
||||
|
||||
int status;
|
||||
if (job == 0) { // Knights of Cygnus
|
||||
status = NoblesseCreator.createCharacter(c, name, face, hair + haircolor, skincolor, top, bottom, shoes, weapon, gender);
|
||||
} else if (job == 1) { // Adventurer
|
||||
newchar.setJob(MapleJob.BEGINNER);
|
||||
newchar.setMapId(/*specialJobType == 2 ? 3000600 : */10000);
|
||||
newchar.getInventory(MapleInventoryType.ETC).addItem(new Item(4161001, (short) 0, (short) 1));
|
||||
status = BeginnerCreator.createCharacter(c, name, face, hair + haircolor, skincolor, top, bottom, shoes, weapon, gender);
|
||||
} else if (job == 2) { // Aran
|
||||
newchar.setJob(MapleJob.LEGEND);
|
||||
newchar.setMapId(914000000);
|
||||
newchar.getInventory(MapleInventoryType.ETC).addItem(new Item(4161048, (short) 0, (short) 1));
|
||||
status = LegendCreator.createCharacter(c, name, face, hair + haircolor, skincolor, top, bottom, shoes, weapon, gender);
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.deleteCharResponse(0, 9));
|
||||
return;
|
||||
}
|
||||
|
||||
MapleInventory equipped = newchar.getInventory(MapleInventoryType.EQUIPPED);
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
Item eq_top = ii.getEquipById(top);
|
||||
eq_top.setPosition((byte) -5);
|
||||
equipped.addFromDB(eq_top);
|
||||
|
||||
Item eq_bottom = ii.getEquipById(bottom);
|
||||
eq_bottom.setPosition((byte) -6);
|
||||
equipped.addFromDB(eq_bottom);
|
||||
|
||||
Item eq_shoes = ii.getEquipById(shoes);
|
||||
eq_shoes.setPosition((byte) -7);
|
||||
equipped.addFromDB(eq_shoes);
|
||||
|
||||
Item eq_weapon = ii.getEquipById(weapon);
|
||||
eq_weapon.setPosition((byte) -11);
|
||||
equipped.addFromDB(eq_weapon.copy());
|
||||
|
||||
if (!newchar.insertNewChar()) {
|
||||
c.announce(MaplePacketCreator.deleteCharResponse(0, 9));
|
||||
return;
|
||||
}
|
||||
c.announce(MaplePacketCreator.addNewCharEntry(newchar));
|
||||
|
||||
Server.getInstance().createCharacterid(newchar.getAccountID(), newchar.getId(), newchar.getWorld());
|
||||
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.sendYellowTip("[NEW CHAR]: " + c.getAccountName() + " has created a new character with IGN " + name));
|
||||
if (status == -2) {
|
||||
c.announce(MaplePacketCreator.deleteCharResponse(0, 9));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
@@ -42,6 +43,8 @@ public final class ViewCharHandler extends AbstractMaplePacketHandler {
|
||||
List<Integer> worlds;
|
||||
List<MapleCharacter> chars;
|
||||
|
||||
int wlen = Server.getInstance().getWorlds().size();
|
||||
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT world, id FROM characters WHERE accountid = ?")) {
|
||||
ps.setInt(1, c.getAccID());
|
||||
@@ -51,6 +54,8 @@ public final class ViewCharHandler extends AbstractMaplePacketHandler {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
int cworld = rs.getByte("world");
|
||||
if(cworld >= wlen) continue;
|
||||
|
||||
boolean inside = false;
|
||||
for (int w : worlds) {
|
||||
if (w == cworld) {
|
||||
|
||||
56
src/net/server/worker/WeddingReservationWorker.java
Normal file
56
src/net/server/worker/WeddingReservationWorker.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2017 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package net.server.worker;
|
||||
|
||||
import java.util.Set;
|
||||
import net.server.world.World;
|
||||
import net.server.channel.Channel;
|
||||
import tools.Pair;
|
||||
|
||||
/**
|
||||
* @author Ronan
|
||||
*/
|
||||
public class WeddingReservationWorker extends BaseWorker implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for(Channel ch : wserv.getChannels()) {
|
||||
Pair<Boolean, Pair<Integer, Set<Integer>>> wedding;
|
||||
|
||||
wedding = ch.getNextWeddingReservation(true); // start cathedral
|
||||
if(wedding != null) {
|
||||
ch.setOngoingWedding(true, wedding.getLeft(), wedding.getRight().getLeft(), wedding.getRight().getRight());
|
||||
} else {
|
||||
ch.setOngoingWedding(true, null, null, null);
|
||||
}
|
||||
|
||||
wedding = ch.getNextWeddingReservation(false); // start chapel
|
||||
if(wedding != null) {
|
||||
ch.setOngoingWedding(false, wedding.getLeft(), wedding.getRight().getLeft(), wedding.getRight().getRight());
|
||||
} else {
|
||||
ch.setOngoingWedding(false, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WeddingReservationWorker(World world) {
|
||||
super(world);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,9 @@ import constants.ServerConstants;
|
||||
import java.sql.Connection;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -59,6 +61,7 @@ import net.server.worker.CharacterAutosaverWorker;
|
||||
import net.server.worker.MountTirednessWorker;
|
||||
import net.server.worker.PetFullnessWorker;
|
||||
import net.server.worker.TimedMapObjectWorker;
|
||||
import net.server.worker.WeddingReservationWorker;
|
||||
import net.server.PlayerStorage;
|
||||
import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
@@ -82,13 +85,18 @@ public class World {
|
||||
private String eventmsg;
|
||||
private List<Channel> channels = new ArrayList<>();
|
||||
private Map<Integer, Byte> pnpcStep = new HashMap<>();
|
||||
private Map<Integer, Short> pnpcPodium = new HashMap<>();
|
||||
private Map<Integer, MapleMessenger> messengers = new HashMap<>();
|
||||
private AtomicInteger runningMessengerId = new AtomicInteger();
|
||||
private Map<Integer, MapleFamily> families = new LinkedHashMap<>();
|
||||
private Map<Integer, Integer> relationships = new HashMap<>();
|
||||
private Map<Integer, Pair<Integer, Integer>> relationshipCouples = new HashMap<>();
|
||||
private Map<Integer, MapleGuildSummary> gsStore = new HashMap<>();
|
||||
private PlayerStorage players = new PlayerStorage();
|
||||
|
||||
private Set<Integer> queuedGuilds = new HashSet<>();
|
||||
private Map<Integer, Pair<Pair<Boolean, Boolean>, Pair<Integer, Integer>>> queuedMarriages = new HashMap<>();
|
||||
private Map<Integer, Set<Integer>> marriageGuests = new HashMap<>();
|
||||
|
||||
private Map<Integer, MapleParty> parties = new HashMap<>();
|
||||
private AtomicInteger runningPartyId = new AtomicInteger();
|
||||
@@ -119,6 +127,7 @@ public class World {
|
||||
private Lock timedMapObjectLock = new MonitoredReentrantLock(MonitoredLockType.MAP_OBJS, true);
|
||||
|
||||
private ScheduledFuture<?> charactersSchedule;
|
||||
private ScheduledFuture<?> marriagesSchedule;
|
||||
|
||||
public World(int world, int flag, String eventmsg, int exprate, int droprate, int mesorate, int questrate) {
|
||||
this.id = world;
|
||||
@@ -134,10 +143,13 @@ public class World {
|
||||
petUpdate = System.currentTimeMillis();
|
||||
mountUpdate = petUpdate;
|
||||
|
||||
petsSchedule = TimerManager.getInstance().register(new PetFullnessWorker(this), 60 * 1000, 60 * 1000);
|
||||
mountsSchedule = TimerManager.getInstance().register(new MountTirednessWorker(this), 60 * 1000, 60 * 1000);
|
||||
timedMapObjectsSchedule = TimerManager.getInstance().register(new TimedMapObjectWorker(this), 60 * 1000, 60 * 1000);
|
||||
charactersSchedule = TimerManager.getInstance().register(new CharacterAutosaverWorker(this), 60 * 60 * 1000, 60 * 60 * 1000);
|
||||
TimerManager tman = TimerManager.getInstance();
|
||||
petsSchedule = tman.register(new PetFullnessWorker(this), 60 * 1000, 60 * 1000);
|
||||
mountsSchedule = tman.register(new MountTirednessWorker(this), 60 * 1000, 60 * 1000);
|
||||
timedMapObjectsSchedule = tman.register(new TimedMapObjectWorker(this), 60 * 1000, 60 * 1000);
|
||||
charactersSchedule = tman.register(new CharacterAutosaverWorker(this), 60 * 60 * 1000, 60 * 60 * 1000);
|
||||
marriagesSchedule = tman.register(new WeddingReservationWorker(this), ServerConstants.WEDDING_RESERVATION_INTERVAL * 60 * 1000, ServerConstants.WEDDING_RESERVATION_INTERVAL * 60 * 1000);
|
||||
|
||||
}
|
||||
|
||||
public List<Channel> getChannels() {
|
||||
@@ -409,6 +421,96 @@ public class World {
|
||||
queuedGuilds.remove(guildId);
|
||||
}
|
||||
|
||||
public boolean isMarriageQueued(int marriageId) {
|
||||
return queuedMarriages.containsKey(marriageId);
|
||||
}
|
||||
|
||||
public Pair<Boolean, Boolean> getMarriageQueuedLocation(int marriageId) {
|
||||
Pair<Pair<Boolean, Boolean>, Pair<Integer, Integer>> qm = queuedMarriages.get(marriageId);
|
||||
return (qm != null) ? qm.getLeft() : null;
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getMarriageQueuedCouple(int marriageId) {
|
||||
Pair<Pair<Boolean, Boolean>, Pair<Integer, Integer>> qm = queuedMarriages.get(marriageId);
|
||||
return (qm != null) ? qm.getRight() : null;
|
||||
}
|
||||
|
||||
public void putMarriageQueued(int marriageId, boolean cathedral, boolean premium, int groomId, int brideId) {
|
||||
queuedMarriages.put(marriageId, new Pair<>(new Pair<>(cathedral, premium), new Pair<>(groomId, brideId)));
|
||||
marriageGuests.put(marriageId, new HashSet());
|
||||
}
|
||||
|
||||
public Pair<Boolean, Set<Integer>> removeMarriageQueued(int marriageId) {
|
||||
Boolean type = queuedMarriages.remove(marriageId).getLeft().getRight();
|
||||
Set<Integer> guests = marriageGuests.remove(marriageId);
|
||||
|
||||
return new Pair<>(type, guests);
|
||||
}
|
||||
|
||||
public synchronized boolean addMarriageGuest(int marriageId, int playerId) {
|
||||
Set<Integer> guests = marriageGuests.get(marriageId);
|
||||
if(guests != null) {
|
||||
if(guests.contains(playerId)) return false;
|
||||
|
||||
guests.add(playerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getWeddingCoupleForGuest(int guestId, Boolean cathedral) {
|
||||
for(Channel ch : channels) {
|
||||
Pair<Integer, Integer> p = ch.getWeddingCoupleForGuest(guestId, cathedral);
|
||||
if(p != null) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
List<Integer> possibleWeddings = new LinkedList<>();
|
||||
for(Entry<Integer, Set<Integer>> mg : new HashSet<>(marriageGuests.entrySet())) {
|
||||
if(mg.getValue().contains(guestId)) {
|
||||
Pair<Boolean, Boolean> loc = getMarriageQueuedLocation(mg.getKey());
|
||||
if(loc != null && cathedral.equals(loc.getLeft())) {
|
||||
possibleWeddings.add(mg.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int pwSize = possibleWeddings.size();
|
||||
if(pwSize == 0) {
|
||||
return null;
|
||||
} else if(pwSize > 1) {
|
||||
int selectedPw = -1;
|
||||
int selectedPos = Integer.MAX_VALUE;
|
||||
|
||||
for(Integer pw : possibleWeddings) {
|
||||
for(Channel ch : channels) {
|
||||
int pos = ch.getWeddingReservationStatus(pw, cathedral);
|
||||
if(pos != -1) {
|
||||
if(pos < selectedPos) {
|
||||
selectedPos = pos;
|
||||
selectedPw = pw;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(selectedPw == -1) return null;
|
||||
|
||||
possibleWeddings.clear();
|
||||
possibleWeddings.add(selectedPw);
|
||||
}
|
||||
|
||||
return getMarriageQueuedCouple(possibleWeddings.get(0));
|
||||
}
|
||||
|
||||
public void debugMarriageStatus() {
|
||||
System.out.println("Queued marriages: " + queuedMarriages);
|
||||
System.out.println("Guest list: " + marriageGuests);
|
||||
}
|
||||
|
||||
public MapleParty createParty(MaplePartyCharacter chrfor) {
|
||||
int partyid = runningPartyId.getAndIncrement();
|
||||
MapleParty party = new MapleParty(partyid, chrfor);
|
||||
@@ -1089,34 +1191,54 @@ public class World {
|
||||
}
|
||||
|
||||
public void setPlayerNpcMapStep(int mapid, int step) {
|
||||
setPlayerNpcMapStep(mapid, step, false);
|
||||
setPlayerNpcMapData(mapid, step, -1, false);
|
||||
}
|
||||
|
||||
public void setPlayerNpcMapStep(int mapid, int step, boolean silent) {
|
||||
public void setPlayerNpcMapPodiumData(int mapid, int podium) {
|
||||
setPlayerNpcMapData(mapid, -1, podium, false);
|
||||
}
|
||||
|
||||
public void setPlayerNpcMapData(int mapid, int step, int podium) {
|
||||
setPlayerNpcMapData(mapid, step, podium, true);
|
||||
}
|
||||
|
||||
private static void executePlayerNpcMapDataUpdate(Connection con, boolean isPodium, Map<Integer, ?> pnpcData, int value, int worldid, int mapid) throws SQLException {
|
||||
PreparedStatement ps;
|
||||
if(pnpcData.containsKey(mapid)) {
|
||||
ps = con.prepareStatement("UPDATE playernpcs_field SET " + (isPodium ? "podium" : "step") + " = ? WHERE world = ? AND map = ?");
|
||||
} else {
|
||||
ps = con.prepareStatement("INSERT INTO playernpcs_field (" + (isPodium ? "podium" : "step") + ", world, map) VALUES (?, ?, ?)");
|
||||
}
|
||||
|
||||
ps.setInt(1, value);
|
||||
ps.setInt(2, worldid);
|
||||
ps.setInt(3, mapid);
|
||||
ps.executeUpdate();
|
||||
|
||||
ps.close();
|
||||
}
|
||||
|
||||
private void setPlayerNpcMapData(int mapid, int step, int podium, boolean silent) {
|
||||
if(!silent) {
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
|
||||
PreparedStatement ps;
|
||||
if(pnpcStep.containsKey(mapid)) {
|
||||
ps = con.prepareStatement("UPDATE playernpcs_field SET step = ? WHERE world = ? AND map = ?");
|
||||
} else {
|
||||
ps = con.prepareStatement("INSERT INTO playernpcs_field (step, world, map) VALUES (?, ?, ?)");
|
||||
|
||||
if(step != -1) {
|
||||
executePlayerNpcMapDataUpdate(con, false, pnpcStep, step, id, mapid);
|
||||
}
|
||||
|
||||
ps.setInt(1, step);
|
||||
ps.setInt(2, id);
|
||||
ps.setInt(3, mapid);
|
||||
ps.executeUpdate();
|
||||
|
||||
ps.close();
|
||||
|
||||
if(podium != -1) {
|
||||
executePlayerNpcMapDataUpdate(con, true, pnpcPodium, podium, id, mapid);
|
||||
}
|
||||
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
pnpcStep.put(mapid, (byte) step);
|
||||
if(step != -1) pnpcStep.put(mapid, (byte) step);
|
||||
if(podium != -1) pnpcPodium.put(mapid, (short) podium);
|
||||
}
|
||||
|
||||
public int getPlayerNpcMapStep(int mapid) {
|
||||
@@ -1127,6 +1249,19 @@ public class World {
|
||||
}
|
||||
}
|
||||
|
||||
public int getPlayerNpcMapPodiumData(int mapid) {
|
||||
try {
|
||||
return pnpcPodium.get(mapid);
|
||||
} catch (NullPointerException npe) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public void resetPlayerNpcMapData() {
|
||||
pnpcStep.clear();
|
||||
pnpcPodium.clear();
|
||||
}
|
||||
|
||||
public void setServerMessage(String msg) {
|
||||
for (Channel ch : channels) {
|
||||
ch.setServerMessage(msg);
|
||||
@@ -1140,33 +1275,160 @@ public class World {
|
||||
}
|
||||
|
||||
public List<Pair<MaplePlayerShopItem, AbstractMapleMapObject>> getAvailableItemBundles(int itemid) {
|
||||
List<Pair<MaplePlayerShopItem, AbstractMapleMapObject>> hmsAvailable = new ArrayList<>();
|
||||
List<Pair<MaplePlayerShopItem, AbstractMapleMapObject>> hmsAvailable = new ArrayList<>();
|
||||
|
||||
for (MapleHiredMerchant hm : getActiveMerchants()) {
|
||||
List<MaplePlayerShopItem> itemBundles = hm.sendAvailableBundles(itemid);
|
||||
|
||||
for(MaplePlayerShopItem mpsi : itemBundles) {
|
||||
hmsAvailable.add(new Pair<>(mpsi, (AbstractMapleMapObject) hm));
|
||||
}
|
||||
for (MapleHiredMerchant hm : getActiveMerchants()) {
|
||||
List<MaplePlayerShopItem> itemBundles = hm.sendAvailableBundles(itemid);
|
||||
|
||||
for(MaplePlayerShopItem mpsi : itemBundles) {
|
||||
hmsAvailable.add(new Pair<>(mpsi, (AbstractMapleMapObject) hm));
|
||||
}
|
||||
}
|
||||
|
||||
for (MaplePlayerShop ps : getActivePlayerShops()) {
|
||||
List<MaplePlayerShopItem> itemBundles = ps.sendAvailableBundles(itemid);
|
||||
|
||||
for(MaplePlayerShopItem mpsi : itemBundles) {
|
||||
hmsAvailable.add(new Pair<>(mpsi, (AbstractMapleMapObject) ps));
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(hmsAvailable, new Comparator<Pair<MaplePlayerShopItem, AbstractMapleMapObject>>() {
|
||||
@Override
|
||||
public int compare(Pair<MaplePlayerShopItem, AbstractMapleMapObject> p1, Pair<MaplePlayerShopItem, AbstractMapleMapObject> p2) {
|
||||
return p1.getLeft().getPrice() - p2.getLeft().getPrice();
|
||||
}
|
||||
});
|
||||
|
||||
hmsAvailable.subList(0, Math.min(hmsAvailable.size(), 200)); //truncates the list to have up to 200 elements
|
||||
return hmsAvailable;
|
||||
}
|
||||
|
||||
private void pushRelationshipCouple(Pair<Integer, Pair<Integer, Integer>> couple) {
|
||||
int mid = couple.getLeft(), hid = couple.getRight().getLeft(), wid = couple.getRight().getRight();
|
||||
relationshipCouples.put(mid, couple.getRight());
|
||||
relationships.put(hid, mid);
|
||||
relationships.put(wid, mid);
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getRelationshipCouple(int relationshipId) {
|
||||
Pair<Integer, Integer> rc = relationshipCouples.get(relationshipId);
|
||||
|
||||
if(rc == null) {
|
||||
Pair<Integer, Pair<Integer, Integer>> couple = getRelationshipCoupleFromDb(relationshipId, true);
|
||||
if(couple == null) return null;
|
||||
|
||||
pushRelationshipCouple(couple);
|
||||
rc = couple.getRight();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
public int getRelationshipId(int playerId) {
|
||||
Integer ret = relationships.get(playerId);
|
||||
|
||||
if(ret == null) {
|
||||
Pair<Integer, Pair<Integer, Integer>> couple = getRelationshipCoupleFromDb(playerId, false);
|
||||
if(couple == null) return -1;
|
||||
|
||||
pushRelationshipCouple(couple);
|
||||
ret = couple.getLeft();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Pair<Integer, Pair<Integer, Integer>> getRelationshipCoupleFromDb(int id, boolean usingMarriageId) {
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
Integer mid = null, hid = null, wid = null;
|
||||
|
||||
PreparedStatement ps;
|
||||
if(usingMarriageId) {
|
||||
ps = con.prepareStatement("SELECT * FROM marriages WHERE marriageid = ?");
|
||||
ps.setInt(1, id);
|
||||
} else {
|
||||
ps = con.prepareStatement("SELECT * FROM marriages WHERE husbandid = ? OR wifeid = ?");
|
||||
ps.setInt(1, id);
|
||||
ps.setInt(2, id);
|
||||
}
|
||||
|
||||
for (MaplePlayerShop ps : getActivePlayerShops()) {
|
||||
List<MaplePlayerShopItem> itemBundles = ps.sendAvailableBundles(itemid);
|
||||
|
||||
for(MaplePlayerShopItem mpsi : itemBundles) {
|
||||
hmsAvailable.add(new Pair<>(mpsi, (AbstractMapleMapObject) ps));
|
||||
}
|
||||
ResultSet rs = ps.executeQuery();
|
||||
if(rs.next()) {
|
||||
mid = rs.getInt("marriageid");
|
||||
hid = rs.getInt("husbandid");
|
||||
wid = rs.getInt("wifeid");
|
||||
}
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
|
||||
return (mid == null) ? null : new Pair<>(mid, new Pair<>(hid, wid));
|
||||
} catch (SQLException se) {
|
||||
se.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public int createRelationship(int groomId, int brideId) {
|
||||
int ret = addRelationshipToDb(groomId, brideId);
|
||||
|
||||
pushRelationshipCouple(new Pair<>(ret, new Pair<>(groomId, brideId)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static int addRelationshipToDb(int groomId, int brideId) {
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
|
||||
Collections.sort(hmsAvailable, new Comparator<Pair<MaplePlayerShopItem, AbstractMapleMapObject>>() {
|
||||
@Override
|
||||
public int compare(Pair<MaplePlayerShopItem, AbstractMapleMapObject> p1, Pair<MaplePlayerShopItem, AbstractMapleMapObject> p2) {
|
||||
return p1.getLeft().getPrice() - p2.getLeft().getPrice();
|
||||
}
|
||||
});
|
||||
PreparedStatement ps = con.prepareStatement("INSERT INTO marriages (husbandid, wifeid) VALUES (?, ?)", Statement.RETURN_GENERATED_KEYS);
|
||||
ps.setInt(1, groomId);
|
||||
ps.setInt(2, brideId);
|
||||
ps.executeUpdate();
|
||||
|
||||
hmsAvailable.subList(0, Math.min(hmsAvailable.size(), 200)); //truncates the list to have up to 200 elements
|
||||
return hmsAvailable;
|
||||
ResultSet rs = ps.getGeneratedKeys();
|
||||
rs.next();
|
||||
int ret = rs.getInt(1);
|
||||
|
||||
rs.close();
|
||||
ps.close();
|
||||
con.close();
|
||||
return ret;
|
||||
} catch (SQLException se) {
|
||||
se.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteRelationship(int playerId, int partnerId) {
|
||||
int relationshipId = relationships.get(playerId);
|
||||
deleteRelationshipFromDb(relationshipId);
|
||||
|
||||
relationshipCouples.remove(relationshipId);
|
||||
relationships.remove(playerId);
|
||||
relationships.remove(partnerId);
|
||||
}
|
||||
|
||||
private static void deleteRelationshipFromDb(int playerId) {
|
||||
try {
|
||||
Connection con = DatabaseConnection.getConnection();
|
||||
PreparedStatement ps = con.prepareStatement("DELETE FROM marriages WHERE marriageid = ?");
|
||||
ps.setInt(1, playerId);
|
||||
ps.executeUpdate();
|
||||
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch (SQLException se) {
|
||||
se.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void dropMessage(int type, String message) {
|
||||
for (MapleCharacter player : getPlayerStorage().getAllCharacters()) {
|
||||
player.dropMessage(type, message);
|
||||
}
|
||||
}
|
||||
|
||||
public final void shutdown() {
|
||||
|
||||
Reference in New Issue
Block a user