Meso patch + Swift Dmg Reflect buff + GPQ Rewards + Starting Q. items
Fixed several RNG pool issues within several handler classes. Fixed an overflow issue with mesos, that would cause players to lose all amount on inventory. Changed the code coupon SQL structure. Now nxcode_items.quantity is to be specified for both nx values and item quantities alike, instead of the use of "quantity" only when items are being provided. Bob Snail now appears each 4 hours, instead of any time. Removed duplicate command Warpto. Warpto merged with Reach command. Fixed solo expeditions being disposed for "lack of personnel" after changing maps (normal limitations should not apply when USE_ENABLE_SOLO_EXPEDITIONS is enabled). Fixed mobskills "Weapon/Magic Reflect" taking too long to show the active status over the mob's head. Fixed a case with clean slate scroll not working as expected. Improved reward contents for the GPQ. Fixed loot manager not acting properly when verifying one-of-a-kind contents. Implemented quest item requirement checkups to start quests. Items required to start a quest now should appear if the player did not start it yet, e.g.: SOS letter. Fixed an issue with server message/boss HPbar switch interaction that would not work the moment after a player changed channels/entered Cash Shop. Improved Victoria Island worldmap design, at the Kerning subway area.
This commit is contained in:
@@ -569,7 +569,7 @@ public class Server {
|
||||
}
|
||||
|
||||
public List<Integer> getActiveCoupons() {
|
||||
synchronized(activeCoupons) {
|
||||
synchronized (activeCoupons) {
|
||||
return activeCoupons;
|
||||
}
|
||||
}
|
||||
@@ -586,7 +586,7 @@ public class Server {
|
||||
|
||||
public void toggleCoupon(Integer couponId) {
|
||||
if(ItemConstants.isRateCoupon(couponId)) {
|
||||
synchronized(activeCoupons) {
|
||||
synchronized (activeCoupons) {
|
||||
if(activeCoupons.contains(couponId)) {
|
||||
activeCoupons.remove(couponId);
|
||||
}
|
||||
@@ -600,7 +600,7 @@ public class Server {
|
||||
}
|
||||
|
||||
public void updateActiveCoupons() throws SQLException {
|
||||
synchronized(activeCoupons) {
|
||||
synchronized (activeCoupons) {
|
||||
activeCoupons.clear();
|
||||
Calendar c = Calendar.getInstance();
|
||||
|
||||
@@ -1669,9 +1669,10 @@ public class Server {
|
||||
}
|
||||
|
||||
private void disconnectIdlesOnLoginState() {
|
||||
List<MapleClient> toDisconnect = new LinkedList<>();
|
||||
|
||||
srvLock.lock();
|
||||
try {
|
||||
List<MapleClient> toDisconnect = new LinkedList<>();
|
||||
long timeNow = System.currentTimeMillis();
|
||||
|
||||
for(Entry<MapleClient, Long> mc : inLoginState.entrySet()) {
|
||||
@@ -1681,17 +1682,19 @@ public class Server {
|
||||
}
|
||||
|
||||
for(MapleClient c : toDisconnect) {
|
||||
if(c.isLoggedIn()) {
|
||||
c.disconnect(false, false);
|
||||
} else {
|
||||
c.getSession().close(true);
|
||||
}
|
||||
|
||||
inLoginState.remove(c);
|
||||
}
|
||||
} finally {
|
||||
srvLock.unlock();
|
||||
}
|
||||
|
||||
for (MapleClient c : toDisconnect) { // thanks Lei for pointing a deadlock issue with srvLock
|
||||
if(c.isLoggedIn()) {
|
||||
c.disconnect(false, false);
|
||||
} else {
|
||||
c.getSession().close(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void disconnectIdlesOnLoginTask() {
|
||||
@@ -1707,75 +1710,73 @@ public class Server {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
srvLock.lock();
|
||||
|
||||
try {
|
||||
System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n");
|
||||
if (getWorlds() == null) return;//already shutdown
|
||||
for (World w : getWorlds()) {
|
||||
w.shutdown();
|
||||
}
|
||||
|
||||
/*for (World w : getWorlds()) {
|
||||
while (w.getPlayerStorage().getAllCharacters().size() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Channel ch : getAllChannels()) {
|
||||
while (ch.getConnectedClients() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
List<Channel> allChannels = getAllChannels();
|
||||
|
||||
if(ServerConstants.USE_THREAD_TRACKER) ThreadTracker.getInstance().cancelThreadTrackerTask();
|
||||
|
||||
for (Channel ch : allChannels) {
|
||||
while (!ch.finishedShutdown()) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resetServerWorlds();
|
||||
|
||||
ThreadManager.getInstance().stop();
|
||||
TimerManager.getInstance().purge();
|
||||
TimerManager.getInstance().stop();
|
||||
|
||||
System.out.println("Worlds + Channels are offline.");
|
||||
acceptor.unbind();
|
||||
acceptor = null;
|
||||
if (!restart) {
|
||||
System.exit(0);
|
||||
} else {
|
||||
System.out.println("\r\nRestarting the server....\r\n");
|
||||
try {
|
||||
instance.finalize();//FUU I CAN AND IT'S FREE
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
instance = null;
|
||||
System.gc();
|
||||
getInstance().init();//DID I DO EVERYTHING?! D:
|
||||
}
|
||||
} finally {
|
||||
srvLock.unlock();
|
||||
}
|
||||
shutdownInternal(restart);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private synchronized void shutdownInternal(boolean restart) {
|
||||
System.out.println((restart ? "Restarting" : "Shutting down") + " the server!\r\n");
|
||||
if (getWorlds() == null) return;//already shutdown
|
||||
for (World w : getWorlds()) {
|
||||
w.shutdown();
|
||||
}
|
||||
|
||||
/*for (World w : getWorlds()) {
|
||||
while (w.getPlayerStorage().getAllCharacters().size() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Channel ch : getAllChannels()) {
|
||||
while (ch.getConnectedClients() > 0) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
List<Channel> allChannels = getAllChannels();
|
||||
|
||||
if(ServerConstants.USE_THREAD_TRACKER) ThreadTracker.getInstance().cancelThreadTrackerTask();
|
||||
|
||||
for (Channel ch : allChannels) {
|
||||
while (!ch.finishedShutdown()) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
System.err.println("FUCK MY LIFE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resetServerWorlds();
|
||||
|
||||
ThreadManager.getInstance().stop();
|
||||
TimerManager.getInstance().purge();
|
||||
TimerManager.getInstance().stop();
|
||||
|
||||
System.out.println("Worlds + Channels are offline.");
|
||||
acceptor.unbind();
|
||||
acceptor = null;
|
||||
if (!restart) {
|
||||
System.exit(0);
|
||||
} else {
|
||||
System.out.println("\r\nRestarting the server....\r\n");
|
||||
try {
|
||||
instance.finalize();//FUU I CAN AND IT'S FREE
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
instance = null;
|
||||
System.gc();
|
||||
getInstance().init();//DID I DO EVERYTHING?! D:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class AdminCommandHandler extends AbstractMaplePacketHandler {
|
||||
int[][] toSpawn = MapleItemInformationProvider.getInstance().getSummonMobs(slea.readInt());
|
||||
for (int z = 0; z < toSpawn.length; z++) {
|
||||
int[] toSpawnChild = toSpawn[z];
|
||||
if (Randomizer.nextInt(101) <= toSpawnChild[1]) {
|
||||
if (Randomizer.nextInt(100) < toSpawnChild[1]) {
|
||||
c.getPlayer().getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(toSpawnChild[0]), c.getPlayer().getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,17 +62,17 @@ public final class CouponCodeHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
ResultSet rs = ps.executeQuery();
|
||||
while (rs.next()) {
|
||||
int type = rs.getInt("type"), item = rs.getInt("item");
|
||||
int type = rs.getInt("type"), quantity = rs.getInt("quantity");
|
||||
|
||||
if (type < 5) {
|
||||
Integer i = couponPoints.get(type);
|
||||
if (i != null) {
|
||||
couponPoints.put(type, i + item);
|
||||
couponPoints.put(type, i + quantity);
|
||||
} else {
|
||||
couponPoints.put(type, item);
|
||||
couponPoints.put(type, quantity);
|
||||
}
|
||||
} else {
|
||||
int quantity = rs.getInt("quantity");
|
||||
int item = rs.getInt("item");
|
||||
|
||||
Integer i = couponItems.get(item);
|
||||
if (i != null) {
|
||||
@@ -108,7 +108,7 @@ public final class CouponCodeHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
if (!couponPoints.isEmpty()) {
|
||||
for (Entry<Integer, Integer> e : couponPoints.entrySet()) {
|
||||
ret.add(new Pair<>(e.getKey(), new Pair<>(e.getValue(), 777)));
|
||||
ret.add(new Pair<>(e.getKey(), new Pair<>(777, e.getValue())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,27 +199,37 @@ public final class CouponCodeHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
for (Pair<Integer, Pair<Integer, Integer>> p : codeRes.getRight()) {
|
||||
type = p.getLeft();
|
||||
int item = p.getRight().getLeft();
|
||||
int quantity = p.getRight().getRight();
|
||||
|
||||
CashShop cs = c.getPlayer().getCashShop();
|
||||
switch (type) {
|
||||
case 0:
|
||||
case 4:
|
||||
cs.gainCash(1, item); //nxCredit
|
||||
cs.gainCash(1, quantity); //nxCredit
|
||||
break;
|
||||
case 1:
|
||||
cs.gainCash(2, item); //maplePoint
|
||||
cs.gainCash(2, quantity); //maplePoint
|
||||
break;
|
||||
case 2:
|
||||
cs.gainCash(4, item); //nxPrepaid
|
||||
cs.gainCash(4, quantity); //nxPrepaid
|
||||
break;
|
||||
case 3:
|
||||
cs.gainCash(1, item);
|
||||
cs.gainCash(4, (item / 5000));
|
||||
cs.gainCash(1, quantity);
|
||||
cs.gainCash(4, (quantity / 5000));
|
||||
break;
|
||||
|
||||
default:
|
||||
short qty = p.getRight().getRight().shortValue();
|
||||
int item = p.getRight().getLeft();
|
||||
|
||||
short qty;
|
||||
if (quantity > Short.MAX_VALUE) {
|
||||
qty = Short.MAX_VALUE;
|
||||
} else if (quantity < Short.MIN_VALUE) {
|
||||
qty = Short.MIN_VALUE;
|
||||
} else {
|
||||
qty = (short) quantity;
|
||||
}
|
||||
|
||||
if (MapleItemInformationProvider.getInstance().isCash(item)) {
|
||||
Item it = CashShop.generateCouponItem(item, qty);
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
chr.closePlayerInteractions();
|
||||
|
||||
chr.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
|
||||
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
|
||||
|
||||
@@ -43,7 +43,7 @@ public final class HealOvertimeHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
short healHP = slea.readShort();
|
||||
if (healHP != 0) {
|
||||
abm.setTimestamp(8, timestamp, 4); // thanks Vcoc for pointing out d/c happening here
|
||||
abm.setTimestamp(8, timestamp, 28); // thanks Vcoc & Thora for pointing out d/c happening here
|
||||
if ((abm.getLastSpam(0) + 1500) > timestamp) AutobanFactory.FAST_HP_HEALING.addPoint(abm, "Fast hp healing");
|
||||
|
||||
int abHeal = 120 + (int)(20 * MapleMapFactory.getMapRecoveryRate(chr.getMapId())); // Sleepywood sauna and showa spa...
|
||||
@@ -58,7 +58,7 @@ public final class HealOvertimeHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
short healMP = slea.readShort();
|
||||
if (healMP != 0 && healMP < 1000) {
|
||||
abm.setTimestamp(9, timestamp, 4);
|
||||
abm.setTimestamp(9, timestamp, 28);
|
||||
if ((abm.getLastSpam(1) + 1500) > timestamp) AutobanFactory.FAST_MP_HEALING.addPoint(abm, "Fast mp healing");
|
||||
chr.addMP(healMP);
|
||||
abm.spam(1, timestamp);
|
||||
|
||||
@@ -37,7 +37,9 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan - header layout courtesy of Eric
|
||||
* @author Ronan
|
||||
*
|
||||
* Header layout thanks to Eric
|
||||
*/
|
||||
public final class NewYearCardHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class PetCommandHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Randomizer.nextInt(101) <= petCommand.getProbability()) {
|
||||
if (Randomizer.nextInt(100) < petCommand.getProbability()) {
|
||||
pet.gainClosenessFullness(chr, petCommand.getIncrease(), 0, command);
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.commandResponse(chr.getId(), petIndex, false, command, false));
|
||||
} else {
|
||||
|
||||
@@ -36,7 +36,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
*/
|
||||
public final class QuestActionHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
// isNpcNearby credits to gabriel.sin
|
||||
// isNpcNearby credits to GabrielSin
|
||||
private static boolean isNpcNearby(SeekableLittleEndianAccessor slea, MapleCharacter player, MapleQuest quest, int npcId) {
|
||||
Point playerP = null;
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
|
||||
Item wscroll = null;
|
||||
|
||||
if (ItemConstants.isCleanSlate(scroll.getItemId())) {
|
||||
Map<String, Integer> eqStats = ii.getEquipStats(scroll.getItemId());
|
||||
Map<String, Integer> eqStats = ii.getEquipStats(toScroll.getItemId()); // clean slate issue found thanks to Masterrulax
|
||||
if (eqStats == null || eqStats.get("tuc") == 0) {
|
||||
c.announce(MaplePacketCreator.getInventoryFull());
|
||||
return;
|
||||
|
||||
@@ -106,7 +106,7 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
||||
for (loseItem loseItem : loseItems) {
|
||||
type = ItemConstants.getInventoryType(loseItem.getId());
|
||||
for (byte b = 0; b < loseItem.getX(); b++) {//LOL?
|
||||
if (Randomizer.nextInt(101) >= loseItem.getChance()) {
|
||||
if (Randomizer.nextInt(100) < loseItem.getChance()) {
|
||||
if (chr.haveItem(loseItem.getId())) {
|
||||
pos.x = (int) (playerpos + ((d % 2 == 0) ? (25 * (d + 1) / 2) : -(25 * (d / 2))));
|
||||
MapleInventoryManipulator.removeById(c, type, loseItem.getId(), 1, false, false);
|
||||
|
||||
14
src/net/server/channel/handlers/UseItemCanvasHandler.java
Normal file
14
src/net/server/channel/handlers/UseItemCanvasHandler.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
public final class UseItemCanvasHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public final class UseSummonBagHandler extends AbstractMaplePacketHandler {
|
||||
int[][] toSpawn = MapleItemInformationProvider.getInstance().getSummonMobs(itemId);
|
||||
for (int z = 0; z < toSpawn.length; z++) {
|
||||
int[] toSpawnChild = toSpawn[z];
|
||||
if (Randomizer.nextInt(101) <= toSpawnChild[1]) {
|
||||
if (Randomizer.nextInt(100) < toSpawnChild[1]) {
|
||||
c.getPlayer().getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(toSpawnChild[0]), c.getPlayer().getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user