New Year cards + Info on PlayerShops/HiredMerchants
New Year is coming soon! Figured out implementation for the New Year cards. Opcodes and packet structures are thanks to Eric. New Year effect crashes/dc's the player in some cases. Added informative notes to shop owners when transactioning an item/bundle.
This commit is contained in:
@@ -116,6 +116,7 @@ import client.inventory.MaplePet;
|
||||
import client.inventory.MapleWeaponType;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.inventory.PetDataFactory;
|
||||
import client.newyear.NewYearCardRecord;
|
||||
import constants.ExpTable;
|
||||
import constants.GameConstants;
|
||||
import constants.ItemConstants;
|
||||
@@ -238,6 +239,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private MonsterBook monsterbook;
|
||||
private MapleRing marriageRing;
|
||||
private CashShop cashshop;
|
||||
private Set<NewYearCardRecord> newyears = new LinkedHashSet<>();
|
||||
private SavedLocation savedLocations[];
|
||||
private SkillMacro[] skillMacros = new SkillMacro[5];
|
||||
private List<Integer> lastmonthfameids;
|
||||
@@ -830,7 +832,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
announce(MaplePacketCreator.getGMEffect(0x10, (byte) 0));
|
||||
List<MapleBuffStat> dsstat = Collections.singletonList(MapleBuffStat.DARKSIGHT);
|
||||
getMap().broadcastGMMessage(this, MaplePacketCreator.cancelForeignBuff(id, dsstat), false);
|
||||
getMap().broadcastMessage(this, MaplePacketCreator.spawnPlayerMapobject(this), false);
|
||||
getMap().broadcastMessage(this, MaplePacketCreator.spawnPlayerMapObject(this), false);
|
||||
|
||||
for(MapleSummon ms: this.getSummonsValues()) {
|
||||
getMap().broadcastNONGMMessage(this, MaplePacketCreator.spawnSummon(ms, false), false);
|
||||
@@ -843,7 +845,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
if (!login) {
|
||||
getMap().broadcastMessage(this, MaplePacketCreator.removePlayerFromMap(getId()), false);
|
||||
}
|
||||
getMap().broadcastGMMessage(this, MaplePacketCreator.spawnPlayerMapobject(this), false);
|
||||
getMap().broadcastGMMessage(this, MaplePacketCreator.spawnPlayerMapObject(this), false);
|
||||
List<Pair<MapleBuffStat, Integer>> dsstat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DARKSIGHT, 0));
|
||||
getMap().broadcastGMMessage(this, MaplePacketCreator.giveForeignBuff(id, dsstat), false);
|
||||
for (MapleMonster mon : this.getControlledMonsters()) {
|
||||
@@ -1074,7 +1076,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
guildUpdate();
|
||||
|
||||
getMap().broadcastMessage(this, MaplePacketCreator.removePlayerFromMap(this.getId()), false);
|
||||
getMap().broadcastMessage(this, MaplePacketCreator.spawnPlayerMapobject(this), false);
|
||||
getMap().broadcastMessage(this, MaplePacketCreator.spawnPlayerMapObject(this), false);
|
||||
getMap().broadcastMessage(this, MaplePacketCreator.showForeignEffect(getId(), 8), false);
|
||||
|
||||
if (GameConstants.hasSPTable(newJob) && newJob.getId() != 2001) {
|
||||
@@ -5338,6 +5340,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
}
|
||||
|
||||
NewYearCardRecord.loadPlayerNewYearCards(ret);
|
||||
|
||||
PreparedStatement ps2, ps3;
|
||||
ResultSet rs2, rs3;
|
||||
|
||||
@@ -7571,7 +7575,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
if (!this.isHidden() || client.getPlayer().gmLevel() > 1) {
|
||||
client.announce(MaplePacketCreator.spawnPlayerMapobject(this));
|
||||
client.announce(MaplePacketCreator.spawnPlayerMapObject(this));
|
||||
}
|
||||
|
||||
if (this.isHidden()) {
|
||||
@@ -7600,6 +7604,40 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
public CashShop getCashShop() {
|
||||
return cashshop;
|
||||
}
|
||||
|
||||
public Set<NewYearCardRecord> getNewYearRecords() {
|
||||
return newyears;
|
||||
}
|
||||
|
||||
public Set<NewYearCardRecord> getReceivedNewYearRecords() {
|
||||
Set<NewYearCardRecord> received = new LinkedHashSet<>();
|
||||
|
||||
for(NewYearCardRecord nyc : newyears) {
|
||||
if(nyc.isReceiverCardReceived()) {
|
||||
received.add(nyc);
|
||||
}
|
||||
}
|
||||
|
||||
return received;
|
||||
}
|
||||
|
||||
public NewYearCardRecord getNewYearRecord(int cardid) {
|
||||
for(NewYearCardRecord nyc : newyears) {
|
||||
if(nyc.getId() == cardid) {
|
||||
return nyc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addNewYearRecord(NewYearCardRecord newyear) {
|
||||
newyears.add(newyear);
|
||||
}
|
||||
|
||||
public void removeNewYearRecord(NewYearCardRecord newyear) {
|
||||
newyears.remove(newyear);
|
||||
}
|
||||
|
||||
public void portalDelay(long delay) {
|
||||
this.portaldelay = System.currentTimeMillis() + delay;
|
||||
|
||||
377
src/client/newyear/NewYearCardRecord.java
Normal file
377
src/client/newyear/NewYearCardRecord.java
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* This file is part of the HeavenMS (MapleSolaxiaV2) Maple Story Server
|
||||
*
|
||||
* Copyright (C) 2017 RonanLana
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package client.newyear;
|
||||
|
||||
import client.MapleCharacter;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import net.server.Server;
|
||||
import server.TimerManager;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan (credits to Eric for showing the New Year opcodes and handler layout)
|
||||
*/
|
||||
public class NewYearCardRecord {
|
||||
private int id;
|
||||
|
||||
private int senderId;
|
||||
private String senderName;
|
||||
private boolean senderDiscardCard;
|
||||
|
||||
private int receiverId;
|
||||
private String receiverName;
|
||||
private boolean receiverDiscardCard;
|
||||
private boolean receiverReceivedCard;
|
||||
|
||||
private String stringContent;
|
||||
private long dateSent = 0;
|
||||
private long dateReceived = 0;
|
||||
|
||||
private ScheduledFuture<?> sendTask = null;
|
||||
|
||||
public NewYearCardRecord(int senderid, String sender, int receiverid, String receiver, String message) {
|
||||
this.id = -1;
|
||||
|
||||
this.senderId = senderid;
|
||||
this.senderName = sender;
|
||||
this.senderDiscardCard = false;
|
||||
|
||||
this.receiverId = receiverid;
|
||||
this.receiverName = receiver;
|
||||
this.receiverDiscardCard = false;
|
||||
this.receiverReceivedCard = false;
|
||||
|
||||
this.stringContent = message;
|
||||
|
||||
this.dateSent = System.currentTimeMillis();
|
||||
this.dateReceived = 0;
|
||||
}
|
||||
|
||||
private void setExtraNewYearCardRecord(int id, boolean senderDiscardCard, boolean receiverDiscardCard, boolean receiverReceivedCard, long dateSent, long dateReceived) {
|
||||
this.id = id;
|
||||
this.senderDiscardCard = senderDiscardCard;
|
||||
this.receiverDiscardCard = receiverDiscardCard;
|
||||
this.receiverReceivedCard = receiverReceivedCard;
|
||||
|
||||
this.dateSent = dateSent;
|
||||
this.dateReceived = dateReceived;
|
||||
}
|
||||
|
||||
public void setId(int cardid) {
|
||||
this.id = cardid;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public int getSenderId() {
|
||||
return senderId;
|
||||
}
|
||||
|
||||
public String getSenderName() {
|
||||
return senderName;
|
||||
}
|
||||
|
||||
public boolean isSenderCardDiscarded() {
|
||||
return senderDiscardCard;
|
||||
}
|
||||
|
||||
public int getReceiverId() {
|
||||
return receiverId;
|
||||
}
|
||||
|
||||
public String getReceiverName() {
|
||||
return receiverName;
|
||||
}
|
||||
|
||||
public boolean isReceiverCardDiscarded() {
|
||||
return receiverDiscardCard;
|
||||
}
|
||||
|
||||
public boolean isReceiverCardReceived() {
|
||||
return receiverReceivedCard;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return stringContent;
|
||||
}
|
||||
|
||||
public long getDateSent() {
|
||||
return dateSent;
|
||||
}
|
||||
|
||||
public long getDateReceived() {
|
||||
return dateReceived;
|
||||
}
|
||||
|
||||
public static void saveNewYearCard(NewYearCardRecord newyear) {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("INSERT INTO newyear VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
|
||||
ps.setInt(1, newyear.senderId);
|
||||
ps.setString(2, newyear.senderName);
|
||||
ps.setInt(3, newyear.receiverId);
|
||||
ps.setString(4, newyear.receiverName);
|
||||
|
||||
ps.setString(5, newyear.stringContent);
|
||||
|
||||
ps.setBoolean(6, newyear.senderDiscardCard);
|
||||
ps.setBoolean(7, newyear.receiverDiscardCard);
|
||||
ps.setBoolean(8, newyear.receiverReceivedCard);
|
||||
|
||||
ps.setLong(9, newyear.dateSent);
|
||||
ps.setLong(10, newyear.dateReceived);
|
||||
|
||||
ps.executeUpdate();
|
||||
try (ResultSet rs = ps.getGeneratedKeys()) {
|
||||
rs.next();
|
||||
newyear.id = rs.getInt(1);
|
||||
}
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateNewYearCard(NewYearCardRecord newyear) {
|
||||
newyear.receiverReceivedCard = true;
|
||||
newyear.dateReceived = System.currentTimeMillis();
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("UPDATE newyear SET received=1, timereceived=? WHERE id=?")) {
|
||||
ps.setLong(1, newyear.dateReceived);
|
||||
ps.setInt(2, newyear.id);
|
||||
|
||||
ps.executeUpdate();
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static NewYearCardRecord loadNewYearCard(int cardid) {
|
||||
NewYearCardRecord nyc = Server.getInstance().getNewYearCard(cardid);
|
||||
if(nyc != null) return nyc;
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM newyear WHERE id = ?")) {
|
||||
ps.setInt(1, cardid);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
NewYearCardRecord newyear = new NewYearCardRecord(rs.getInt("senderid"), rs.getString("sendername"), rs.getInt("receiverid"), rs.getString("receivername"), rs.getString("message"));
|
||||
newyear.setExtraNewYearCardRecord(rs.getInt("id"), rs.getBoolean("senderdiscard"), rs.getBoolean("receiverdiscard"), rs.getBoolean("received"), rs.getLong("timesent"), rs.getLong("timereceived"));
|
||||
|
||||
Server.getInstance().setNewYearCard(newyear);
|
||||
return newyear;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void loadPlayerNewYearCards(MapleCharacter chr) {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM newyear WHERE senderid = ? OR receiverid = ?")) {
|
||||
ps.setInt(1, chr.getId());
|
||||
ps.setInt(2, chr.getId());
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
NewYearCardRecord newyear = new NewYearCardRecord(rs.getInt("senderid"), rs.getString("sendername"), rs.getInt("receiverid"), rs.getString("receivername"), rs.getString("message"));
|
||||
newyear.setExtraNewYearCardRecord(rs.getInt("id"), rs.getBoolean("senderdiscard"), rs.getBoolean("receiverdiscard"), rs.getBoolean("received"), rs.getLong("timesent"), rs.getLong("timereceived"));
|
||||
|
||||
chr.addNewYearRecord(newyear);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void printNewYearRecords(MapleCharacter chr) {
|
||||
chr.dropMessage(5, "New Years: " + chr.getNewYearRecords().size());
|
||||
|
||||
for(NewYearCardRecord nyc : chr.getNewYearRecords()) {
|
||||
chr.dropMessage(5, "-------------------------------");
|
||||
|
||||
chr.dropMessage(5, "Id: " + nyc.id);
|
||||
|
||||
chr.dropMessage(5, "Sender id: " + nyc.senderId);
|
||||
chr.dropMessage(5, "Sender name: " + nyc.senderName);
|
||||
chr.dropMessage(5, "Sender discard: " + nyc.senderDiscardCard);
|
||||
|
||||
chr.dropMessage(5, "Receiver id: " + nyc.receiverId);
|
||||
chr.dropMessage(5, "Receiver name: " + nyc.receiverName);
|
||||
chr.dropMessage(5, "Receiver discard: " + nyc.receiverDiscardCard);
|
||||
chr.dropMessage(5, "Received: " + nyc.receiverReceivedCard);
|
||||
|
||||
chr.dropMessage(5, "Message: " + nyc.stringContent);
|
||||
chr.dropMessage(5, "Date sent: " + nyc.dateSent);
|
||||
chr.dropMessage(5, "Date recv: " + nyc.dateReceived);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getCharacterWorld(int receiverid) {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT world FROM characters WHERE id = ?")) {
|
||||
ps.setInt(1, receiverid);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
return rs.getInt("world");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void startNewYearCardTask() {
|
||||
if(sendTask != null) return;
|
||||
|
||||
sendTask = TimerManager.getInstance().register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int world = getCharacterWorld(receiverId);
|
||||
if(world == -1) {
|
||||
sendTask.cancel(false);
|
||||
sendTask = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
MapleCharacter target = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(receiverId);
|
||||
if(target != null && target.isLoggedin() && !target.isAwayFromWorld()) {
|
||||
target.announce(MaplePacketCreator.onNewYearCardRes(target, NewYearCardRecord.this, 0xC, 0));
|
||||
}
|
||||
}
|
||||
}, 1000 * 60 * 60); //1 Hour
|
||||
}
|
||||
|
||||
public void stopNewYearCardTask() {
|
||||
if(sendTask != null) {
|
||||
sendTask.cancel(false);
|
||||
sendTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteNewYearCard(int id) {
|
||||
Server.getInstance().removeNewYearCard(id);
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("DELETE FROM newyear WHERE id = ?")) {
|
||||
ps.setInt(1, id);
|
||||
ps.executeUpdate();
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeAllNewYearCard(boolean send, MapleCharacter chr) {
|
||||
int cid = chr.getId();
|
||||
|
||||
/* not truly needed since it's going to be hard removed from the DB
|
||||
String actor = (send ? "sender" : "receiver");
|
||||
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("UPDATE newyear SET " + actor + "id = 1, received = 0 WHERE " + actor + "id = ?")) {
|
||||
ps.setInt(1, cid);
|
||||
ps.executeUpdate();
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
*/
|
||||
|
||||
Set<NewYearCardRecord> set = new HashSet<>(chr.getNewYearRecords());
|
||||
for(NewYearCardRecord nyc : set) {
|
||||
if(send) {
|
||||
if(nyc.senderId == cid) {
|
||||
nyc.senderDiscardCard = true;
|
||||
nyc.receiverReceivedCard = false;
|
||||
|
||||
chr.removeNewYearRecord(nyc);
|
||||
deleteNewYearCard(nyc.id);
|
||||
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(chr, nyc, 0xE, 0));
|
||||
|
||||
MapleCharacter other = chr.getClient().getWorldServer().getPlayerStorage().getCharacterById(nyc.getReceiverId());
|
||||
if(other != null && other.isLoggedin() && !other.isAwayFromWorld()) {
|
||||
other.removeNewYearRecord(nyc);
|
||||
other.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(other, nyc, 0xE, 0));
|
||||
|
||||
other.dropMessage(6, "[NEW YEAR] " + chr.getName() + " threw away the New Year card.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(nyc.receiverId == cid) {
|
||||
nyc.receiverDiscardCard = true;
|
||||
nyc.receiverReceivedCard = false;
|
||||
|
||||
chr.removeNewYearRecord(nyc);
|
||||
deleteNewYearCard(nyc.id);
|
||||
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(chr, nyc, 0xE, 0));
|
||||
|
||||
MapleCharacter other = chr.getClient().getWorldServer().getPlayerStorage().getCharacterById(nyc.getSenderId());
|
||||
if(other != null && other.isLoggedin() && !other.isAwayFromWorld()) {
|
||||
other.removeNewYearRecord(nyc);
|
||||
other.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(other, nyc, 0xE, 0));
|
||||
|
||||
other.dropMessage(6, "[NEW YEAR] " + chr.getName() + " threw away the New Year card.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void startPendingNewYearCardRequests() {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM newyear WHERE timereceived = 0 AND senderdiscard = 0")) {
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
NewYearCardRecord newyear = new NewYearCardRecord(rs.getInt("senderid"), rs.getString("sendername"), rs.getInt("receiverid"), rs.getString("receivername"), rs.getString("message"));
|
||||
newyear.setExtraNewYearCardRecord(rs.getInt("id"), rs.getBoolean("senderdiscard"), rs.getBoolean("receiverdiscard"), rs.getBoolean("received"), rs.getLong("timesent"), rs.getLong("timereceived"));
|
||||
|
||||
Server.getInstance().setNewYearCard(newyear);
|
||||
newyear.startNewYearCardTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,14 @@ public final class ItemConstants {
|
||||
return itemId / 1000 == 5000;
|
||||
}
|
||||
|
||||
public static boolean isNewYearCardEtc(int itemId) {
|
||||
return itemId / 10000 == 430;
|
||||
}
|
||||
|
||||
public static boolean isNewYearCardUse(int itemId) {
|
||||
return itemId / 10000 == 216;
|
||||
}
|
||||
|
||||
public static boolean isAccessory(int itemId) {
|
||||
return itemId >= 1110000 && itemId < 1140000;
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@ public final class PacketProcessor {
|
||||
registerHandler(RecvOpcode.ALLIANCE_OPERATION, new AllianceOperationHandler());
|
||||
registerHandler(RecvOpcode.USE_SOLOMON_ITEM, new UseSolomonHandler());
|
||||
registerHandler(RecvOpcode.USE_GACHA_EXP, new UseGachaExpHandler());
|
||||
registerHandler(RecvOpcode.NEW_YEAR_CARD_REQUEST, new NewYearCardHandler());
|
||||
registerHandler(RecvOpcode.USE_ITEM_REWARD, new ItemRewardHandler());
|
||||
registerHandler(RecvOpcode.USE_REMOTE, new RemoteGachaponHandler());
|
||||
registerHandler(RecvOpcode.ACCEPT_FAMILY, new AcceptFamilyHandler());
|
||||
|
||||
@@ -146,6 +146,7 @@ public enum RecvOpcode {
|
||||
ENTER_MTS(0x9C),
|
||||
USE_SOLOMON_ITEM(0x9D),
|
||||
USE_GACHA_EXP(0x9E),
|
||||
NEW_YEAR_CARD_REQUEST(0x9F),
|
||||
CLICK_GUIDE(0xA2),
|
||||
ARAN_COMBO_COUNTER(0xA3),
|
||||
MOVE_PET(0xA7),
|
||||
|
||||
@@ -68,6 +68,7 @@ import tools.Pair;
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import client.SkillFactory;
|
||||
import client.newyear.NewYearCardRecord;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
import java.util.Calendar;
|
||||
@@ -91,6 +92,7 @@ public class Server implements Runnable {
|
||||
private final Lock srvLock = new MonitoredReentrantLock(MonitoredLockType.SERVER);
|
||||
private final PlayerBuffStorage buffStorage = new PlayerBuffStorage();
|
||||
private final Map<Integer, MapleAlliance> alliances = new HashMap<>(100);
|
||||
private final Map<Integer, NewYearCardRecord> newyears = new HashMap<>();
|
||||
|
||||
private boolean online = false;
|
||||
public static long uptime = System.currentTimeMillis();
|
||||
@@ -109,6 +111,18 @@ public class Server implements Runnable {
|
||||
public List<Pair<Integer, String>> worldRecommendedList() {
|
||||
return worldRecommendedList;
|
||||
}
|
||||
|
||||
public void setNewYearCard(NewYearCardRecord nyc) {
|
||||
newyears.put(nyc.getId(), nyc);
|
||||
}
|
||||
|
||||
public NewYearCardRecord getNewYearCard(int cardid) {
|
||||
return newyears.get(cardid);
|
||||
}
|
||||
|
||||
public NewYearCardRecord removeNewYearCard(int cardid) {
|
||||
return newyears.remove(cardid);
|
||||
}
|
||||
|
||||
/*
|
||||
public void removeChannel(int worldid, int channel) { //lol don't!
|
||||
@@ -306,6 +320,8 @@ public class Server implements Runnable {
|
||||
MapleQuest.loadAllQuest();
|
||||
System.out.println("Quest loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds\r\n");
|
||||
|
||||
NewYearCardRecord.startPendingNewYearCardRequests();
|
||||
|
||||
if(ServerConstants.USE_THREAD_TRACKER) ThreadTracker.getInstance().registerThreadTrackerTask();
|
||||
|
||||
try {
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class GuildOperationHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
private void respawnPlayer(MapleCharacter mc) {
|
||||
mc.getMap().broadcastMessage(mc, MaplePacketCreator.removePlayerFromMap(mc.getId()), false);
|
||||
mc.getMap().broadcastMessage(mc, MaplePacketCreator.spawnPlayerMapobject(mc), false);
|
||||
mc.getMap().broadcastMessage(mc, MaplePacketCreator.spawnPlayerMapObject(mc), false);
|
||||
}
|
||||
|
||||
private class Invited {
|
||||
|
||||
153
src/net/server/channel/handlers/NewYearCardHandler.java
Normal file
153
src/net/server/channel/handlers/NewYearCardHandler.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This file is part of the HeavenMS (MapleSolaxiaV2) Maple Story Server
|
||||
*
|
||||
* Copyright (C) 2017 RonanLana
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import constants.ItemConstants;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.Item;
|
||||
import client.newyear.NewYearCardRecord;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.DatabaseConnection;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan - header layout courtesy of Eric
|
||||
*/
|
||||
public final class NewYearCardHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
final MapleCharacter player = c.getPlayer();
|
||||
byte reqMode = slea.readByte(); //[00] -> NewYearReq (0 = Send)
|
||||
|
||||
if(reqMode == 0) { // card has been sent
|
||||
if(player.haveItem(2160101)) { // new year's card
|
||||
short slot = slea.readShort(); //[00 2C] -> nPOS (Item Slot Pos)
|
||||
int itemid = slea.readInt(); //[00 20 F5 E5] -> nItemID (item id)
|
||||
|
||||
int status = getValidNewYearCardStatus(itemid, player, slot);
|
||||
if(status == 0) {
|
||||
if(player.canHold(4300000, 1)) {
|
||||
String receiver = slea.readMapleAsciiString(); //[04 00 54 65 73 74] -> sReceiverName (person to send to)
|
||||
|
||||
int receiverid = getReceiverId(receiver, c.getWorld());
|
||||
if(receiverid != -1) {
|
||||
if(receiverid != c.getPlayer().getId()) {
|
||||
String message = slea.readMapleAsciiString(); //[06 00 4C 65 74 74 65 72] -> sContent (message)
|
||||
|
||||
NewYearCardRecord newyear = new NewYearCardRecord(player.getId(), player.getName(), receiverid, receiver, message);
|
||||
NewYearCardRecord.saveNewYearCard(newyear);
|
||||
player.addNewYearRecord(newyear);
|
||||
|
||||
player.getClient().getAbstractPlayerInteraction().gainItem(2160101, (short)-1);
|
||||
player.getClient().getAbstractPlayerInteraction().gainItem(4300000, (short) 1);
|
||||
|
||||
Server.getInstance().setNewYearCard(newyear);
|
||||
newyear.startNewYearCardTask();
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, newyear, 4, 0)); // successfully sent
|
||||
} else {
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, -1, 5, 0xF)); // cannot send to yourself
|
||||
}
|
||||
} else {
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, -1, 5, 0x13)); // cannot find such character
|
||||
}
|
||||
} else {
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, -1, 5, 0x10)); // inventory full
|
||||
}
|
||||
} else {
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, -1, 5, status)); // item and inventory errors
|
||||
}
|
||||
} else {
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, -1, 5, 0x11)); // have no card to send
|
||||
}
|
||||
} else { //receiver accepted the card
|
||||
int cardid = slea.readInt();
|
||||
|
||||
NewYearCardRecord newyear = NewYearCardRecord.loadNewYearCard(cardid);
|
||||
|
||||
if(newyear != null && newyear.getReceiverId() == player.getId() && !newyear.isReceiverCardReceived()) {
|
||||
if(!newyear.isSenderCardDiscarded()) {
|
||||
if(player.canHold(4301000, 1)) {
|
||||
newyear.stopNewYearCardTask();
|
||||
NewYearCardRecord.updateNewYearCard(newyear);
|
||||
|
||||
player.getClient().getAbstractPlayerInteraction().gainItem(4301000, (short)1);
|
||||
if(!newyear.getMessage().isEmpty()) player.dropMessage(6, "[NEW YEAR] " + newyear.getSenderName() + ": " + newyear.getMessage());
|
||||
|
||||
player.addNewYearRecord(newyear);
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, newyear, 6, 0)); // successfully rcvd
|
||||
|
||||
player.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(player, newyear, 0xD, 0));
|
||||
|
||||
MapleCharacter sender = c.getWorldServer().getPlayerStorage().getCharacterById(newyear.getSenderId());
|
||||
if(sender != null && sender.isLoggedin() && !sender.isAwayFromWorld()) {
|
||||
sender.getMap().broadcastMessage(MaplePacketCreator.onNewYearCardRes(sender, newyear, 0xD, 0));
|
||||
sender.dropMessage(6, "[NEW YEAR] Your addressee successfully received the New Year card.");
|
||||
}
|
||||
} else {
|
||||
player.announce(MaplePacketCreator.onNewYearCardRes(player, -1, 5, 0x10)); // inventory full
|
||||
}
|
||||
} else {
|
||||
player.dropMessage(6, "[NEW YEAR] The sender of the New Year card already dropped it. Nothing to receive.");
|
||||
}
|
||||
} else {
|
||||
if(newyear == null) {
|
||||
player.dropMessage(6, "[NEW YEAR] The sender of the New Year card already dropped it. Nothing to receive.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getReceiverId(String receiver, int world) {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT id, world FROM characters WHERE name LIKE ?")) {
|
||||
ps.setString(1, receiver);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
if(rs.getInt("world") == world) {
|
||||
return rs.getInt("id");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(SQLException sqle) {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int getValidNewYearCardStatus(int itemid, MapleCharacter player, short slot) {
|
||||
if(!ItemConstants.isNewYearCardUse(itemid)) return 0x14;
|
||||
|
||||
Item it = player.getInventory(MapleItemInformationProvider.getInstance().getInventoryType(itemid)).getItem(slot);
|
||||
return (it != null && it.getItemId() == itemid) ? 0 : 0x12;
|
||||
}
|
||||
}
|
||||
@@ -336,7 +336,7 @@ public class World {
|
||||
}
|
||||
if (bDifferentGuild) {
|
||||
mc.getMap().broadcastMessage(mc, MaplePacketCreator.removePlayerFromMap(cid), false);
|
||||
mc.getMap().broadcastMessage(mc, MaplePacketCreator.spawnPlayerMapobject(mc), false);
|
||||
mc.getMap().broadcastMessage(mc, MaplePacketCreator.spawnPlayerMapObject(mc), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.newyear.NewYearCardRecord;
|
||||
import constants.ItemConstants;
|
||||
import constants.ServerConstants;
|
||||
|
||||
@@ -544,7 +545,7 @@ public class MapleInventoryManipulator {
|
||||
c.getPlayer().setChalkboard(null);
|
||||
}
|
||||
}
|
||||
if (source == null || (!ItemConstants.isRechargable(itemId) && source.getQuantity() < quantity) || quantity < 0) {
|
||||
if ((!ItemConstants.isRechargable(itemId) && source.getQuantity() < quantity) || quantity < 0) {
|
||||
return;
|
||||
}
|
||||
Point dropPos = new Point(c.getPlayer().getPosition());
|
||||
@@ -553,6 +554,17 @@ public class MapleInventoryManipulator {
|
||||
target.setQuantity(quantity);
|
||||
source.setQuantity((short) (source.getQuantity() - quantity));
|
||||
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(1, source))));
|
||||
|
||||
if(ItemConstants.isNewYearCardEtc(itemId)) {
|
||||
if(itemId == 4300000) {
|
||||
NewYearCardRecord.removeAllNewYearCard(true, c.getPlayer());
|
||||
c.getAbstractPlayerInteraction().removeAll(4300000);
|
||||
} else {
|
||||
NewYearCardRecord.removeAllNewYearCard(false, c.getPlayer());
|
||||
c.getAbstractPlayerInteraction().removeAll(4301000);
|
||||
}
|
||||
}
|
||||
|
||||
boolean weddingRing = source.getItemId() == 1112803 || source.getItemId() == 1112806 || source.getItemId() == 1112807 || source.getItemId() == 1112809;
|
||||
if (weddingRing) {
|
||||
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos);
|
||||
@@ -572,7 +584,16 @@ public class MapleInventoryManipulator {
|
||||
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(3, source))));
|
||||
if (src < 0) {
|
||||
c.getPlayer().equipChanged();
|
||||
} else if(ItemConstants.isNewYearCardEtc(itemId)) {
|
||||
if(itemId == 4300000) {
|
||||
NewYearCardRecord.removeAllNewYearCard(true, c.getPlayer());
|
||||
c.getAbstractPlayerInteraction().removeAll(4300000);
|
||||
} else {
|
||||
NewYearCardRecord.removeAllNewYearCard(false, c.getPlayer());
|
||||
c.getAbstractPlayerInteraction().removeAll(4301000);
|
||||
}
|
||||
}
|
||||
|
||||
if (c.getPlayer().getMap().getEverlast()) {
|
||||
if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
|
||||
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos);
|
||||
|
||||
@@ -753,7 +753,7 @@ public class MapleStatEffect {
|
||||
applyto.setStance(0);
|
||||
|
||||
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.removePlayerFromMap(applyto.getId()), false);
|
||||
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapobject(applyto), false);
|
||||
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapObject(applyto), false);
|
||||
}
|
||||
}
|
||||
if (isDispel() && makeChanceResult()) {
|
||||
@@ -919,7 +919,7 @@ public class MapleStatEffect {
|
||||
applyto.removeAllCooldownsExcept(Buccaneer.TIME_LEAP, true);
|
||||
} else if(isHyperBody() && !primary) {
|
||||
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.removePlayerFromMap(applyto.getId()), false);
|
||||
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapobject(applyto), false);
|
||||
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapObject(applyto), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -182,11 +182,13 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
int price = (int)Math.min((long)pItem.getPrice() * quantity, Integer.MAX_VALUE);
|
||||
|
||||
int price = (int) Math.min((long)pItem.getPrice() * quantity, Integer.MAX_VALUE);
|
||||
if (c.getPlayer().getMeso() >= price) {
|
||||
if (MapleInventoryManipulator.checkSpace(c, newItem.getItemId(), newItem.getQuantity(), newItem.getOwner())) {
|
||||
MapleInventoryManipulator.addFromDrop(c, newItem, false);
|
||||
c.getPlayer().gainMeso(-price, false);
|
||||
announceItemSold(newItem, price); // idea thanks to vcoc
|
||||
|
||||
synchronized (sold) {
|
||||
sold.add(new SoldItem(c.getPlayer().getName(), pItem.getItem().getItemId(), quantity, price));
|
||||
@@ -226,6 +228,16 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void announceItemSold(Item item, int mesos) {
|
||||
String qtyStr = (item.getQuantity() > 1) ? " (qty. " + item.getQuantity() + ")" : "";
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
MapleCharacter player = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(ownerId);
|
||||
if(player != null && player.isLoggedin() && !player.isAwayFromWorld()) {
|
||||
player.dropMessage(6, "[HIRED MERCHANT] Item '" + ii.getName(item.getItemId()) + "'" + qtyStr + " has been sold for " + mesos + " mesos.");
|
||||
}
|
||||
}
|
||||
|
||||
public void forceClose() {
|
||||
Server.getInstance().getWorld(world).unregisterHiredMerchant(this);
|
||||
@@ -508,7 +520,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public int getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@@ -2131,13 +2131,13 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
if (chr.isHidden()) {
|
||||
broadcastGMMessage(chr, MaplePacketCreator.spawnPlayerMapobject(chr), false);
|
||||
broadcastGMMessage(chr, MaplePacketCreator.spawnPlayerMapObject(chr), false);
|
||||
chr.announce(MaplePacketCreator.getGMEffect(0x10, (byte) 1));
|
||||
|
||||
List<Pair<MapleBuffStat, Integer>> dsstat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DARKSIGHT, 0));
|
||||
broadcastGMMessage(chr, MaplePacketCreator.giveForeignBuff(chr.getId(), dsstat), false);
|
||||
} else {
|
||||
broadcastMessage(chr, MaplePacketCreator.spawnPlayerMapobject(chr), false);
|
||||
broadcastMessage(chr, MaplePacketCreator.spawnPlayerMapObject(chr), false);
|
||||
}
|
||||
|
||||
sendObjectPlacement(chr.getClient());
|
||||
|
||||
@@ -34,9 +34,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import tools.locks.MonitoredReentrantLock;
|
||||
import net.SendOpcode;
|
||||
import net.server.Server;
|
||||
import server.MapleInventoryManipulator;
|
||||
import server.maps.AbstractMapleMapObject;
|
||||
import server.maps.MapleMapObjectType;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
import tools.data.output.MaplePacketLittleEndianWriter;
|
||||
@@ -103,7 +103,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
visitor.setSlot(i);
|
||||
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, i + 1));
|
||||
|
||||
if(i == 2) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(this.getOwner(), 1));
|
||||
if(i == 2) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(owner, 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
visitorLock.unlock();
|
||||
}
|
||||
|
||||
if(this.getOwner().getPlayerShop() != null) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(this.getOwner(), 4));
|
||||
if(owner.getPlayerShop() != null) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(owner, 4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,10 +205,15 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
return;
|
||||
}
|
||||
synchronized (c.getPlayer()) {
|
||||
if (c.getPlayer().getMeso() >= (long) pItem.getPrice() * quantity) {
|
||||
int price = (int) Math.min((long)pItem.getPrice() * quantity, Integer.MAX_VALUE);
|
||||
|
||||
if (c.getPlayer().getMeso() >= price) {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, newItem, false)) {
|
||||
c.getPlayer().gainMeso(-pItem.getPrice() * quantity, false);
|
||||
owner.gainMeso(pItem.getPrice() * quantity, true);
|
||||
c.getPlayer().gainMeso(-price, false);
|
||||
|
||||
announceItemSold(newItem, price); // idea thanks to vcoc
|
||||
owner.gainMeso(price, true);
|
||||
|
||||
pItem.setBundles((short) (pItem.getBundles() - quantity));
|
||||
if (pItem.getBundles() < 1) {
|
||||
pItem.setDoesExist(false);
|
||||
@@ -227,6 +232,13 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void announceItemSold(Item item, int mesos) {
|
||||
String qtyStr = (item.getQuantity() > 1) ? " (qty. " + item.getQuantity() + ")" : "";
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
|
||||
owner.dropMessage(6, "[PLAYER SHOP] Item '" + ii.getName(item.getItemId()) + "'" + qtyStr + " has been sold for " + mesos + " mesos.");
|
||||
}
|
||||
|
||||
public void broadcastToVisitors(final byte[] packet) {
|
||||
visitorLock.lock();
|
||||
@@ -283,7 +295,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
|
||||
for(MapleCharacter mc : visitorList) forceRemoveVisitor(mc);
|
||||
if (owner != null) {
|
||||
forceRemoveVisitor(getOwner());
|
||||
forceRemoveVisitor(owner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,12 +488,12 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.removeCharBox(this.getOwner()));
|
||||
client.announce(MaplePacketCreator.removeCharBox(owner));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.addCharBox(this.getOwner(), 4));
|
||||
client.announce(MaplePacketCreator.addCharBox(owner, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import net.SendOpcode;
|
||||
import net.server.PlayerCoolDownValueHolder;
|
||||
@@ -98,6 +99,7 @@ import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.inventory.ModifyInventory;
|
||||
import client.newyear.NewYearCardRecord;
|
||||
import client.status.MonsterStatus;
|
||||
import client.status.MonsterStatusEffect;
|
||||
import constants.GameConstants;
|
||||
@@ -217,30 +219,18 @@ public class MaplePacketCreator {
|
||||
addRingInfo(mplew, chr);
|
||||
addTeleportInfo(mplew, chr);
|
||||
addMonsterBookInfo(mplew, chr);
|
||||
addNewYearInfo(mplew, chr);//have fun!
|
||||
addNewYearInfo(mplew, chr);
|
||||
addAreaInfo(mplew, chr);//assuming it stayed here xd
|
||||
mplew.writeShort(0);
|
||||
}
|
||||
|
||||
private static void addNewYearInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
|
||||
mplew.writeShort(0);
|
||||
/*
|
||||
*(_DWORD *)this = CInPacket::Decode4(a2);
|
||||
*((_DWORD *)v2 + 1) = CInPacket::Decode4(a2);
|
||||
CInPacket::DecodeStr(&v7);
|
||||
v9 = 0;
|
||||
(*(void (__stdcall **)(char *, int))((char *)&loc_B1410B + 1))((char *)v2 + 8, v7);
|
||||
*(_DWORD *)((char *)v2 + 21) = (unsigned __int8)CInPacket::Decode1(a2);
|
||||
CInPacket::DecodeBuffer((char *)v2 + 25, 8);
|
||||
*(_DWORD *)((char *)v2 + 33) = CInPacket::Decode4(a2);
|
||||
CInPacket::DecodeStr(&v6);
|
||||
LOBYTE(v8) = 1;
|
||||
(*(void (__stdcall **)(char *, int))((char *)&loc_B1410B + 1))((char *)v2 + 37, v6);
|
||||
*(_DWORD *)((char *)v2 + 50) = (unsigned __int8)CInPacket::Decode1(a2);
|
||||
*(_DWORD *)((char *)v2 + 54) = (unsigned __int8)CInPacket::Decode1(a2);
|
||||
CInPacket::DecodeBuffer((char *)v2 + 58, 8);
|
||||
CInPacket::DecodeStr(&v9);
|
||||
*/
|
||||
Set<NewYearCardRecord> received = chr.getReceivedNewYearRecords();
|
||||
|
||||
mplew.writeShort(received.size());
|
||||
for(NewYearCardRecord nyc : received) {
|
||||
encodeNewYearCard(nyc, mplew);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addTeleportInfo(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
|
||||
@@ -1742,7 +1732,7 @@ public class MaplePacketCreator {
|
||||
* @param chr The character to spawn to other clients.
|
||||
* @return The spawn player packet.
|
||||
*/
|
||||
public static byte[] spawnPlayerMapobject(MapleCharacter chr) {
|
||||
public static byte[] spawnPlayerMapObject(MapleCharacter chr) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.SPAWN_PLAYER.getValue());
|
||||
mplew.writeInt(chr.getId());
|
||||
@@ -1834,7 +1824,7 @@ public class MaplePacketCreator {
|
||||
|
||||
mplew.writeShort(chr.getJob().getId());
|
||||
|
||||
/* replace "mplew.writeShort(chr.getJob().getId())" with this snippet for 3rd party FJ animation on all classes
|
||||
/* replace "mplew.writeShort(chr.getJob().getId())" with this snippet for 3rd person FJ animation on all classes
|
||||
if (chr.getJob().isA(MapleJob.HERMIT) || chr.getJob().isA(MapleJob.DAWNWARRIOR2) || chr.getJob().isA(MapleJob.NIGHTWALKER2)) {
|
||||
mplew.writeShort(chr.getJob().getId());
|
||||
} else {
|
||||
@@ -1887,14 +1877,106 @@ public class MaplePacketCreator {
|
||||
} else {
|
||||
mplew.write(0);
|
||||
}
|
||||
addRingLook(mplew, chr, true);
|
||||
addRingLook(mplew, chr, false);
|
||||
addRingLook(mplew, chr, true); // crush
|
||||
addRingLook(mplew, chr, false); // friendship
|
||||
addMarriageRingLook(mplew, chr);
|
||||
mplew.skip(3);
|
||||
encodeNewYearCardInfo(mplew, chr); // new year seems to crash sometimes...
|
||||
mplew.skip(2);
|
||||
mplew.write(chr.getTeam());//only needed in specific fields
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
private static void encodeNewYearCardInfo(MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
|
||||
Set<NewYearCardRecord> newyears = chr.getReceivedNewYearRecords();
|
||||
if(!newyears.isEmpty()) {
|
||||
mplew.write(1);
|
||||
|
||||
mplew.writeInt(newyears.size());
|
||||
for(NewYearCardRecord nyc : newyears) {
|
||||
mplew.writeInt(nyc.getId());
|
||||
}
|
||||
} else {
|
||||
mplew.write(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] onNewYearCardRes(MapleCharacter user, int cardId, int mode, int msg) {
|
||||
NewYearCardRecord newyear = user.getNewYearRecord(cardId);
|
||||
return onNewYearCardRes(user, newyear, mode, msg);
|
||||
}
|
||||
|
||||
public static byte[] onNewYearCardRes(MapleCharacter user, NewYearCardRecord newyear, int mode, int msg) {
|
||||
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.NEW_YEAR_CARD_RES.getValue());
|
||||
mplew.write(mode);
|
||||
switch (mode) {
|
||||
case 4: // Successfully sent a New Year Card\r\n to %s.
|
||||
case 6: // Successfully received a New Year Card.
|
||||
encodeNewYearCard(newyear, mplew);
|
||||
break;
|
||||
|
||||
case 8: // Successfully deleted a New Year Card.
|
||||
mplew.writeInt(newyear.getId());
|
||||
break;
|
||||
|
||||
case 5: // Nexon's stupid and makes 4 modes do the same operation..
|
||||
case 7:
|
||||
case 9:
|
||||
case 0xB:
|
||||
// 0x10: You have no free slot to store card.\r\ntry later on please.
|
||||
// 0x11: You have no card to send.
|
||||
// 0x12: Wrong inventory information !
|
||||
// 0x13: Cannot find such character !
|
||||
// 0x14: Incoherent Data !
|
||||
// 0x15: An error occured during DB operation.
|
||||
// 0x16: An unknown error occured !
|
||||
// 0xF: You cannot send a card to yourself !
|
||||
mplew.write(msg);
|
||||
break;
|
||||
|
||||
case 0xA: // GetUnreceivedList_Done
|
||||
int nSN = 1;
|
||||
mplew.writeInt(nSN);
|
||||
if ((nSN - 1) <= 98 && nSN > 0) {//lol nexon are you kidding
|
||||
for (int i = 0; i < nSN; i++) {
|
||||
mplew.writeInt(newyear.getId());
|
||||
mplew.writeInt(newyear.getSenderId());
|
||||
mplew.writeMapleAsciiString(newyear.getSenderName());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC: // NotiArrived
|
||||
mplew.writeInt(newyear.getId());
|
||||
mplew.writeMapleAsciiString(newyear.getSenderName());
|
||||
break;
|
||||
|
||||
case 0xD: // BroadCast_AddCardInfo
|
||||
mplew.writeInt(newyear.getId());
|
||||
mplew.writeInt(user.getId());
|
||||
break;
|
||||
|
||||
case 0xE: // BroadCast_RemoveCardInfo
|
||||
mplew.writeInt(newyear.getId());
|
||||
break;
|
||||
}
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
private static void encodeNewYearCard(NewYearCardRecord newyear, MaplePacketLittleEndianWriter mplew) {
|
||||
mplew.writeInt(newyear.getId());
|
||||
mplew.writeInt(newyear.getSenderId());
|
||||
mplew.writeMapleAsciiString(newyear.getSenderName());
|
||||
mplew.writeBool(newyear.isSenderCardDiscarded());
|
||||
mplew.writeLong(newyear.getDateSent());
|
||||
mplew.writeInt(newyear.getReceiverId());
|
||||
mplew.writeMapleAsciiString(newyear.getReceiverName());
|
||||
mplew.writeBool(newyear.isReceiverCardDiscarded());
|
||||
mplew.writeBool(newyear.isReceiverCardReceived());
|
||||
mplew.writeLong(newyear.getDateReceived());
|
||||
mplew.writeMapleAsciiString(newyear.getMessage());
|
||||
}
|
||||
|
||||
private static void addRingLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr, boolean crush) {
|
||||
List<MapleRing> rings;
|
||||
if (crush) {
|
||||
@@ -1922,15 +2004,17 @@ public class MaplePacketCreator {
|
||||
}
|
||||
|
||||
private static void addMarriageRingLook(final MaplePacketLittleEndianWriter mplew, MapleCharacter chr) {
|
||||
if (chr.getMarriageRing() != null && !chr.getMarriageRing().equipped()) {
|
||||
MapleRing ring = chr.getMarriageRing();
|
||||
|
||||
if (ring != null && !ring.equipped()) {
|
||||
mplew.write(0);
|
||||
return;
|
||||
}
|
||||
mplew.writeBool(chr.getMarriageRing() != null);
|
||||
if (chr.getMarriageRing() != null) {
|
||||
mplew.writeBool(ring != null);
|
||||
if (ring != null) {
|
||||
mplew.writeInt(chr.getId());
|
||||
mplew.writeInt(chr.getMarriageRing().getPartnerChrId());
|
||||
mplew.writeInt(chr.getMarriageRing().getRingId());
|
||||
mplew.writeInt(ring.getPartnerChrId());
|
||||
mplew.writeInt(ring.getRingId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user