Overall wedding implementation
Implementation of the wedding feature.
This commit is contained in:
@@ -248,6 +248,8 @@ public final class PacketProcessor {
|
||||
registerHandler(RecvOpcode.MONSTER_CARNIVAL, new MonsterCarnivalHandler());
|
||||
registerHandler(RecvOpcode.REMOTE_STORE, new RemoteStoreHandler());
|
||||
registerHandler(RecvOpcode.WEDDING_ACTION, new WeddingHandler());
|
||||
registerHandler(RecvOpcode.WEDDING_TALK, new WeddingTalkHandler());
|
||||
registerHandler(RecvOpcode.WEDDING_TALK_MORE, new WeddingTalkMoreHandler());
|
||||
registerHandler(RecvOpcode.WATER_OF_LIFE, new UseWaterOfLifeHandler());
|
||||
registerHandler(RecvOpcode.ADMIN_CHAT, new AdminChatHandler());
|
||||
registerHandler(RecvOpcode.MOVE_DRAGON, new MoveDragonHandler());
|
||||
|
||||
@@ -114,7 +114,6 @@ public enum RecvOpcode {
|
||||
QUEST_ACTION(0x6B),
|
||||
//lolno
|
||||
SKILL_MACRO(0x6E),
|
||||
SPOUSE_CHAT(0x6F),
|
||||
USE_ITEM_REWARD(0x70),
|
||||
MAKER_SKILL(0x71),
|
||||
USE_REMOTE(0x74),
|
||||
@@ -122,6 +121,7 @@ public enum RecvOpcode {
|
||||
ADMIN_CHAT(0x76),
|
||||
PARTYCHAT(0x77),
|
||||
WHISPER(0x78),
|
||||
SPOUSE_CHAT(0x79),
|
||||
MESSENGER(0x7A),
|
||||
PLAYER_INTERACTION(0x7B),
|
||||
PARTY_OPERATION(0x7C),
|
||||
@@ -137,6 +137,8 @@ public enum RecvOpcode {
|
||||
RPS_ACTION(0x88),
|
||||
RING_ACTION(0x89),
|
||||
WEDDING_ACTION(0x8A),
|
||||
WEDDING_TALK(0x8B),
|
||||
WEDDING_TALK_MORE(0x8B),
|
||||
ALLIANCE_OPERATION(0x8F),
|
||||
OPEN_FAMILY(0x92),
|
||||
ADD_FAMILY(0x93),
|
||||
|
||||
@@ -67,7 +67,7 @@ public enum SendOpcode {
|
||||
OPEN_FULL_CLIENT_DOWNLOAD_LINK(0x28),
|
||||
MEMO_RESULT(0x29),
|
||||
MAP_TRANSFER_RESULT(0x2A),
|
||||
ANTI_MACRO_RESULT(0x2B),
|
||||
WEDDING_PHOTO(0x2B), //ANTI_MACRO_RESULT(0x2B),
|
||||
CLAIM_RESULT(0x2D),
|
||||
CLAIM_AVAILABLE_TIME(0x2E),
|
||||
CLAIM_STATUS_CHANGED(0x2F),
|
||||
|
||||
@@ -340,9 +340,10 @@ public class Server implements Runnable {
|
||||
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, "[WEDDING] " + couple.getLeft() + " and " + couple.getRight() + "'s wedding will start soon, and it will be held at the " + (cathedral ? "Cathedral" : "Chapel") + " in Amoria, on channel " + channel + ". Cheers for their love!!");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -204,11 +204,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
|
||||
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);
|
||||
}
|
||||
chr.addPlayerRing(ring);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,8 +277,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)) {
|
||||
slea.readInt(); //Birthday
|
||||
// if (checkBirthday(c, birthday)) {
|
||||
int payment = slea.readByte();
|
||||
slea.skip(3); //0s
|
||||
int snID = slea.readInt();
|
||||
|
||||
@@ -60,6 +60,7 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
|
||||
mc.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(mc.getId(), mc.getAllBuffs());
|
||||
mc.setAwayFromWorld(true);
|
||||
mc.notifyMapTransferToPartner(-1);
|
||||
mc.cancelAllBuffs(true);
|
||||
mc.cancelBuffExpireTask();
|
||||
mc.cancelDiseaseExpireTask();
|
||||
|
||||
@@ -69,6 +69,7 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
|
||||
chr.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
|
||||
chr.setAwayFromWorld(true);
|
||||
chr.notifyMapTransferToPartner(-1);
|
||||
chr.cancelAllBuffs(true);
|
||||
chr.cancelBuffExpireTask();
|
||||
chr.cancelDiseaseExpireTask();
|
||||
|
||||
@@ -51,7 +51,7 @@ public final class GeneralChatHandler extends net.AbstractMaplePacketHandler {
|
||||
String[] sp = s.split(" ");
|
||||
sp[0] = sp[0].toLowerCase().substring(1);
|
||||
|
||||
if(Commands.executeSolaxiaPlayerCommand(c, sp, heading)) {
|
||||
if(Commands.executeHeavenMsPlayerCommand(c, sp, heading)) {
|
||||
String command = "";
|
||||
for (String used : sp) {
|
||||
command += used + " ";
|
||||
|
||||
@@ -54,6 +54,7 @@ import constants.GameConstants;
|
||||
import constants.ServerConstants;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import tools.packets.Wedding;
|
||||
|
||||
public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -255,6 +256,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) {
|
||||
|
||||
@@ -25,86 +25,477 @@ package net.server.channel.handlers;
|
||||
//import java.sql.PreparedStatement;
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import client.inventory.MapleInventoryType;
|
||||
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 server.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.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?
|
||||
|
||||
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));
|
||||
|
||||
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.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.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
|
||||
System.out.println("Cancel Ring Action: " + slea.toString()); // log packet and see if any bytes
|
||||
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);
|
||||
|
||||
DueyHandler.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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 server.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) 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) 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());
|
||||
}
|
||||
}
|
||||
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;
|
||||
@@ -58,6 +60,7 @@ import server.maps.AbstractMapleMapObject;
|
||||
import net.server.worker.CharacterAutosaverWorker;
|
||||
import net.server.worker.MountTirednessWorker;
|
||||
import net.server.worker.PetFullnessWorker;
|
||||
import net.server.worker.WeddingReservationWorker;
|
||||
import net.server.PlayerStorage;
|
||||
import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
@@ -83,10 +86,14 @@ public class World {
|
||||
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();
|
||||
@@ -113,6 +120,7 @@ public class World {
|
||||
private long merchantUpdate;
|
||||
|
||||
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;
|
||||
@@ -128,9 +136,11 @@ 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);
|
||||
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);
|
||||
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() {
|
||||
@@ -371,6 +381,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);
|
||||
@@ -1028,33 +1128,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