Overall wedding implementation

Implementation of the wedding feature.
This commit is contained in:
ronancpl
2018-04-10 21:50:29 -03:00
parent 6da5edd837
commit ede8ad8551
59 changed files with 5281 additions and 1246 deletions

View File

@@ -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());
}
}