Heal GMS + Improved chnl workers & Pshop tooltip + Equips on party HP

Slightly improved channel and disease announce workers performance.
Completion of repeatable quests no longer generates fame to players.
Equipment drop rates of Leprechaun were slightly decreased.
Fixed Pet Item Ignore not checking certain exploit cases correctly.
Optimized Pet Item Ignore server handler performance.
Fixed some exploits and improved performance on PetLootHandler.
Improved concurrency protection on MapleInventoryManipulator.
Heal skill effect on players now works GMS-intended, as description says. Also removed the delayed Heal cast effect to others.
Fixed party player HPBar not accounting the player's HP stat gained on equips towards the effective MaxHP.
The duration of mists generated by mobs has been rescaled to 10x longer than what has been displayed until now (wz duration property is supposed to actually be in 100ms).
Optimized timer management for mob skill cooldown and elemental effectiveness.
Implemented an additional inventory check system, to be used in cases where it's expected to remove a set group for items (with quantity) to then add a new group of items.
Fixed Player Shop/Hired Merchant "vacancy" tooltip, now properly showing whether the store has a visitor room or is already full at that time.
Fixed Player Shops only using the standard stand type.
Fixed cash pet food ignoring certain pet itemids when reading data from WZ.
This commit is contained in:
ronancpl
2018-07-21 14:40:46 -03:00
parent 3752ebbae5
commit bee8b5259b
78 changed files with 1194 additions and 628 deletions
+6 -1
View File
@@ -32,7 +32,7 @@ PQs:
Skills: Skills:
* Some skills behaving oddly have been patched, such as Steal, Venomous Star/Stab and Mystic Doors. * Some skills behaving oddly have been patched, such as Steal, Venomous Star/Stab, Heal and Mystic Doors.
* Maker skill features properly developed. * Maker skill features properly developed.
* Improved current Battleship skill, now showing the HP properly on buff tab and making visible for others after changing maps. * Improved current Battleship skill, now showing the HP properly on buff tab and making visible for others after changing maps.
* Server is using heuristics to calculate fee costs for the Maker (errors sums up to 8k mesos, reagent errors stacks up comformant with it's level). * Server is using heuristics to calculate fee costs for the Maker (errors sums up to 8k mesos, reagent errors stacks up comformant with it's level).
@@ -59,7 +59,9 @@ Player Social Network:
* Guild and Alliance system fully functional. * Guild and Alliance system fully functional.
* Implemented Marriage system from the ground-up (excluding character packet encoding parts that were already present, proper credits given throughout the source files). * Implemented Marriage system from the ground-up (excluding character packet encoding parts that were already present, proper credits given throughout the source files).
* Beginners can create and join a "beginner-only" party (characters up to level 10). * Beginners can create and join a "beginner-only" party (characters up to level 10).
* HP bar of party members now properly calculates the HP gain from equipments.
* Enhanced synchronization on Player Shops and Hired Merchants. Transactions made are instantly informed to the owner. * Enhanced synchronization on Player Shops and Hired Merchants. Transactions made are instantly informed to the owner.
* Player Shops and Hired Merchants properly displaying the correct shop image to other players, and informing whether the shop is available to visit or full.
* Game minirooms such as match cards and omok now has a functional password system. * Game minirooms such as match cards and omok now has a functional password system.
* Item pickup cooldown on non-owned/non-partyowned items functional. * Item pickup cooldown on non-owned/non-partyowned items functional.
* Further improved the server's ranking system, now displaying properly daily player ranking movement. * Further improved the server's ranking system, now displaying properly daily player ranking movement.
@@ -134,6 +136,8 @@ Server potentials:
* Enhanced auto-pot system: pet uses as many potions as necessary to reach the desired threshold. * Enhanced auto-pot system: pet uses as many potions as necessary to reach the desired threshold.
* Enhanced buff system: smartly checks for the best available buff effects to be active on the player. * Enhanced buff system: smartly checks for the best available buff effects to be active on the player.
* Enhanced AP auto-assigner: exactly matches AP with the needed for the player's current level, surplus assigned to the primary attribute. * Enhanced AP auto-assigner: exactly matches AP with the needed for the player's current level, surplus assigned to the primary attribute.
* Enhanced inventory check: free slots on inventory smartly fetched on demand.
* Enhanced auto-loot handler: optimized the brute-force checks for some cash items on the player equipped inventory at every requisition.
* Tweaked pet/mount hunger: calculations for fullness/tiredness takes active time of the subject into account. * Tweaked pet/mount hunger: calculations for fullness/tiredness takes active time of the subject into account.
* Consistent experience gain system. * Consistent experience gain system.
* NPC crafters (equips, plates/jewels, etc) now won't take items freely if the requirement conditions are not properly met. * NPC crafters (equips, plates/jewels, etc) now won't take items freely if the requirement conditions are not properly met.
@@ -150,6 +154,7 @@ Server potentials:
* Centralized getcurrenttime throughout several server handlers, boosting it's performance overall. * Centralized getcurrenttime throughout several server handlers, boosting it's performance overall.
* Autosaver (periodically saves on DB current state of every player in-game). * Autosaver (periodically saves on DB current state of every player in-game).
* Both fixed and randomized versions of HP/MP growth rate available, regarding player job (enable one at ServerConstants). Placeholder for HP/MP washing feature. * Both fixed and randomized versions of HP/MP growth rate available, regarding player job (enable one at ServerConstants). Placeholder for HP/MP washing feature.
* Implemented methods to get the current Players' MaxHP/MaxMP method with equipment HP/MP gains already summed up.
* Reallocated mapobjectids utilization throughout the source, preventing issues such as "NPC disappearing mysteriously after some server time" from happening. * Reallocated mapobjectids utilization throughout the source, preventing issues such as "NPC disappearing mysteriously after some server time" from happening.
* Implemented old GMS statup mechanic for novices level 10 or below. Usage of the edited localhost is mandatory on this. * Implemented old GMS statup mechanic for novices level 10 or below. Usage of the edited localhost is mandatory on this.
* Accounts can be created automatically when trying to login on an inexistent account -- credits to shavit. * Accounts can be created automatically when trying to login on an inexistent account -- credits to shavit.
+20
View File
@@ -1144,3 +1144,23 @@ Nova ferramenta: MapleInvalidItemWithNoNameFetcher. Busca por itemids sem as pro
17 Julho 2018, 17 Julho 2018,
Corrigido problema crítico no novo sistema de login, que impedia contas recém-criadas de logar no jogo. Corrigido problema crítico no novo sistema de login, que impedia contas recém-criadas de logar no jogo.
18 - 19 Julho 2018,
Suavemente otimizado desempenho geral de channel workers e disease announce worker.
Quests repetiveis no mesmo dia não geram fama.
Equip drops de Leprechaun mais raros de aparecer (chance 2000 -> 1200).
Corrigido Pet Item Ignore não checando certos casos corretamente e otimizado busca nos handlers pelos cash itens equipados.
Corrigido alguns exploits e otimizado alguns recursos usados pelo PetLootHandler.
Protegido contra acesso concorrente certos trechos de código críticos do MapleInventoryManipulator.
Corrigido Heal para contabilizar ganho de HP GMS-like.
Corrigido efeito de Heal para outros atuando extremamente lento.
Corrigido maxHP sendo mostrado nas barras de HP de colegas de party para mostrar o HP efetivo (maxhp + aumento de HP equipado).
Duração da mist foi rescalado pra 10x mais que a duração passada (wz representa duração de mist em 100ms).
Otimizado manutenção de temporizadores em cooldown de skills de mobs e em elemental effectiveness.
Implementado um sistema adicional de checagem de slots disponíveis no inventário, para casos onde se espera retirada de um vetor de (itemid, quantidade) para inserção de outro vetor de (itemid, quantidade).
20 Julho 2018,
Corrigido tooltip de player shops e hired merchants, agora com ícone mostrando se há como visitar uma loja ou está ocupada.
Corrigido player shop permits diferentes do comum não sendo consumidos ao usar.
Corrigido player shop sempre aparecendo como o tipo básico (sem estandes), para qualquer permit itemid.
Corrigido cash pet food ignorando certos petids ao ler dados do WZ.
+88
View File
@@ -0,0 +1,88 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <[email protected]>
Matthias Butz <[email protected]>
Jan Christian Meyer <[email protected]>
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/>.
*/
//Time Setting is in millisecond
var beginTime = 60 * 1000; //The time to begin the ride
var rideTime = 60 * 1000; //The time that require move to destination
function init() {
beginTime = em.getTransportationTime(beginTime);
rideTime = em.getTransportationTime(rideTime);
em.getChannelServer().getMapFactory().getMap(222020100).resetReactors();
em.getChannelServer().getMapFactory().getMap(222020200).resetReactors();
scheduleNew();
}
function scheduleNew() {
em.setProperty("goingUp", "false");
em.setProperty("goingDown", "true");
em.getChannelServer().getMapFactory().getMap(222020100).resetReactors();
em.getChannelServer().getMapFactory().getMap(222020200).setReactorState();
em.schedule("goingUpNow", beginTime);
}
function goUp() {
em.schedule("goingUpNow", beginTime);
}
function goDown() {
em.schedule("goingDownNow", beginTime);
}
function goingUpNow() {
em.getChannelServer().getMapFactory().getMap(222020110).warpEveryone(222020111);
em.setProperty("goingUp", "true");
em.schedule("isUpNow", rideTime);
em.getChannelServer().getMapFactory().getMap(222020100).setReactorState();
}
function goingDownNow() {
em.getChannelServer().getMapFactory().getMap(222020210).warpEveryone(222020211);
em.setProperty("goingDown", "true");
em.schedule("isDownNow", rideTime);
em.getChannelServer().getMapFactory().getMap(222020200).setReactorState();
}
function isUpNow() {
em.setProperty("goingDown", "false"); // clear
em.getChannelServer().getMapFactory().getMap(222020200).resetReactors();
em.getChannelServer().getMapFactory().getMap(222020111).warpEveryone(222020200, 0);
goDown();
}
function isDownNow() {
em.setProperty("goingUp", "false"); // clear
em.getChannelServer().getMapFactory().getMap(222020100).resetReactors();
em.getChannelServer().getMapFactory().getMap(222020211).warpEveryone(222020100, 4);
goUp();
}
function cancelSchedule() {
}
+1 -1
View File
@@ -146,7 +146,7 @@ function refineItems(refineType) {
itemqty = refineQty * 10; itemqty = refineQty * 10;
var fee = getRefineFee(refineFees[refineType][(itemid % 100) | 0] * refineQty); var fee = getRefineFee(refineFees[refineType][(itemid % 100) | 0] * refineQty);
if(cm.canHold(itemid + 1000, refineQty) && cm.getMeso() >= fee) { if(cm.canHold(itemid + 1000, refineQty, itemid, itemqty) && cm.getMeso() >= fee) {
cm.gainMeso(-fee); cm.gainMeso(-fee);
cm.gainItem(itemid, -itemqty); cm.gainItem(itemid, -itemqty);
cm.gainItem(itemid + (itemid != 4010007 ? 1000 : 1001), refineQty); cm.gainItem(itemid + (itemid != 4010007 ? 1000 : 1001), refineQty);
+1 -1
View File
@@ -146,7 +146,7 @@ function refineItems(refineType) {
itemqty = refineQty * 10; itemqty = refineQty * 10;
var fee = getRefineFee(refineFees[refineType][(itemid % 100) | 0] * refineQty); var fee = getRefineFee(refineFees[refineType][(itemid % 100) | 0] * refineQty);
if(cm.canHold(itemid + 1000, refineQty) && cm.getMeso() >= fee) { if(cm.canHold(itemid + 1000, refineQty, itemid, itemqty) && cm.getMeso() >= fee) {
cm.gainMeso(-fee); cm.gainMeso(-fee);
cm.gainItem(itemid, -itemqty); cm.gainItem(itemid, -itemqty);
cm.gainItem(itemid + (itemid != 4010007 ? 1000 : 1001), refineQty); cm.gainItem(itemid + (itemid != 4010007 ? 1000 : 1001), refineQty);
+1 -1
View File
@@ -146,7 +146,7 @@ function refineItems(refineType) {
itemqty = refineQty * 10; itemqty = refineQty * 10;
var fee = getRefineFee(refineFees[refineType][(itemid % 100) | 0] * refineQty); var fee = getRefineFee(refineFees[refineType][(itemid % 100) | 0] * refineQty);
if(cm.canHold(itemid + 1000, refineQty) && cm.getMeso() >= fee) { if(cm.canHold(itemid + 1000, refineQty, itemid, itemqty) && cm.getMeso() >= fee) {
cm.gainMeso(-fee); cm.gainMeso(-fee);
cm.gainItem(itemid, -itemqty); cm.gainItem(itemid, -itemqty);
cm.gainItem(itemid + (itemid != 4010007 ? 1000 : 1001), refineQty); cm.gainItem(itemid + (itemid != 4010007 ? 1000 : 1001), refineQty);
+6 -1
View File
@@ -51,6 +51,7 @@ function writeFeatureTab_PQs() {
function writeFeatureTab_Skills() { function writeFeatureTab_Skills() {
addFeature("Reviewed many skills, such as Steal and M. Door."); addFeature("Reviewed many skills, such as Steal and M. Door.");
addFeature("Heal GMS-like: fixed HP gain & Heal skill packet.");
addFeature("Improved battleship: HP visible and map-persistent."); addFeature("Improved battleship: HP visible and map-persistent.");
addFeature("Maker skill features properly developed."); addFeature("Maker skill features properly developed.");
addFeature("Chair Mastery - map chair boosts HP/MP rec."); addFeature("Chair Mastery - map chair boosts HP/MP rec.");
@@ -71,6 +72,7 @@ function writeFeatureTab_Quests() {
function writeFeatureTab_PlayerSocialNetwork() { function writeFeatureTab_PlayerSocialNetwork() {
addFeature("Guild and Alliance system fully functional."); addFeature("Guild and Alliance system fully functional.");
addFeature("Party for novices-only."); addFeature("Party for novices-only.");
addFeature("P. members' HPBar accounts HP gain on equips.");
addFeature("Thoroughly reviewed P. Shops and H. Merchants."); addFeature("Thoroughly reviewed P. Shops and H. Merchants.");
addFeature("Transactions on Merchs instantly announced to owner."); addFeature("Transactions on Merchs instantly announced to owner.");
addFeature("Game minirooms with functional pw system."); addFeature("Game minirooms with functional pw system.");
@@ -149,6 +151,8 @@ function writeFeatureTab_Serverpotentials() {
addFeature("Enhanced auto-pot system: smart pet potion handle."); addFeature("Enhanced auto-pot system: smart pet potion handle.");
addFeature("Enhanced buff system: best buffs effects takes place."); addFeature("Enhanced buff system: best buffs effects takes place.");
addFeature("Enhanced AP auto-assigner: focus on eqp demands."); addFeature("Enhanced AP auto-assigner: focus on eqp demands.");
addFeature("Enhanced inventory check: free slots smartly fetched.");
addFeature("Enhanced petloot handler: no brute-force inv. checks.");
addFeature("Tweaked pet/mount hunger to a balanced growth rate."); addFeature("Tweaked pet/mount hunger to a balanced growth rate.");
addFeature("Consistent experience gain system."); addFeature("Consistent experience gain system.");
addFeature("NPC crafters won't take items freely anymore."); addFeature("NPC crafters won't take items freely anymore.");
@@ -165,6 +169,7 @@ function writeFeatureTab_Serverpotentials() {
addFeature("Centralized servertime, boosting handler performance."); addFeature("Centralized servertime, boosting handler performance.");
addFeature("Autosaver (periodically saves player's data on DB)."); addFeature("Autosaver (periodically saves player's data on DB).");
addFeature("Fixed and randomized HP/MP growth rate available."); addFeature("Fixed and randomized HP/MP growth rate available.");
addFeature("Players' MaxHP/MaxMP method accounting equip gain.");
addFeature("Prevented 'NPC gone after some uptime' issue."); addFeature("Prevented 'NPC gone after some uptime' issue.");
addFeature("Implemented starters' AP assigning for under level 11."); addFeature("Implemented starters' AP assigning for under level 11.");
addFeature("AP assigning available for novices level 10 or below."); addFeature("AP assigning available for novices level 10 or below.");
@@ -202,7 +207,7 @@ function writeFeatureTab_Localhostedits() {
function writeFeatureTab_Project() { function writeFeatureTab_Project() {
addFeature("Organized project code."); addFeature("Organized project code.");
addFeature("Highly updated drop data."); addFeature("Highly updated drop data.");
addFeature("Highly configurable server."); addFeature("Highly configurable & optimized server.");
addFeature("Fixed/added many missing packet opcodes."); addFeature("Fixed/added many missing packet opcodes.");
addFeature("Uncovered many opcodes throughout the source."); addFeature("Uncovered many opcodes throughout the source.");
addFeature("Reviewed many Java aspects that needed attention."); addFeature("Reviewed many Java aspects that needed attention.");
+3 -1
View File
@@ -77,6 +77,7 @@ function writeHeavenMSCommandsLv5() { //Developer
addCommand("debugplayercoupons", ""); addCommand("debugplayercoupons", "");
addCommand("debugtimer", ""); addCommand("debugtimer", "");
addCommand("debugmarriage", ""); addCommand("debugmarriage", "");
addCommand("showpackets", "");
addCommand("set", ""); addCommand("set", "");
} }
@@ -99,7 +100,7 @@ function writeHeavenMSCommandsLv4() { //SuperGM
addCommand("pap", ""); addCommand("pap", "");
addCommand("pianus", ""); addCommand("pianus", "");
addCommand("cake", ""); addCommand("cake", "");
addCommand("pnpcremove", ""); addCommand("playernpcremove", "");
addCommand("playernpc", ""); addCommand("playernpc", "");
} }
@@ -117,6 +118,7 @@ function writeHeavenMSCommandsLv3() { //GM
addCommand("reloaddrops", ""); addCommand("reloaddrops", "");
addCommand("reloadportals", ""); addCommand("reloadportals", "");
addCommand("reloadmap", ""); addCommand("reloadmap", "");
addCommand("reloadshops", "");
addCommand("hpmp", ""); addCommand("hpmp", "");
addCommand("maxhpmp", ""); addCommand("maxhpmp", "");
addCommand("music", ""); addCommand("music", "");
+16 -16
View File
@@ -19613,22 +19613,22 @@ USE `heavenms`;
(9400583, 2041030, 1, 1, 0, 5000), (9400583, 2041030, 1, 1, 0, 5000),
(9400583, 4006000, 1, 1, 0, 20000), (9400583, 4006000, 1, 1, 0, 20000),
(9400583, 2070005, 1, 1, 0, 400), (9400583, 2070005, 1, 1, 0, 400),
(9400583, 1002391, 1, 1, 0, 2000), (9400583, 1002391, 1, 1, 0, 1200),
(9400583, 1302096, 1, 1, 0, 2000), (9400583, 1302096, 1, 1, 0, 1200),
(9400583, 1041099, 1, 1, 0, 2000), (9400583, 1041099, 1, 1, 0, 1200),
(9400583, 1422012, 1, 1, 0, 2000), (9400583, 1422012, 1, 1, 0, 1200),
(9400583, 1412004, 1, 1, 0, 2000), (9400583, 1412004, 1, 1, 0, 1200),
(9400583, 1051010, 1, 1, 0, 2000), (9400583, 1051010, 1, 1, 0, 1200),
(9400583, 1051058, 1, 1, 0, 2000), (9400583, 1051058, 1, 1, 0, 1200),
(9400583, 1082056, 1, 1, 0, 2000), (9400583, 1082056, 1, 1, 0, 1200),
(9400583, 1092029, 1, 1, 0, 2000), (9400583, 1092029, 1, 1, 0, 1200),
(9400583, 1382010, 1, 1, 0, 2000), (9400583, 1382010, 1, 1, 0, 1200),
(9400583, 1072114, 1, 1, 0, 2000), (9400583, 1072114, 1, 1, 0, 1200),
(9400583, 1050064, 1, 1, 0, 2000), (9400583, 1050064, 1, 1, 0, 1200),
(9400583, 1002276, 1, 1, 0, 2000), (9400583, 1002276, 1, 1, 0, 1200),
(9400583, 1050077, 1, 1, 0, 2000), (9400583, 1050077, 1, 1, 0, 1200),
(9400583, 1061101, 1, 1, 0, 2000), (9400583, 1061101, 1, 1, 0, 1200),
(9400583, 1002328, 1, 1, 0, 2000), (9400583, 1002328, 1, 1, 0, 1200),
(9400549, 0, 2000, 3000, 0, 400000), (9400549, 0, 2000, 3000, 0, 400000),
(9400638, 0, 100, 200, 0, 400000), (9400638, 0, 100, 200, 0, 400000),
(9400638, 4011007, 1, 1, 0, 1000), (9400638, 4011007, 1, 1, 0, 1000),
+81 -18
View File
@@ -64,7 +64,6 @@ import net.server.world.PartyOperation;
import net.server.world.World; import net.server.world.World;
import scripting.event.EventInstanceManager; import scripting.event.EventInstanceManager;
import server.CashShop; import server.CashShop;
import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
import server.MaplePortal; import server.MaplePortal;
import server.MapleShop; import server.MapleShop;
@@ -104,7 +103,6 @@ import tools.FilePrinter;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.Randomizer; import tools.Randomizer;
import tools.locks.MonitoredReentrantLock;
import tools.packets.Wedding; import tools.packets.Wedding;
import client.autoban.AutobanManager; import client.autoban.AutobanManager;
import client.creator.CharacterFactoryRecipe; import client.creator.CharacterFactoryRecipe;
@@ -112,11 +110,13 @@ import client.inventory.Equip;
import client.inventory.Item; import client.inventory.Item;
import client.inventory.ItemFactory; import client.inventory.ItemFactory;
import client.inventory.MapleInventory; import client.inventory.MapleInventory;
import client.inventory.MapleInventoryProof;
import client.inventory.MapleInventoryType; import client.inventory.MapleInventoryType;
import client.inventory.MaplePet; import client.inventory.MaplePet;
import client.inventory.MapleWeaponType; import client.inventory.MapleWeaponType;
import client.inventory.ModifyInventory; import client.inventory.ModifyInventory;
import client.inventory.PetDataFactory; import client.inventory.PetDataFactory;
import client.inventory.manipulator.MapleInventoryManipulator;
import client.newyear.NewYearCardRecord; import client.newyear.NewYearCardRecord;
import constants.ExpTable; import constants.ExpTable;
import constants.GameConstants; import constants.GameConstants;
@@ -156,7 +156,8 @@ import constants.skills.ThunderBreaker;
import net.server.channel.handlers.PartyOperationHandler; import net.server.channel.handlers.PartyOperationHandler;
import scripting.item.ItemScriptManager; import scripting.item.ItemScriptManager;
import server.maps.MapleMapItem; import server.maps.MapleMapItem;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
public class MapleCharacter extends AbstractAnimatedMapleMapObject { public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
@@ -168,7 +169,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private int world; private int world;
private int accountid, id; private int accountid, id;
private int rank, rankMove, jobRank, jobRankMove; private int rank, rankMove, jobRank, jobRankMove;
private int level, str, dex, luk, int_, hp, maxhp, mp, maxmp; private int level, str, dex, luk, int_, hp, maxhp, eqphp, mp, maxmp, eqpmp;
private int hpMpApUsed; private int hpMpApUsed;
private int hair; private int hair;
private int face; private int face;
@@ -202,6 +203,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private long lastfametime, lastUsedCashItem, lastExpression = 0, lastHealed, lastBuyback = 0, lastDeathtime, lastMesoDrop = -1, jailExpiration = -1; private long lastfametime, lastUsedCashItem, lastExpression = 0, lastHealed, lastBuyback = 0, lastDeathtime, lastMesoDrop = -1, jailExpiration = -1;
private transient int localmaxhp, localmaxmp, localstr, localdex, localluk, localint_, magic, watk; private transient int localmaxhp, localmaxmp, localstr, localdex, localluk, localint_, magic, watk;
private boolean hidden, canDoor = true, berserk, hasMerchant, hasSandboxItem = false, whiteChat = false; private boolean hidden, canDoor = true, berserk, hasMerchant, hasSandboxItem = false, whiteChat = false;
private boolean equippedMesoMagnet = false, equippedItemPouch = false, equippedPetItemIgnore = false;
private int linkedLevel = 0; private int linkedLevel = 0;
private String linkedName = null; private String linkedName = null;
private boolean finishedDojoTutorial; private boolean finishedDojoTutorial;
@@ -325,6 +327,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
for (int i = 0; i < remainingSp.length; i++) { for (int i = 0; i < remainingSp.length; i++) {
remainingSp[i] = 0; remainingSp[i] = 0;
} }
for (MapleInventoryType type : MapleInventoryType.values()) { for (MapleInventoryType type : MapleInventoryType.values()) {
byte b = 24; byte b = 24;
if (type == MapleInventoryType.CASH) { if (type == MapleInventoryType.CASH) {
@@ -332,6 +335,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
} }
inventory[type.ordinal()] = new MapleInventory(this, type, (byte) b); inventory[type.ordinal()] = new MapleInventory(this, type, (byte) b);
} }
inventory[MapleInventoryType.CANHOLD.ordinal()] = new MapleInventoryProof(this);
for (int i = 0; i < SavedLocationType.values().length; i++) { for (int i = 0; i < SavedLocationType.values().length; i++) {
savedLocations[i] = null; savedLocations[i] = null;
} }
@@ -4393,6 +4398,18 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return maxhp; return maxhp;
} }
public int getMaxMp() {
return maxmp;
}
public int getMaxHpEquipped() {
return Math.min(maxhp + eqphp, 30000);
}
public int getMaxMpEquipped() {
return Math.min(maxmp + eqpmp, 30000);
}
public int getMaxClassLevel() { public int getMaxClassLevel() {
return isCygnus() ? 120 : 200; return isCygnus() ? 120 : 200;
} }
@@ -4405,10 +4422,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return GameConstants.getJobMaxLevel(job); return GameConstants.getJobMaxLevel(job);
} }
public int getMaxMp() {
return maxmp;
}
public int getMeso() { public int getMeso() {
return meso.get(); return meso.get();
} }
@@ -4693,7 +4706,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
this.setMiniGame(null); this.setMiniGame(null);
if (game.isOwner(this)) { if (game.isOwner(this)) {
this.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(this)); this.getMap().broadcastMessage(MaplePacketCreator.removeMinigameBox(this));
game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose(3)); game.broadcastToVisitor(MaplePacketCreator.getMiniGameClose(3));
} else { } else {
game.removeVisitor(this); game.removeVisitor(this);
@@ -5176,8 +5189,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setInt(1, getId()); ps.setInt(1, getId());
ps.setInt(2, to.getId()); ps.setInt(2, to.getId());
ps.executeUpdate(); ps.executeUpdate();
} } finally {
finally {
con.close(); con.close();
} }
} catch (SQLException e) { } catch (SQLException e) {
@@ -6610,7 +6622,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (partychar.getMapId() == mapId && partychar.getChannel() == channel) { if (partychar.getMapId() == mapId && partychar.getChannel() == channel) {
MapleCharacter other = Server.getInstance().getWorld(world).getChannel(channel).getPlayerStorage().getCharacterByName(partychar.getName()); MapleCharacter other = Server.getInstance().getWorld(world).getChannel(channel).getPlayerStorage().getCharacterByName(partychar.getName());
if (other != null) { if (other != null) {
client.announce(MaplePacketCreator.updatePartyMemberHP(other.getId(), other.getHp(), other.getCurrentMaxHp())); client.announce(MaplePacketCreator.updatePartyMemberHP(other.getId(), other.getHp(), other.getMaxHpEquipped()));
} }
} }
} }
@@ -7388,7 +7400,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
ps.setString(1, to); ps.setString(1, to);
ps.setString(2, this.getName()); ps.setString(2, this.getName());
ps.setString(3, msg); ps.setString(3, msg);
ps.setLong(4, System.currentTimeMillis()); ps.setLong(4, Server.getInstance().getCurrentTime());
ps.setByte(5, fame); ps.setByte(5, fame);
ps.executeUpdate(); ps.executeUpdate();
} finally { } finally {
@@ -8149,11 +8161,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
int channel = client.getChannel(); int channel = client.getChannel();
int mapId = getMapId(); int mapId = getMapId();
int curmaxhp = getMaxHpEquipped();
for (MaplePartyCharacter partychar : party.getMembers()) { for (MaplePartyCharacter partychar : party.getMembers()) {
if (partychar.getMapId() == mapId && partychar.getChannel() == channel) { if (partychar.getMapId() == mapId && partychar.getChannel() == channel) {
MapleCharacter other = Server.getInstance().getWorld(world).getChannel(channel).getPlayerStorage().getCharacterByName(partychar.getName()); MapleCharacter other = Server.getInstance().getWorld(world).getChannel(channel).getPlayerStorage().getCharacterByName(partychar.getName());
if (other != null) { if (other != null) {
other.client.announce(MaplePacketCreator.updatePartyMemberHP(getId(), this.hp, maxhp)); other.client.announce(MaplePacketCreator.updatePartyMemberHP(getId(), this.hp, curmaxhp));
} }
} }
} }
@@ -8202,8 +8215,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
} }
announce(MaplePacketCreator.updateQuestInfo((short) quest.getQuest().getId(), quest.getNpc())); announce(MaplePacketCreator.updateQuestInfo((short) quest.getQuest().getId(), quest.getNpc()));
} else if (quest.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) { } else if (quest.getStatus().equals(MapleQuestStatus.Status.COMPLETED)) {
short questid = quest.getQuest().getId(); MapleQuest mquest = quest.getQuest();
if(!MapleQuest.isExploitableQuest(questid)) { short questid = mquest.getId();
if(!mquest.isSameDayRepeatable() && !MapleQuest.isExploitableQuest(questid)) {
quest_fame += 1; quest_fame += 1;
if(ServerConstants.FAME_GAIN_BY_QUEST > 0) if(ServerConstants.FAME_GAIN_BY_QUEST > 0)
fameGainByQuest(); fameGainByQuest();
@@ -8679,7 +8693,56 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return autoban; return autoban;
} }
public void equipPendantOfSpirit() { public void resetEquippedHpMp() {
eqphp = 0;
eqpmp = 0;
}
public void equippedItem(Equip equip) {
int itemid = equip.getItemId();
eqphp += equip.getHp();
eqpmp += equip.getMp();
if (itemid == 1122017) {
this.equipPendantOfSpirit();
} else if (itemid == 1812000) { // meso magnet
equippedMesoMagnet = true;
} else if (itemid == 1812001) { // item pouch
equippedItemPouch = true;
} else if (itemid == 1812007) { // item ignore pendant
equippedPetItemIgnore = true;
}
}
public void unequippedItem(Equip equip) {
int itemid = equip.getItemId();
eqphp -= equip.getHp();
eqpmp -= equip.getMp();
if (itemid == 1122017) {
this.unequipPendantOfSpirit();
} else if (itemid == 1812000) { // meso magnet
equippedMesoMagnet = false;
} else if (itemid == 1812001) { // item pouch
equippedItemPouch = false;
} else if (itemid == 1812007) { // item ignore pendant
equippedPetItemIgnore = false;
}
}
public boolean isEquippedMesoMagnet() {
return equippedMesoMagnet;
}
public boolean isEquippedItemPouch() {
return equippedItemPouch;
}
public boolean isEquippedPetItemIgnore() {
return equippedPetItemIgnore;
}
private void equipPendantOfSpirit() {
if (pendantOfSpirit == null) { if (pendantOfSpirit == null) {
pendantOfSpirit = TimerManager.getInstance().register(new Runnable() { pendantOfSpirit = TimerManager.getInstance().register(new Runnable() {
@Override @Override
@@ -8695,7 +8758,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
} }
} }
public void unequipPendantOfSpirit() { private void unequipPendantOfSpirit() {
if (pendantOfSpirit != null) { if (pendantOfSpirit != null) {
pendantOfSpirit.cancel(false); pendantOfSpirit.cancel(false);
pendantOfSpirit = null; pendantOfSpirit = null;
+3 -3
View File
@@ -44,7 +44,6 @@ import java.util.Set;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.*; import tools.*;
import tools.locks.MonitoredReentrantLock;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
@@ -74,7 +73,9 @@ import server.life.MapleMonster;
import server.MapleTrade; import server.MapleTrade;
import server.maps.*; import server.maps.*;
import server.quest.MapleQuest; import server.quest.MapleQuest;
import tools.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
public class MapleClient { public class MapleClient {
@@ -806,7 +807,6 @@ public class MapleClient {
if (player.getMap() != null) { if (player.getMap() != null) {
int mapId = player.getMapId(); int mapId = player.getMapId();
player.getMap().removePlayer(player); player.getMap().removePlayer(player);
if(GameConstants.isDojo(mapId)) { if(GameConstants.isDojo(mapId)) {
this.getChannelServer().freeDojoSectionIfEmpty(mapId); this.getChannelServer().freeDojoSectionIfEmpty(mapId);
} }
+2 -2
View File
@@ -32,10 +32,10 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.Semaphore; import java.util.concurrent.Semaphore;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
public final class MonsterBook { public final class MonsterBook {
private static final Semaphore semaphore = new Semaphore(10); private static final Semaphore semaphore = new Semaphore(10);
+10 -2
View File
@@ -1769,6 +1769,10 @@ public class Commands {
newMap.respawn(); newMap.respawn();
break; break;
case "reloadshops":
MapleShopFactory.getInstance().reloadShops();
break;
case "hpmp": case "hpmp":
victim = player; victim = player;
int statUpdate = 1; int statUpdate = 1;
@@ -2611,9 +2615,9 @@ public class Commands {
player.getMap().spawnMonsterOnGroundBelow(monster, player.getPosition()); player.getMap().spawnMonsterOnGroundBelow(monster, player.getPosition());
break; break;
case "pnpcremove": case "playernpcremove":
if (sub.length < 2) { if (sub.length < 2) {
player.yellowMessage("Syntax: !pnpcremove <playername>"); player.yellowMessage("Syntax: !playernpcremove <playername>");
break; break;
} }
@@ -2731,6 +2735,10 @@ public class Commands {
c.getChannelServer().debugMarriageStatus(); c.getChannelServer().debugMarriageStatus();
break; break;
case "showpackets":
ServerConstants.USE_DEBUG_SHOW_RCVD_PACKET = !ServerConstants.USE_DEBUG_SHOW_RCVD_PACKET;
break;
case "set": case "set":
for(int i = 0; i < sub.length - 1; i++) { for(int i = 0; i < sub.length - 1; i++) {
ServerConstants.DEBUG_VALUES[i] = Integer.parseInt(sub[i + 1]); ServerConstants.DEBUG_VALUES[i] = Integer.parseInt(sub[i + 1]);
+2 -2
View File
@@ -28,10 +28,10 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
+29 -21
View File
@@ -32,7 +32,7 @@ import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Map; import java.util.Map;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import tools.Pair; import tools.Pair;
import client.MapleCharacter; import client.MapleCharacter;
@@ -41,19 +41,19 @@ import constants.ItemConstants;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
import client.inventory.manipulator.MapleInventoryManipulator; import client.inventory.manipulator.MapleInventoryManipulator;
import tools.FilePrinter; import tools.FilePrinter;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
* @author Matze, Ronan * @author Matze, Ronan
*/ */
public class MapleInventory implements Iterable<Item> { public class MapleInventory implements Iterable<Item> {
private MapleCharacter owner; protected MapleCharacter owner;
private Map<Short, Item> inventory = new LinkedHashMap<>(); protected Map<Short, Item> inventory = new LinkedHashMap<>();
private byte slotLimit; protected byte slotLimit;
private MapleInventoryType type; protected MapleInventoryType type;
private boolean checked = false; protected boolean checked = false;
private Lock lock = new MonitoredReentrantLock(MonitoredLockType.INVENTORY, true); protected Lock lock = new MonitoredReentrantLock(MonitoredLockType.INVENTORY, true);
public MapleInventory(MapleCharacter mc, MapleInventoryType type, byte slotLimit) { public MapleInventory(MapleCharacter mc, MapleInventoryType type, byte slotLimit) {
this.owner = mc; this.owner = mc;
@@ -301,7 +301,7 @@ public class MapleInventory implements Iterable<Item> {
} }
} }
private short addSlot(Item item) { protected short addSlot(Item item) {
if(item == null) { if(item == null) {
return -1; return -1;
} }
@@ -324,7 +324,7 @@ public class MapleInventory implements Iterable<Item> {
} }
} }
private void addSlotFromDB(short slot, Item item) { protected void addSlotFromDB(short slot, Item item) {
lock.lock(); lock.lock();
try { try {
inventory.put(slot, item); inventory.put(slot, item);
@@ -418,18 +418,22 @@ public class MapleInventory implements Iterable<Item> {
} }
public static boolean checkSpot(MapleCharacter chr, Item item) { public static boolean checkSpot(MapleCharacter chr, Item item) {
if (chr.getInventory(item.getInventoryType()).isFull()) return false; return !chr.getInventory(item.getInventoryType()).isFull();
return true;
} }
public static boolean checkSpots(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items) { public static boolean checkSpots(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items) {
List<Integer> zeroedList = new ArrayList<>(5); return checkSpots(chr, items, false);
for(byte i = 0; i < 5; i++) zeroedList.add(0);
return checkSpots(chr, items, zeroedList);
} }
public static boolean checkSpots(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed) { public static boolean checkSpots(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, boolean useProofInv) {
int invTypesSize = MapleInventoryType.values().length;
List<Integer> zeroedList = new ArrayList<>(invTypesSize);
for(byte i = 0; i < invTypesSize; i++) zeroedList.add(0);
return checkSpots(chr, items, zeroedList, useProofInv);
}
public static boolean checkSpots(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed, boolean useProofInv) {
// assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0. // assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0.
Map<Integer, Short> rcvItems = new LinkedHashMap<>(); Map<Integer, Short> rcvItems = new LinkedHashMap<>();
@@ -452,7 +456,7 @@ public class MapleInventory implements Iterable<Item> {
int itemType = rcvTypes.get(it.getKey()) - 1; int itemType = rcvTypes.get(it.getKey()) - 1;
int usedSlots = typesSlotsUsed.get(itemType); int usedSlots = typesSlotsUsed.get(itemType);
int result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getKey(), it.getValue(), "", usedSlots); int result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getKey(), it.getValue(), "", usedSlots, useProofInv);
boolean hasSpace = ((result % 2) != 0); boolean hasSpace = ((result % 2) != 0);
if(!hasSpace) return false; if(!hasSpace) return false;
@@ -481,13 +485,17 @@ public class MapleInventory implements Iterable<Item> {
} }
public static boolean checkSpotsAndOwnership(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items) { public static boolean checkSpotsAndOwnership(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items) {
return checkSpotsAndOwnership(chr, items, false);
}
public static boolean checkSpotsAndOwnership(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, boolean useProofInv) {
List<Integer> zeroedList = new ArrayList<>(5); List<Integer> zeroedList = new ArrayList<>(5);
for(byte i = 0; i < 5; i++) zeroedList.add(0); for(byte i = 0; i < 5; i++) zeroedList.add(0);
return checkSpotsAndOwnership(chr, items, zeroedList); return checkSpotsAndOwnership(chr, items, zeroedList, useProofInv);
} }
public static boolean checkSpotsAndOwnership(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed) { public static boolean checkSpotsAndOwnership(MapleCharacter chr, List<Pair<Item, MapleInventoryType>> items, List<Integer> typesSlotsUsed, boolean useProofInv) {
//assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0 and item list to be checked is a legal one. //assumption: no "UNDEFINED" or "EQUIPPED" items shall be tested here, all counts are >= 0 and item list to be checked is a legal one.
Map<Long, Short> rcvItems = new LinkedHashMap<>(); Map<Long, Short> rcvItems = new LinkedHashMap<>();
@@ -516,7 +524,7 @@ public class MapleInventory implements Iterable<Item> {
//System.out.print("inserting " + itemId.intValue() + " with type " + itemType + " qty " + it.getValue() + " owner '" + rcvOwners.get(it.getKey()) + "' current usedSlots:"); //System.out.print("inserting " + itemId.intValue() + " with type " + itemType + " qty " + it.getValue() + " owner '" + rcvOwners.get(it.getKey()) + "' current usedSlots:");
//for(Integer i : typesSlotsUsed) System.out.print(" " + i); //for(Integer i : typesSlotsUsed) System.out.print(" " + i);
int result = MapleInventoryManipulator.checkSpaceProgressively(c, itemId.intValue(), it.getValue(), rcvOwners.get(it.getKey()), usedSlots); int result = MapleInventoryManipulator.checkSpaceProgressively(c, itemId.intValue(), it.getValue(), rcvOwners.get(it.getKey()), usedSlots, useProofInv);
boolean hasSpace = ((result % 2) != 0); boolean hasSpace = ((result % 2) != 0);
//System.out.print(" -> hasSpace: " + hasSpace + " RESULT : " + result + "\n"); //System.out.print(" -> hasSpace: " + hasSpace + " RESULT : " + result + "\n");
@@ -0,0 +1,99 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.inventory;
import client.MapleCharacter;
/**
*
* @author Ronan
*/
public class MapleInventoryProof extends MapleInventory {
public MapleInventoryProof(MapleCharacter mc) {
super(mc, MapleInventoryType.CANHOLD, (byte) 0);
}
public void cloneContents(MapleInventory inv) {
inv.lockInventory();
lock.lock();
try {
inventory.clear();
this.setSlotLimit(inv.getSlotLimit());
for(Item it : inv.list()) {
Item item = new Item(it.getItemId(), it.getPosition(), it.getQuantity());
inventory.put(item.getPosition(), item);
}
} finally {
lock.unlock();
inv.unlockInventory();
}
}
public void flushContents() {
lock.lock();
try {
inventory.clear();
} finally {
lock.unlock();
}
}
@Override
protected short addSlot(Item item) {
if(item == null) {
return -1;
}
lock.lock();
try {
short slotId = getNextFreeSlot();
if (slotId < 0) {
return -1;
}
inventory.put(slotId, item);
return slotId;
} finally {
lock.unlock();
}
}
@Override
protected void addSlotFromDB(short slot, Item item) {
lock.lock();
try {
inventory.put(slot, item);
} finally {
lock.unlock();
}
}
@Override
public void removeSlot(short slot) {
lock.lock();
try {
inventory.remove(slot);
} finally {
lock.unlock();
}
}
}
@@ -31,6 +31,7 @@ public enum MapleInventoryType {
SETUP(3), SETUP(3),
ETC(4), ETC(4),
CASH(5), CASH(5),
CANHOLD(6), //Proof-guard for inserting after removal checks
EQUIPPED(-1); //Seems nexon screwed something when removing an item T_T EQUIPPED(-1); //Seems nexon screwed something when removing an item T_T
final byte type; final byte type;
+3 -7
View File
@@ -36,6 +36,7 @@ import server.movement.LifeMovementFragment;
import client.MapleCharacter; import client.MapleCharacter;
import java.sql.Connection; import java.sql.Connection;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair;
/** /**
* *
@@ -273,13 +274,8 @@ public class MaplePet extends Item {
this.summoned = yes; this.summoned = yes;
} }
public boolean canConsume(int itemId) { public Pair<Integer, Boolean> canConsume(int itemId) {
for (int petId : MapleItemInformationProvider.getInstance().petsCanConsume(itemId)) { return MapleItemInformationProvider.getInstance().canPetConsume(this.getItemId(), itemId);
if (petId == this.getItemId()) {
return true;
}
}
return false;
} }
public void updatePosition(List<LifeMovementFragment> movement) { public void updatePosition(List<LifeMovementFragment> movement) {
@@ -22,6 +22,7 @@
package client.inventory.manipulator; package client.inventory.manipulator;
import client.MapleBuffStat; import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleClient; import client.MapleClient;
import client.inventory.Equip; import client.inventory.Equip;
import client.inventory.Item; import client.inventory.Item;
@@ -38,6 +39,7 @@ import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
import server.maps.MapleMap;
import tools.FilePrinter; import tools.FilePrinter;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
@@ -45,6 +47,7 @@ import tools.MaplePacketCreator;
/** /**
* *
* @author Matze * @author Matze
* @author Ronan (improved check space feature & removed redundant object calls)
*/ */
public class MapleInventoryManipulator { public class MapleInventoryManipulator {
@@ -67,9 +70,11 @@ public class MapleInventoryManipulator {
public static boolean addById(MapleClient c, int itemId, short quantity, String owner, int petid, byte flag, long expiration) { public static boolean addById(MapleClient c, int itemId, short quantity, String owner, int petid, byte flag, long expiration) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ItemConstants.getInventoryType(itemId); MapleInventoryType type = ItemConstants.getInventoryType(itemId);
MapleCharacter chr = c.getPlayer();
MapleInventory inv = chr.getInventory(type);
if (!type.equals(MapleInventoryType.EQUIP)) { if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemId); short slotMax = ii.getSlotMax(c, itemId);
List<Item> existing = c.getPlayer().getInventory(type).listById(itemId); List<Item> existing = inv.listById(itemId);
if (!ItemConstants.isRechargeable(itemId) && petid == -1) { if (!ItemConstants.isRechargeable(itemId) && petid == -1) {
if (existing.size() > 0) { // first update all existing slots to slotMax if (existing.size() > 0) { // first update all existing slots to slotMax
Iterator<Item> i = existing.iterator(); Iterator<Item> i = existing.iterator();
@@ -97,7 +102,7 @@ public class MapleInventoryManipulator {
Item nItem = new Item(itemId, (short) 0, newQ, petid); Item nItem = new Item(itemId, (short) 0, newQ, petid);
nItem.setFlag(flag); nItem.setFlag(flag);
nItem.setExpiration(expiration); nItem.setExpiration(expiration);
short newSlot = c.getPlayer().getInventory(type).addItem(nItem); short newSlot = inv.addItem(nItem);
if (newSlot == -1) { if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
@@ -107,7 +112,7 @@ public class MapleInventoryManipulator {
nItem.setOwner(owner); nItem.setOwner(owner);
} }
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
if(sandboxItem) c.getPlayer().setHasSandboxItem(); if(sandboxItem) chr.setHasSandboxItem();
if ((ItemConstants.isRechargeable(itemId)) && quantity == 0) { if ((ItemConstants.isRechargeable(itemId)) && quantity == 0) {
break; break;
} }
@@ -120,14 +125,14 @@ public class MapleInventoryManipulator {
Item nItem = new Item(itemId, (short) 0, quantity, petid); Item nItem = new Item(itemId, (short) 0, quantity, petid);
nItem.setFlag(flag); nItem.setFlag(flag);
nItem.setExpiration(expiration); nItem.setExpiration(expiration);
short newSlot = c.getPlayer().getInventory(type).addItem(nItem); short newSlot = inv.addItem(nItem);
if (newSlot == -1) { if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return false; return false;
} }
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
if(MapleInventoryManipulator.isSandboxItem(nItem)) c.getPlayer().setHasSandboxItem(); if(MapleInventoryManipulator.isSandboxItem(nItem)) chr.setHasSandboxItem();
} }
} else if (quantity == 1) { } else if (quantity == 1) {
Item nEquip = ii.getEquipById(itemId); Item nEquip = ii.getEquipById(itemId);
@@ -136,14 +141,14 @@ public class MapleInventoryManipulator {
if (owner != null) { if (owner != null) {
nEquip.setOwner(owner); nEquip.setOwner(owner);
} }
short newSlot = c.getPlayer().getInventory(type).addItem(nEquip); short newSlot = inv.addItem(nEquip);
if (newSlot == -1) { if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return false; return false;
} }
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nEquip)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nEquip))));
if(MapleInventoryManipulator.isSandboxItem(nEquip)) c.getPlayer().setHasSandboxItem(); if(MapleInventoryManipulator.isSandboxItem(nEquip)) chr.setHasSandboxItem();
} else { } else {
throw new RuntimeException("Trying to create equip with non-one quantity"); throw new RuntimeException("Trying to create equip with non-one quantity");
} }
@@ -159,17 +164,19 @@ public class MapleInventoryManipulator {
} }
public static boolean addFromDrop(MapleClient c, Item item, boolean show, int petId) { public static boolean addFromDrop(MapleClient c, Item item, boolean show, int petId) {
MapleCharacter chr = c.getPlayer();
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = item.getInventoryType(); MapleInventoryType type = item.getInventoryType();
if (ii.isPickupRestricted(item.getItemId()) && c.getPlayer().haveItemWithId(item.getItemId(), true)) { if (ii.isPickupRestricted(item.getItemId()) && chr.haveItemWithId(item.getItemId(), true)) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.showItemUnavailable()); c.announce(MaplePacketCreator.showItemUnavailable());
return false; return false;
} }
short quantity = item.getQuantity(); short quantity = item.getQuantity();
MapleInventory inv = chr.getInventory(type);
if (!type.equals(MapleInventoryType.EQUIP)) { if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, item.getItemId()); short slotMax = ii.getSlotMax(c, item.getItemId());
List<Item> existing = c.getPlayer().getInventory(type).listById(item.getItemId()); List<Item> existing = inv.listById(item.getItemId());
if (!ItemConstants.isRechargeable(item.getItemId()) && petId == -1) { if (!ItemConstants.isRechargeable(item.getItemId()) && petId == -1) {
if (existing.size() > 0) { // first update all existing slots to slotMax if (existing.size() > 0) { // first update all existing slots to slotMax
Iterator<Item> i = existing.iterator(); Iterator<Item> i = existing.iterator();
@@ -195,7 +202,7 @@ public class MapleInventoryManipulator {
nItem.setExpiration(item.getExpiration()); nItem.setExpiration(item.getExpiration());
nItem.setOwner(item.getOwner()); nItem.setOwner(item.getOwner());
nItem.setFlag(item.getFlag()); nItem.setFlag(item.getFlag());
short newSlot = c.getPlayer().getInventory(type).addItem(nItem); short newSlot = inv.addItem(nItem);
if (newSlot == -1) { if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
@@ -203,32 +210,32 @@ public class MapleInventoryManipulator {
return false; return false;
} }
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
if(MapleInventoryManipulator.isSandboxItem(nItem)) c.getPlayer().setHasSandboxItem(); if(MapleInventoryManipulator.isSandboxItem(nItem)) chr.setHasSandboxItem();
} }
} else { } else {
Item nItem = new Item(item.getItemId(), (short) 0, quantity, petId); Item nItem = new Item(item.getItemId(), (short) 0, quantity, petId);
nItem.setExpiration(item.getExpiration()); nItem.setExpiration(item.getExpiration());
nItem.setFlag(item.getFlag()); nItem.setFlag(item.getFlag());
short newSlot = c.getPlayer().getInventory(type).addItem(nItem); short newSlot = inv.addItem(nItem);
if (newSlot == -1) { if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return false; return false;
} }
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
if(MapleInventoryManipulator.isSandboxItem(nItem)) c.getPlayer().setHasSandboxItem(); if(MapleInventoryManipulator.isSandboxItem(nItem)) chr.setHasSandboxItem();
c.announce(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
} }
} else if (quantity == 1) { } else if (quantity == 1) {
short newSlot = c.getPlayer().getInventory(type).addItem(item); short newSlot = inv.addItem(item);
if (newSlot == -1) { if (newSlot == -1) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return false; return false;
} }
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, item)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, item))));
if(MapleInventoryManipulator.isSandboxItem(item)) c.getPlayer().setHasSandboxItem(); if(MapleInventoryManipulator.isSandboxItem(item)) chr.setHasSandboxItem();
} else { } else {
FilePrinter.printError(FilePrinter.ITEM, "Tried to pickup Equip id " + item.getItemId() + " containing more than 1 quantity --> " + quantity); FilePrinter.printError(FilePrinter.ITEM, "Tried to pickup Equip id " + item.getItemId() + " containing more than 1 quantity --> " + quantity);
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
@@ -248,14 +255,16 @@ public class MapleInventoryManipulator {
public static boolean checkSpace(MapleClient c, int itemid, int quantity, String owner) { public static boolean checkSpace(MapleClient c, int itemid, int quantity, String owner) {
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ItemConstants.getInventoryType(itemid); MapleInventoryType type = ItemConstants.getInventoryType(itemid);
MapleCharacter chr = c.getPlayer();
MapleInventory inv = chr.getInventory(type);
if(ii.isPickupRestricted(itemid) && haveItemWithId(c.getPlayer().getInventory(type), itemid)) { if(ii.isPickupRestricted(itemid) && haveItemWithId(inv, itemid)) {
return false; return false;
} }
if (!type.equals(MapleInventoryType.EQUIP)) { if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemid); short slotMax = ii.getSlotMax(c, itemid);
List<Item> existing = c.getPlayer().getInventory(type).listById(itemid); List<Item> existing = inv.listById(itemid);
if (!ItemConstants.isRechargeable(itemid)) { if (!ItemConstants.isRechargeable(itemid)) {
if (existing.size() > 0) // first update all existing slots to slotMax if (existing.size() > 0) // first update all existing slots to slotMax
{ {
@@ -279,13 +288,13 @@ public class MapleInventoryManipulator {
} else { } else {
numSlotsNeeded = 1; numSlotsNeeded = 1;
} }
return !c.getPlayer().getInventory(type).isFull(numSlotsNeeded - 1); return !inv.isFull(numSlotsNeeded - 1);
} else { } else {
return !c.getPlayer().getInventory(type).isFull(); return !inv.isFull();
} }
} }
public static int checkSpaceProgressively(MapleClient c, int itemid, int quantity, String owner, int usedSlots) { public static int checkSpaceProgressively(MapleClient c, int itemid, int quantity, String owner, int usedSlots, boolean useProofInv) {
// return value --> bit0: if has space for this one; // return value --> bit0: if has space for this one;
// value after: new slots filled; // value after: new slots filled;
// assumption: equipments always have slotMax == 1. // assumption: equipments always have slotMax == 1.
@@ -293,16 +302,18 @@ public class MapleInventoryManipulator {
int returnValue; int returnValue;
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
MapleInventoryType type = ItemConstants.getInventoryType(itemid); MapleInventoryType type = !useProofInv ? ItemConstants.getInventoryType(itemid) : MapleInventoryType.CANHOLD;
MapleCharacter chr = c.getPlayer();
MapleInventory inv = chr.getInventory(type);
if(ii.isPickupRestricted(itemid) && haveItemWithId(c.getPlayer().getInventory(type), itemid)) { if(ii.isPickupRestricted(itemid) && haveItemWithId(inv, itemid)) {
return 0; return 0;
} }
if (!type.equals(MapleInventoryType.EQUIP)) { if (!type.equals(MapleInventoryType.EQUIP)) {
short slotMax = ii.getSlotMax(c, itemid); short slotMax = ii.getSlotMax(c, itemid);
if (!ItemConstants.isRechargeable(itemid)) { if (!ItemConstants.isRechargeable(itemid)) {
List<Item> existing = c.getPlayer().getInventory(type).listById(itemid); List<Item> existing = inv.listById(itemid);
if (existing.size() > 0) // first update all existing slots to slotMax if (existing.size() > 0) // first update all existing slots to slotMax
{ {
@@ -328,11 +339,11 @@ public class MapleInventoryManipulator {
} }
returnValue = ((numSlotsNeeded + usedSlots) << 1); returnValue = ((numSlotsNeeded + usedSlots) << 1);
returnValue += (numSlotsNeeded == 0 || !c.getPlayer().getInventory(type).isFullAfterSomeItems(numSlotsNeeded - 1, usedSlots)) ? 1 : 0; returnValue += (numSlotsNeeded == 0 || !inv.isFullAfterSomeItems(numSlotsNeeded - 1, usedSlots)) ? 1 : 0;
//System.out.print(" needed " + numSlotsNeeded + " used " + usedSlots + " rval " + returnValue); //System.out.print(" needed " + numSlotsNeeded + " used " + usedSlots + " rval " + returnValue);
} else { } else {
returnValue = ((quantity + usedSlots) << 1); returnValue = ((quantity + usedSlots) << 1);
returnValue += (!c.getPlayer().getInventory(type).isFullAfterSomeItems(0, usedSlots)) ? 1 : 0; returnValue += (!inv.isFullAfterSomeItems(0, usedSlots)) ? 1 : 0;
//System.out.print(" eqpneeded " + 1 + " used " + usedSlots + " rval " + returnValue); //System.out.print(" eqpneeded " + 1 + " used " + usedSlots + " rval " + returnValue);
} }
@@ -344,9 +355,30 @@ public class MapleInventoryManipulator {
} }
public static void removeFromSlot(MapleClient c, MapleInventoryType type, short slot, short quantity, boolean fromDrop, boolean consume) { public static void removeFromSlot(MapleClient c, MapleInventoryType type, short slot, short quantity, boolean fromDrop, boolean consume) {
Item item = c.getPlayer().getInventory(type).getItem(slot); MapleInventory inv = c.getPlayer().getInventory(type);
Item item = inv.getItem(slot);
boolean allowZero = consume && ItemConstants.isRechargeable(item.getItemId()); boolean allowZero = consume && ItemConstants.isRechargeable(item.getItemId());
c.getPlayer().getInventory(type).removeItem(slot, quantity, allowZero);
if(type == MapleInventoryType.EQUIPPED) {
inv.lockInventory();
try {
c.getPlayer().unequippedItem((Equip) item);
inv.removeItem(slot, quantity, allowZero);
} finally {
inv.unlockInventory();
}
announceModifyInventory(c, item, fromDrop, allowZero);
} else {
inv.removeItem(slot, quantity, allowZero);
if(type != MapleInventoryType.CANHOLD) {
announceModifyInventory(c, item, fromDrop, allowZero);
}
}
}
private static void announceModifyInventory(MapleClient c, Item item, boolean fromDrop, boolean allowZero) {
if (item.getQuantity() == 0 && !allowZero) { if (item.getQuantity() == 0 && !allowZero) {
c.announce(MaplePacketCreator.modifyInventory(fromDrop, Collections.singletonList(new ModifyInventory(3, item)))); c.announce(MaplePacketCreator.modifyInventory(fromDrop, Collections.singletonList(new ModifyInventory(3, item))));
} else { } else {
@@ -374,7 +406,7 @@ public class MapleInventoryManipulator {
} }
} }
} }
if (removeQuantity > 0) { if (removeQuantity > 0 && type != MapleInventoryType.CANHOLD) {
throw new RuntimeException("[HACK] Not enough items available of Item:" + itemId + ", Quantity (After Quantity/Over Current Quantity): " + (quantity - removeQuantity) + "/" + quantity); throw new RuntimeException("[HACK] Not enough items available of Item:" + itemId + ", Quantity (After Quantity/Over Current Quantity): " + (quantity - removeQuantity) + "/" + quantity);
} }
} }
@@ -384,15 +416,17 @@ public class MapleInventoryManipulator {
} }
public static void move(MapleClient c, MapleInventoryType type, short src, short dst) { public static void move(MapleClient c, MapleInventoryType type, short src, short dst) {
MapleInventory inv = c.getPlayer().getInventory(type);
if (src < 0 || dst < 0) { if (src < 0 || dst < 0) {
return; return;
} }
if(dst > c.getPlayer().getInventory(type).getSlotLimit()) { if(dst > inv.getSlotLimit()) {
return; return;
} }
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item source = c.getPlayer().getInventory(type).getItem(src); Item source = inv.getItem(src);
Item initialTarget = c.getPlayer().getInventory(type).getItem(dst); Item initialTarget = inv.getItem(dst);
if (source == null) { if (source == null) {
return; return;
} }
@@ -402,7 +436,7 @@ public class MapleInventoryManipulator {
} }
short oldsrcQ = source.getQuantity(); short oldsrcQ = source.getQuantity();
short slotMax = ii.getSlotMax(c, source.getItemId()); short slotMax = ii.getSlotMax(c, source.getItemId());
c.getPlayer().getInventory(type).move(src, dst, slotMax); inv.move(src, dst, slotMax);
final List<ModifyInventory> mods = new ArrayList<>(); final List<ModifyInventory> mods = new ArrayList<>();
if (!(type.equals(MapleInventoryType.EQUIP) || type.equals(MapleInventoryType.CASH)) && initialTarget != null && initialTarget.getItemId() == source.getItemId() && !ItemConstants.isRechargeable(source.getItemId()) && isSameOwner(source, initialTarget)) { if (!(type.equals(MapleInventoryType.EQUIP) || type.equals(MapleInventoryType.CASH)) && initialTarget != null && initialTarget.getItemId() == source.getItemId() && !ItemConstants.isRechargeable(source.getItemId()) && isSameOwner(source, initialTarget)) {
if ((olddstQ + oldsrcQ) > slotMax) { if ((olddstQ + oldsrcQ) > slotMax) {
@@ -419,76 +453,83 @@ public class MapleInventoryManipulator {
} }
public static void equip(MapleClient c, short src, short dst) { public static void equip(MapleClient c, short src, short dst) {
Equip source = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(src); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if (source == null || !MapleItemInformationProvider.getInstance().canWearEquipment(c.getPlayer(), source, dst)) {
MapleCharacter chr = c.getPlayer();
MapleInventory eqpInv = chr.getInventory(MapleInventoryType.EQUIP);
MapleInventory eqpdInv = chr.getInventory(MapleInventoryType.EQUIPPED);
Equip source = (Equip) eqpInv.getItem(src);
if (source == null || !ii.canWearEquipment(chr, source, dst)) {
c.announce(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
return; return;
} else if ((((source.getItemId() >= 1902000 && source.getItemId() <= 1902002) || source.getItemId() == 1912000) && c.getPlayer().isCygnus()) || ((source.getItemId() >= 1902005 && source.getItemId() <= 1902007) || source.getItemId() == 1912005) && !c.getPlayer().isCygnus()) {// Adventurer taming equipment } else if ((((source.getItemId() >= 1902000 && source.getItemId() <= 1902002) || source.getItemId() == 1912000) && chr.isCygnus()) || ((source.getItemId() >= 1902005 && source.getItemId() <= 1902007) || source.getItemId() == 1912005) && !chr.isCygnus()) {// Adventurer taming equipment
return; return;
} }
boolean itemChanged = false; boolean itemChanged = false;
if (MapleItemInformationProvider.getInstance().isUntradeableOnEquip(source.getItemId())) { if (ii.isUntradeableOnEquip(source.getItemId())) {
source.setFlag((byte) ItemConstants.UNTRADEABLE); source.setFlag((byte) ItemConstants.UNTRADEABLE);
itemChanged = true; itemChanged = true;
} }
if (source.getRingId() > -1) {
c.getPlayer().getRingById(source.getRingId()).equip();
}
if (dst == -6) { // unequip the overall if (dst == -6) { // unequip the overall
Item top = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -5); Item top = eqpdInv.getItem((short) -5);
if (top != null && ItemConstants.isOverall(top.getItemId())) { if (top != null && ItemConstants.isOverall(top.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) { if (eqpInv.isFull()) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return; return;
} }
unequip(c, (byte) -5, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot()); unequip(c, (byte) -5, eqpInv.getNextFreeSlot());
} }
} else if (dst == -5) { } else if (dst == -5) {
final Item bottom = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -6); final Item bottom = eqpdInv.getItem((short) -6);
if (bottom != null && ItemConstants.isOverall(source.getItemId())) { if (bottom != null && ItemConstants.isOverall(source.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) { if (eqpInv.isFull()) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return; return;
} }
unequip(c, (byte) -6, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot()); unequip(c, (byte) -6, eqpInv.getNextFreeSlot());
} }
} else if (dst == -10) {// check if weapon is two-handed } else if (dst == -10) {// check if weapon is two-handed
Item weapon = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -11); Item weapon = eqpdInv.getItem((short) -11);
if (weapon != null && MapleItemInformationProvider.getInstance().isTwoHanded(weapon.getItemId())) { if (weapon != null && ii.isTwoHanded(weapon.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) { if (eqpInv.isFull()) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return; return;
} }
unequip(c, (byte) -11, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot()); unequip(c, (byte) -11, eqpInv.getNextFreeSlot());
} }
} else if (dst == -11) { } else if (dst == -11) {
Item shield = c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem((short) -10); Item shield = eqpdInv.getItem((short) -10);
if (shield != null && MapleItemInformationProvider.getInstance().isTwoHanded(source.getItemId())) { if (shield != null && ii.isTwoHanded(source.getItemId())) {
if (c.getPlayer().getInventory(MapleInventoryType.EQUIP).isFull()) { if (eqpInv.isFull()) {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getShowInventoryFull()); c.announce(MaplePacketCreator.getShowInventoryFull());
return; return;
} }
unequip(c, (byte) -10, c.getPlayer().getInventory(MapleInventoryType.EQUIP).getNextFreeSlot()); unequip(c, (byte) -10, eqpInv.getNextFreeSlot());
} }
} }
if (dst == -18) { if (dst == -18) {
if (c.getPlayer().getMount() != null) { if (chr.getMount() != null) {
c.getPlayer().getMount().setItemId(source.getItemId()); chr.getMount().setItemId(source.getItemId());
} }
} }
if (source.getItemId() == 1122017) {
c.getPlayer().equipPendantOfSpirit();
}
//1112413, 1112414, 1112405 (Lilin's Ring) //1112413, 1112414, 1112405 (Lilin's Ring)
source = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(src); source = (Equip) eqpInv.getItem(src);
Equip target = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem(dst); Equip target = (Equip) eqpdInv.getItem(dst);
c.getPlayer().getInventory(MapleInventoryType.EQUIP).removeSlot(src); eqpInv.removeSlot(src);
if (target != null) { if (target != null) {
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).removeSlot(dst); eqpdInv.lockInventory();
try {
chr.unequippedItem(target);
eqpdInv.removeSlot(dst);
} finally {
eqpdInv.unlockInventory();
}
} }
final List<ModifyInventory> mods = new ArrayList<>(); final List<ModifyInventory> mods = new ArrayList<>();
@@ -498,23 +539,38 @@ public class MapleInventoryManipulator {
} }
source.setPosition(dst); source.setPosition(dst);
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).addItemFromDB(source);
eqpdInv.lockInventory();
try {
if (source.getRingId() > -1) {
chr.getRingById(source.getRingId()).equip();
}
chr.equippedItem(source);
eqpdInv.addItemFromDB(source);
} finally {
eqpdInv.unlockInventory();
}
if (target != null) { if (target != null) {
target.setPosition(src); target.setPosition(src);
c.getPlayer().getInventory(MapleInventoryType.EQUIP).addItemFromDB(target); eqpInv.addItemFromDB(target);
} }
if (c.getPlayer().getBuffedValue(MapleBuffStat.BOOSTER) != null && ItemConstants.isWeapon(source.getItemId())) { if (chr.getBuffedValue(MapleBuffStat.BOOSTER) != null && ItemConstants.isWeapon(source.getItemId())) {
c.getPlayer().cancelBuffStats(MapleBuffStat.BOOSTER); chr.cancelBuffStats(MapleBuffStat.BOOSTER);
} }
mods.add(new ModifyInventory(2, source, src)); mods.add(new ModifyInventory(2, source, src));
c.announce(MaplePacketCreator.modifyInventory(true, mods)); c.announce(MaplePacketCreator.modifyInventory(true, mods));
c.getPlayer().equipChanged(); chr.equipChanged();
} }
public static void unequip(MapleClient c, short src, short dst) { public static void unequip(MapleClient c, short src, short dst) {
Equip source = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem(src); MapleCharacter chr = c.getPlayer();
Equip target = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(dst); MapleInventory eqpInv = chr.getInventory(MapleInventoryType.EQUIP);
MapleInventory eqpdInv = chr.getInventory(MapleInventoryType.EQUIPPED);
Equip source = (Equip) eqpdInv.getItem(src);
Equip target = (Equip) eqpInv.getItem(dst);
if (dst < 0) { if (dst < 0) {
return; return;
} }
@@ -525,24 +581,29 @@ public class MapleInventoryManipulator {
c.announce(MaplePacketCreator.getInventoryFull()); c.announce(MaplePacketCreator.getInventoryFull());
return; return;
} }
if (source.getItemId() == 1122017) {
c.getPlayer().unequipPendantOfSpirit(); eqpdInv.lockInventory();
} try {
if (source.getRingId() > -1) { if (source.getRingId() > -1) {
c.getPlayer().getRingById(source.getRingId()).unequip(); chr.getRingById(source.getRingId()).unequip();
} }
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).removeSlot(src); chr.unequippedItem(source);
eqpdInv.removeSlot(src);
} finally {
eqpdInv.unlockInventory();
}
if (target != null) { if (target != null) {
c.getPlayer().getInventory(MapleInventoryType.EQUIP).removeSlot(dst); eqpInv.removeSlot(dst);
} }
source.setPosition(dst); source.setPosition(dst);
c.getPlayer().getInventory(MapleInventoryType.EQUIP).addItemFromDB(source); eqpInv.addItemFromDB(source);
if (target != null) { if (target != null) {
target.setPosition(src); target.setPosition(src);
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).addItemFromDB(target); eqpdInv.addItemFromDB(target);
} }
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(2, source, src)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(2, source, src))));
c.getPlayer().equipChanged(); chr.equipChanged();
} }
public static void drop(MapleClient c, MapleInventoryType type, short src, short quantity) { public static void drop(MapleClient c, MapleInventoryType type, short src, short quantity) {
@@ -550,30 +611,32 @@ public class MapleInventoryManipulator {
if (src < 0) { if (src < 0) {
type = MapleInventoryType.EQUIPPED; type = MapleInventoryType.EQUIPPED;
} }
Item source = c.getPlayer().getInventory(type).getItem(src);
if (c.getPlayer().getTrade() != null || c.getPlayer().getMiniGame() != null || source == null) { //Only check needed would prob be merchants (to see if the player is in one) MapleCharacter chr = c.getPlayer();
MapleInventory inv = chr.getInventory(type);
Item source = inv.getItem(src);
if (chr.getTrade() != null || chr.getMiniGame() != null || source == null) { //Only check needed would prob be merchants (to see if the player is in one)
return; return;
} }
int itemId = source.getItemId(); int itemId = source.getItemId();
if (ItemConstants.isPet(itemId)) { if (ItemConstants.isPet(itemId)) {
return; return;
} }
if (type == MapleInventoryType.EQUIPPED && itemId == 1122017) {
c.getPlayer().unequipPendantOfSpirit(); MapleMap map = chr.getMap();
} if (chr.getItemEffect() == itemId && source.getQuantity() == 1) {
if (c.getPlayer().getItemEffect() == itemId && source.getQuantity() == 1) { chr.setItemEffect(0);
c.getPlayer().setItemEffect(0); map.broadcastMessage(MaplePacketCreator.itemEffect(chr.getId(), 0));
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.itemEffect(c.getPlayer().getId(), 0));
} else if (itemId == 5370000 || itemId == 5370001) { } else if (itemId == 5370000 || itemId == 5370001) {
if (c.getPlayer().getItemQuantity(itemId, false) == 1) { if (chr.getItemQuantity(itemId, false) == 1) {
c.getPlayer().setChalkboard(null); chr.setChalkboard(null);
} }
} }
if ((!ItemConstants.isRechargeable(itemId) && source.getQuantity() < quantity) || quantity < 0) { if ((!ItemConstants.isRechargeable(itemId) && source.getQuantity() < quantity) || quantity < 0) {
return; return;
} }
Point dropPos = new Point(c.getPlayer().getPosition()); Point dropPos = new Point(chr.getPosition());
if (quantity < source.getQuantity() && !ItemConstants.isRechargeable(itemId)) { if (quantity < source.getQuantity() && !ItemConstants.isRechargeable(itemId)) {
Item target = source.copy(); Item target = source.copy();
target.setQuantity(quantity); target.setQuantity(quantity);
@@ -582,50 +645,61 @@ public class MapleInventoryManipulator {
if(ItemConstants.isNewYearCardEtc(itemId)) { if(ItemConstants.isNewYearCardEtc(itemId)) {
if(itemId == 4300000) { if(itemId == 4300000) {
NewYearCardRecord.removeAllNewYearCard(true, c.getPlayer()); NewYearCardRecord.removeAllNewYearCard(true, chr);
c.getAbstractPlayerInteraction().removeAll(4300000); c.getAbstractPlayerInteraction().removeAll(4300000);
} else { } else {
NewYearCardRecord.removeAllNewYearCard(false, c.getPlayer()); NewYearCardRecord.removeAllNewYearCard(false, chr);
c.getAbstractPlayerInteraction().removeAll(4301000); c.getAbstractPlayerInteraction().removeAll(4301000);
} }
} else if (ItemConstants.isWeddingRing(source.getItemId())) { } else if (ItemConstants.isWeddingRing(source.getItemId())) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos); map.disappearingItemDrop(chr, chr, target, dropPos);
} else if (c.getPlayer().getMap().getEverlast()) { } else if (map.getEverlast()) {
if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) { if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos); map.disappearingItemDrop(chr, chr, target, dropPos);
} else { } else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos, true, true); map.spawnItemDrop(chr, chr, target, dropPos, true, true);
} }
} else if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) { } else if (ii.isDropRestricted(target.getItemId()) || ii.isCash(target.getItemId()) || isDroppedItemRestricted(target)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos); map.disappearingItemDrop(chr, chr, target, dropPos);
} else { } else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), target, dropPos, true, true); map.spawnItemDrop(chr, chr, target, dropPos, true, true);
} }
} else { } else {
c.getPlayer().getInventory(type).removeSlot(src); if (type == MapleInventoryType.EQUIPPED) {
inv.lockInventory();
try {
chr.unequippedItem((Equip) source);
inv.removeSlot(src);
} finally {
inv.unlockInventory();
}
} else {
inv.removeSlot(src);
}
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(3, source)))); c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(3, source))));
if (src < 0) { if (src < 0) {
c.getPlayer().equipChanged(); chr.equipChanged();
} else if(ItemConstants.isNewYearCardEtc(itemId)) { } else if(ItemConstants.isNewYearCardEtc(itemId)) {
if(itemId == 4300000) { if(itemId == 4300000) {
NewYearCardRecord.removeAllNewYearCard(true, c.getPlayer()); NewYearCardRecord.removeAllNewYearCard(true, chr);
c.getAbstractPlayerInteraction().removeAll(4300000); c.getAbstractPlayerInteraction().removeAll(4300000);
} else { } else {
NewYearCardRecord.removeAllNewYearCard(false, c.getPlayer()); NewYearCardRecord.removeAllNewYearCard(false, chr);
c.getAbstractPlayerInteraction().removeAll(4301000); c.getAbstractPlayerInteraction().removeAll(4301000);
} }
} }
if (c.getPlayer().getMap().getEverlast()) { if (map.getEverlast()) {
if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) { if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos); map.disappearingItemDrop(chr, chr, source, dropPos);
} else { } else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos, true, true); map.spawnItemDrop(chr, chr, source, dropPos, true, true);
} }
} else if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) { } else if (ii.isDropRestricted(itemId) || ii.isCash(itemId) || isDroppedItemRestricted(source)) {
c.getPlayer().getMap().disappearingItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos); map.disappearingItemDrop(chr, chr, source, dropPos);
} else { } else {
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), source, dropPos, true, true); map.spawnItemDrop(chr, chr, source, dropPos, true, true);
} }
} }
} }
+5 -2
View File
@@ -41,8 +41,8 @@ public class ServerConstants {
//Server Flags //Server Flags
public static final boolean USE_CUSTOM_KEYSET = true; //Enables auto-setup of the HeavenMS's custom keybindings when creating characters. public static final boolean USE_CUSTOM_KEYSET = true; //Enables auto-setup of the HeavenMS's custom keybindings when creating characters.
public static final boolean USE_DEBUG = false; //Will enable some text prints on the client, oriented for debugging purposes. public static final boolean USE_DEBUG = false; //Will enable some text prints on the client, oriented for debugging purposes.
public static final boolean USE_DEBUG_SHOW_RCVD_PACKET = false; //Prints on the cmd all received packet ids.
public static final boolean USE_DEBUG_SHOW_INFO_EQPEXP = false; //Prints on the cmd all equip exp gain info. public static final boolean USE_DEBUG_SHOW_INFO_EQPEXP = false; //Prints on the cmd all equip exp gain info.
public static boolean USE_DEBUG_SHOW_RCVD_PACKET = false; //Prints on the cmd all received packet ids.
public static final boolean USE_MAXRANGE_ECHO_OF_HERO = true; public static final boolean USE_MAXRANGE_ECHO_OF_HERO = true;
public static final boolean USE_MAXRANGE = true; //Will send and receive packets from all events on a map, rather than those of only view range. public static final boolean USE_MAXRANGE = true; //Will send and receive packets from all events on a map, rather than those of only view range.
@@ -74,7 +74,6 @@ public class ServerConstants {
public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped. public static final boolean USE_ERASE_UNTRADEABLE_DROP = true; //Forces flagged untradeable items to disappear when dropped.
public static final boolean USE_ERASE_PET_ON_EXPIRATION = false;//Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll. public static final boolean USE_ERASE_PET_ON_EXPIRATION = false;//Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll.
public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats. public static final boolean USE_BUFF_MOST_SIGNIFICANT = true; //When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats.
public static final boolean USE_QUEST_RATE = false; //Exp/Meso gained by quests uses fixed server exp/meso rate times quest rate as multiplier, instead of player rates.
public static final boolean USE_MULTIPLE_SAME_EQUIP_DROP = true;//Enables multiple drops by mobs of the same equipment, number of possible drops based on the quantities provided at the drop data. public static final boolean USE_MULTIPLE_SAME_EQUIP_DROP = true;//Enables multiple drops by mobs of the same equipment, number of possible drops based on the quantities provided at the drop data.
public static final boolean USE_BANISHABLE_TOWN_SCROLL = true; //Enables town scrolls to act as if it's a "player banish", rendering the antibanish scroll effect available. public static final boolean USE_BANISHABLE_TOWN_SCROLL = true; //Enables town scrolls to act as if it's a "player banish", rendering the antibanish scroll effect available.
public static final boolean USE_OLD_GMS_STYLED_PQ_NPCS = true; //Enables PQ NPCs with similar behaviour to old GMS style, that skips info about the PQs and immediately tries to register the party in. public static final boolean USE_OLD_GMS_STYLED_PQ_NPCS = true; //Enables PQ NPCs with similar behaviour to old GMS style, that skips info about the PQs and immediately tries to register the party in.
@@ -155,6 +154,10 @@ public class ServerConstants {
public static final boolean USE_ADD_RATES_BY_LEVEL = true; //Rates are added each 20 levels. public static final boolean USE_ADD_RATES_BY_LEVEL = true; //Rates are added each 20 levels.
public static final boolean USE_STACK_COUPON_RATES = true; //Multiple coupons effects builds up together. public static final boolean USE_STACK_COUPON_RATES = true; //Multiple coupons effects builds up together.
public static final boolean USE_PERFECT_PITCH = true; //For lvl 30 or above, each lvlup grants player 1 perfect pitch. public static final boolean USE_PERFECT_PITCH = true; //For lvl 30 or above, each lvlup grants player 1 perfect pitch.
//Quest Configuration
public static final boolean USE_QUEST_RATE = false; //Exp/Meso gained by quests uses fixed server exp/meso rate times quest rate as multiplier, instead of player rates.
public static final int FAME_GAIN_MIN_HOUR_INTERVAL = 24; //Minimum time interval in hours the repeatable quest must have to be accounted for the "fame gain by quest".
public static final int FAME_GAIN_BY_QUEST = 4; //Fame gain each N quest completes, set 0 to disable. public static final int FAME_GAIN_BY_QUEST = 4; //Fame gain each N quest completes, set 0 to disable.
//Guild Configuration //Guild Configuration
+2 -2
View File
@@ -28,6 +28,8 @@ import java.util.HashSet;
import java.util.Calendar; import java.util.Calendar;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.Server; import net.server.Server;
import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.service.IoHandlerAdapter;
@@ -46,14 +48,12 @@ import constants.ServerConstants;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import server.TimerManager; import server.TimerManager;
import tools.locks.MonitoredLockType;
public class MapleServerHandler extends IoHandlerAdapter { public class MapleServerHandler extends IoHandlerAdapter {
private final static Set<Short> ignoredDebugRecvPackets = new HashSet<>(Arrays.asList((short) 167, (short) 197, (short) 89, (short) 91, (short) 41, (short) 188, (short) 107)); private final static Set<Short> ignoredDebugRecvPackets = new HashSet<>(Arrays.asList((short) 167, (short) 197, (short) 89, (short) 91, (short) 41, (short) 188, (short) 107));
-131
View File
@@ -1,131 +0,0 @@
package net.server;
import java.io.Console;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author kevintjuh93
*/
public class CreateINI {
public static void main(String args[]) {
StringBuilder sb = new StringBuilder();
String nextline = "\r\n";//Because I can, and it's free.
byte worlds;
Console con = System.console();
System.out.println("Welcome to MoopleDEV's .ini creator\r\n\r\n");
sb.append("#MoopleDEV's INI file. Do NOT modify it if you are an idiot (:\r\n");
sb.append("#Flag types: 0 = nothing, 1 = event, 2 = new, 3 = hot\r\n\r\n");
System.out.println("Flag types: 0 = nothing, 1 = event, 2 = new, 3 = hot\r\n\r\n");
worlds = Byte.parseByte(con.readLine("Number of worlds: "));
sb.append("worlds=").append(worlds).append("\r\n\r\n");
System.out.println("\r\n");
for (byte b = 0; b < worlds; b++) {
sb.append("#Properties for world ").append(b).append("\r\n");
System.out.println("Properties for world " + b);
if (b > 1) {
System.out.println("Make sure you create a npc folder for this world!");
}
sb.append("flag").append(b).append("=").append(
Integer.parseInt(con.readLine(" Flag: "))).append("\r\n");
sb.append("servermessage").append(b).append("=").append(
con.readLine(" Server message: ")).append("\r\n");
sb.append("eventmessage").append(b).append("=").append(
con.readLine(" Event message: ")).append("\r\n");
sb.append("whyamirecommended").append(b).append("=").append(
con.readLine(" Recommend message: ")).append("\r\n");
sb.append("channels").append(b).append("=").append(
Byte.parseByte(con.readLine(" Number of channels: "))).append("\r\n");
sb.append("exprate").append(b).append("=").append(
Integer.parseInt(con.readLine(" Exp rate: "))).append("\r\n");
sb.append("droprate").append(b).append("=").append(
Integer.parseInt(con.readLine(" Drop rate: "))).append("\r\n");
sb.append("mesorate").append(b).append("=").append(
Integer.parseInt(con.readLine(" Meso rate: "))).append("\r\n");
sb.append("questrate").append(b).append("=").append(
Integer.parseInt(con.readLine(" Quest rate: "))).append("\r\n");
System.out.println(nextline);
sb.append("\r\n");
}
sb.append("\r\n").append("gmserver=").append(Boolean.parseBoolean(con.readLine("Do you want a GM Server? (true/false)")));
FileOutputStream out = null;
try {
out = new FileOutputStream("moople.ini", false);
out.write(sb.toString().getBytes());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
sb = new StringBuilder();
try {
System.out.println("\r\nYou are about to set the Java Heap Size, if you don't know what it is, type '?'.");
String heapsize = con.readLine("Java Heap Size (in MB): ");
while (heapsize.equals("?")) {
System.out.println("\r\n");
System.out.println("WikiAnswers: Java heap is the heap size allocated to JVM applications which takes care of the new objects being created. If the objects being created exceed the heap size, it will throw an error saying memoryOutof Bound\r\n");
System.out.println("I recommend using 64 bit with the heap size around 4000, if you have 4 gb RAM.");
heapsize = con.readLine("Java Heap Size (in MB): ");
}
String linux = con.readLine("\r\nAre you using a Linux platform or not? (y/n):");
while (!linux.equals("y") && !linux.equals("n")) {
System.out.println("Type 'y' if you use linux else type 'n'.");
linux = con.readLine("Are you using a Linux platform or not? (y/n):");
}
if (linux.equals("n")) {
out = new FileOutputStream("launch_server.bat", false);
sb.append("@echo off").append("\r\n").append("@title MoopleDEV Server v83").append("\r\n");
sb.append("set CLASSPATH=.;dist\\*\r\n");
sb.append("java -Xmx").append(heapsize).append("m -Dwzpath=wz\\ net.server.Server\r\n");
sb.append("pause");
} else {//test
out = new FileOutputStream("launch_server.sh", false);
sb.append("#!/bin/sh").append("\r\n\r\n");
sb.append("export CLASSPATH=\".:dist/*\" \r\n\r\n");
sb.append("java -Dwzpath=wz/ \\\r\n");
sb.append("-Xmx").append(heapsize).append("m ").append("net.server.Server");
System.out.println("Use DOS2UNIX command to convert the .sh file once again.");
}
out.write(sb.toString().getBytes());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
System.out.println("\r\nMake sure that ServerConstants in modified too, and clean+compiled before you start the server.");
System.out.println("If you want other settings; restart this .bat or modify the moople.ini");
}
}
+2 -2
View File
@@ -28,8 +28,8 @@ import java.util.Map;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import server.life.MobSkill; import server.life.MobSkill;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
/** /**
* *
+2 -2
View File
@@ -27,11 +27,11 @@ import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import tools.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
public class PlayerStorage { public class PlayerStorage {
private final ReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_STORAGE, true); private final ReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_STORAGE, true);
+19 -8
View File
@@ -41,12 +41,16 @@ import java.util.Map.Entry;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import tools.locks.MonitoredReentrantLock;
import tools.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import net.server.audit.ThreadTracker;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
import net.MapleServerHandler; import net.MapleServerHandler;
import net.mina.MapleCodecFactory; import net.mina.MapleCodecFactory;
import net.server.channel.Channel; import net.server.channel.Channel;
@@ -75,7 +79,6 @@ import client.newyear.NewYearCardRecord;
import constants.ItemConstants; import constants.ItemConstants;
import constants.GameConstants; import constants.GameConstants;
import constants.ServerConstants; import constants.ServerConstants;
import net.server.audit.ThreadTracker;
import server.CashShop.CashItemFactory; import server.CashShop.CashItemFactory;
import server.TimerManager; import server.TimerManager;
import server.life.MaplePlayerNPCFactory; import server.life.MaplePlayerNPCFactory;
@@ -84,7 +87,6 @@ import tools.AutoJCE;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.FilePrinter; import tools.FilePrinter;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType;
public class Server { public class Server {
private static final Set<Integer> activeFly = new HashSet<>(); private static final Set<Integer> activeFly = new HashSet<>();
@@ -325,10 +327,17 @@ public class Server {
} }
public void runAnnouncePlayerDiseasesSchedule() { public void runAnnouncePlayerDiseasesSchedule() {
List<MapleClient> processDiseaseAnnounceClients;
disLock.lock(); disLock.lock();
try { try {
while(!processDiseaseAnnouncePlayers.isEmpty()) { processDiseaseAnnounceClients = new LinkedList<>(processDiseaseAnnouncePlayers);
MapleClient c = processDiseaseAnnouncePlayers.remove(0); processDiseaseAnnouncePlayers.clear();
} finally {
disLock.unlock();
}
while(!processDiseaseAnnounceClients.isEmpty()) {
MapleClient c = processDiseaseAnnounceClients.remove(0);
MapleCharacter player = c.getPlayer(); MapleCharacter player = c.getPlayer();
if(player != null && player.isLoggedinWorld()) { if(player != null && player.isLoggedinWorld()) {
for(MapleCharacter chr : player.getMap().getCharacters()) { for(MapleCharacter chr : player.getMap().getCharacters()) {
@@ -337,6 +346,8 @@ public class Server {
} }
} }
disLock.lock();
try {
// this is to force the system to wait for at least one complete tick before releasing disease info for the registered clients // this is to force the system to wait for at least one complete tick before releasing disease info for the registered clients
while(!registeredDiseaseAnnouncePlayers.isEmpty()) { while(!registeredDiseaseAnnouncePlayers.isEmpty()) {
MapleClient c = registeredDiseaseAnnouncePlayers.remove(0); MapleClient c = registeredDiseaseAnnouncePlayers.remove(0);
@@ -362,7 +373,7 @@ public class Server {
p.load(new FileInputStream("world.ini")); p.load(new FileInputStream("world.ini"));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
System.out.println("Please start create_server.bat"); System.out.println("[SEVERE] Could not find/open 'world.ini'.");
System.exit(0); System.exit(0);
} }
@@ -453,7 +464,7 @@ public class Server {
loadPlayerNpcMapStepFromDb(); loadPlayerNpcMapStepFromDb();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();//For those who get errors e.printStackTrace();//For those who get errors
System.out.println("Error in moople.ini, start CreateINI.bat to re-make the file."); System.out.println("[SEVERE] Syntax error in 'world.ini'.");
System.exit(0); System.exit(0);
} }
+3 -2
View File
@@ -34,10 +34,11 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import constants.ServerConstants;
import net.server.audit.locks.MonitoredLockType;
import server.TimerManager; import server.TimerManager;
import tools.FilePrinter; import tools.FilePrinter;
import tools.locks.MonitoredLockType;
import constants.ServerConstants;
/** /**
* *
@@ -17,7 +17,7 @@
You should have received a copy of the GNU Affero General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package tools.locks; package net.server.audit.locks;
/** /**
* *
@@ -49,6 +49,8 @@ public enum MonitoredLockType {
CHANNEL_FACESCHDL, CHANNEL_FACESCHDL,
CHANNEL_MOBACTION, CHANNEL_MOBACTION,
CHANNEL_MOBANIMAT, CHANNEL_MOBANIMAT,
CHANNEL_MOBMIST,
CHANNEL_MOBSKILL,
CHANNEL_MOBSTATUS, CHANNEL_MOBSTATUS,
CHANNEL_OVTSTATUS, CHANNEL_OVTSTATUS,
CHANNEL_OVERALL, CHANNEL_OVERALL,
@@ -17,7 +17,7 @@
You should have received a copy of the GNU Affero General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package tools.locks; package net.server.audit.locks;
import constants.ServerConstants; import constants.ServerConstants;
import java.text.DateFormat; import java.text.DateFormat;
@@ -17,7 +17,7 @@
You should have received a copy of the GNU Affero General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package tools.locks; package net.server.audit.locks;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
@@ -17,7 +17,7 @@
You should have received a copy of the GNU Affero General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package tools.locks; package net.server.audit.locks;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -17,7 +17,7 @@
You should have received a copy of the GNU Affero General Public License 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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package tools.locks; package net.server.audit.locks;
import constants.ServerConstants; import constants.ServerConstants;
import java.text.DateFormat; import java.text.DateFormat;
+15 -3
View File
@@ -34,11 +34,12 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock;
import tools.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
import net.MapleServerHandler; import net.MapleServerHandler;
import net.mina.MapleCodecFactory; import net.mina.MapleCodecFactory;
@@ -76,7 +77,6 @@ import client.MapleCharacter;
import client.status.MonsterStatusEffect; import client.status.MonsterStatusEffect;
import constants.ServerConstants; import constants.ServerConstants;
import server.maps.MapleMiniDungeonInfo; import server.maps.MapleMiniDungeonInfo;
import tools.locks.MonitoredLockType;
public final class Channel { public final class Channel {
@@ -89,6 +89,8 @@ public final class Channel {
private EventScriptManager eventSM; private EventScriptManager eventSM;
private MobStatusScheduler mobStatusSchedulers[] = new MobStatusScheduler[4]; private MobStatusScheduler mobStatusSchedulers[] = new MobStatusScheduler[4];
private MobAnimationScheduler mobAnimationSchedulers[] = new MobAnimationScheduler[4]; private MobAnimationScheduler mobAnimationSchedulers[] = new MobAnimationScheduler[4];
private MobClearSkillScheduler mobClearSkillSchedulers[] = new MobClearSkillScheduler[4];
private MobMistScheduler mobMistSchedulers[] = new MobMistScheduler[4];
private FaceExpressionScheduler faceExpressionSchedulers[] = new FaceExpressionScheduler[4]; private FaceExpressionScheduler faceExpressionSchedulers[] = new FaceExpressionScheduler[4];
private OverallScheduler channelSchedulers[] = new OverallScheduler[4]; private OverallScheduler channelSchedulers[] = new OverallScheduler[4];
private Map<Integer, MapleHiredMerchant> hiredMerchants = new HashMap<>(); private Map<Integer, MapleHiredMerchant> hiredMerchants = new HashMap<>();
@@ -164,6 +166,8 @@ public final class Channel {
mobStatusSchedulers[i] = new MobStatusScheduler(); mobStatusSchedulers[i] = new MobStatusScheduler();
mobAnimationSchedulers[i] = new MobAnimationScheduler(); mobAnimationSchedulers[i] = new MobAnimationScheduler();
mobClearSkillSchedulers[i] = new MobClearSkillScheduler();
mobMistSchedulers[i] = new MobMistScheduler();
faceExpressionSchedulers[i] = new FaceExpressionScheduler(faceLock[i]); faceExpressionSchedulers[i] = new FaceExpressionScheduler(faceLock[i]);
channelSchedulers[i] = new OverallScheduler(); channelSchedulers[i] = new OverallScheduler();
} }
@@ -868,6 +872,14 @@ public final class Channel {
return mobAnimationSchedulers[getChannelSchedulerIndex(mapid)].registerAnimationMode(mobHash, delay); return mobAnimationSchedulers[getChannelSchedulerIndex(mapid)].registerAnimationMode(mobHash, delay);
} }
public void registerMobClearSkillAction(int mapid, Runnable runAction, long delay) {
mobClearSkillSchedulers[getChannelSchedulerIndex(mapid)].registerClearSkillAction(runAction, delay);
}
public void registerMobMistCancelAction(int mapid, Runnable runAction, long delay) {
mobMistSchedulers[getChannelSchedulerIndex(mapid)].registerMistCancelAction(runAction, delay);
}
public void registerOverallAction(int mapid, Runnable runAction, long delay) { public void registerOverallAction(int mapid, Runnable runAction, long delay) {
channelSchedulers[getChannelSchedulerIndex(mapid)].registerDelayedAction(runAction, delay); channelSchedulers[getChannelSchedulerIndex(mapid)].registerDelayedAction(runAction, delay);
} }
@@ -674,6 +674,8 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
// This formula is still a bit wonky, but it is fairly accurate. // This formula is still a bit wonky, but it is fairly accurate.
calcDmgMax = (int) Math.round((chr.getTotalInt() * 4.8 + chr.getTotalLuk() * 4) * chr.getTotalMagic() / 1000); calcDmgMax = (int) Math.round((chr.getTotalInt() * 4.8 + chr.getTotalLuk() * 4) * chr.getTotalMagic() / 1000);
calcDmgMax = calcDmgMax * effect.getHp() / 100; calcDmgMax = calcDmgMax * effect.getHp() / 100;
ret.speed = 7;
} }
} else if(ret.skill == Hermit.SHADOW_MESO) { } else if(ret.skill == Hermit.SHADOW_MESO) {
// Shadow Meso also has its own formula // Shadow Meso also has its own formula
@@ -230,7 +230,14 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
} else if (action == 0x0E) { // Put into Cash Inventory } else if (action == 0x0E) { // Put into Cash Inventory
int cashId = slea.readInt(); int cashId = slea.readInt();
slea.skip(4); slea.skip(4);
MapleInventory mi = chr.getInventory(MapleInventoryType.getByType(slea.readByte()));
byte invType = slea.readByte();
if (invType < 1 || invType > 5) {
c.disconnect(false, false);
return;
}
MapleInventory mi = chr.getInventory(MapleInventoryType.getByType(invType));
Item item = mi.findByCashId(cashId); Item item = mi.findByCashId(cashId);
if (item == null) { if (item == null) {
c.announce(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
@@ -39,13 +39,19 @@ public final class InventoryMergeHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer(); MapleCharacter chr = c.getPlayer();
chr.getAutobanManager().setTimestamp(2, slea.readInt(), 3); chr.getAutobanManager().setTimestamp(2, slea.readInt(), 3);
MapleInventoryType inventoryType = MapleInventoryType.getByType(slea.readByte());
if(!ServerConstants.USE_ITEM_SORT) { if(!ServerConstants.USE_ITEM_SORT) {
c.announce(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
return; return;
} }
byte invType = slea.readByte();
if (invType < 1 || invType > 5) {
c.disconnect(false, false);
return;
}
MapleInventoryType inventoryType = MapleInventoryType.getByType(invType);
MapleInventory inventory = c.getPlayer().getInventory(inventoryType); MapleInventory inventory = c.getPlayer().getInventory(inventoryType);
inventory.lockInventory(); inventory.lockInventory();
try { try {
@@ -188,14 +188,14 @@ public final class InventorySortHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer(); MapleCharacter chr = c.getPlayer();
chr.getAutobanManager().setTimestamp(3, slea.readInt(), 3); chr.getAutobanManager().setTimestamp(3, slea.readInt(), 3);
byte inventoryType = slea.readByte();
if(!ServerConstants.USE_ITEM_SORT) { if(!ServerConstants.USE_ITEM_SORT) {
c.announce(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
return; return;
} }
if (inventoryType < 1 || inventoryType > 5) { byte invType = slea.readByte();
if (invType < 1 || invType > 5) {
c.disconnect(false, false); c.disconnect(false, false);
return; return;
} }
@@ -203,7 +203,7 @@ public final class InventorySortHandler extends AbstractMaplePacketHandler {
ArrayList<Item> itemarray = new ArrayList<>(); ArrayList<Item> itemarray = new ArrayList<>();
List<ModifyInventory> mods = new ArrayList<>(); List<ModifyInventory> mods = new ArrayList<>();
MapleInventory inventory = chr.getInventory(MapleInventoryType.getByType(inventoryType)); MapleInventory inventory = chr.getInventory(MapleInventoryType.getByType(invType));
inventory.lockInventory(); inventory.lockInventory();
try { try {
for (short i = 1; i <= inventory.getSlotLimit(); i++) { for (short i = 1; i <= inventory.getSlotLimit(); i++) {
@@ -218,7 +218,7 @@ public final class InventorySortHandler extends AbstractMaplePacketHandler {
mods.add(new ModifyInventory(3, item)); mods.add(new ModifyInventory(3, item));
} }
int invTypeCriteria = (MapleInventoryType.getByType(inventoryType) == MapleInventoryType.EQUIP) ? 3 : 1; int invTypeCriteria = (MapleInventoryType.getByType(invType) == MapleInventoryType.EQUIP) ? 3 : 1;
int sortCriteria = (ServerConstants.USE_ITEM_SORT_BY_NAME == true) ? 2 : 0; int sortCriteria = (ServerConstants.USE_ITEM_SORT_BY_NAME == true) ? 2 : 0;
PairedQuicksort pq = new PairedQuicksort(itemarray, sortCriteria, invTypeCriteria); PairedQuicksort pq = new PairedQuicksort(itemarray, sortCriteria, invTypeCriteria);
@@ -232,7 +232,7 @@ public final class InventorySortHandler extends AbstractMaplePacketHandler {
} }
c.announce(MaplePacketCreator.modifyInventory(true, mods)); c.announce(MaplePacketCreator.modifyInventory(true, mods));
c.announce(MaplePacketCreator.finishedSort2(inventoryType)); c.announce(MaplePacketCreator.finishedSort2(invType));
c.announce(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
} }
} }
@@ -28,6 +28,7 @@ import tools.data.input.SeekableLittleEndianAccessor;
import tools.data.output.MaplePacketLittleEndianWriter; import tools.data.output.MaplePacketLittleEndianWriter;
public final class NPCAnimationHandler extends AbstractMaplePacketHandler { public final class NPCAnimationHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) { public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
int length = (int) slea.available(); int length = (int) slea.available();
@@ -161,22 +161,8 @@ public final class PetAutoPotHandler extends AbstractMaplePacketHandler {
return false; return false;
} }
private Pair<Short, Short> calcEffectivePool(MapleCharacter chr) { private static Pair<Short, Short> calcEffectivePool(MapleCharacter chr) {
short hp = 0, mp = 0; return new Pair<>((short) chr.getMaxHpEquipped(), (short) chr.getMaxMpEquipped());
if(ServerConstants.USE_EQUIPS_ON_AUTOPOT) {
for(Item i : chr.getInventory(MapleInventoryType.EQUIPPED).list()) {
Equip e = (Equip) i;
hp += e.getHp();
mp += e.getMp();
}
}
hp = (short) Math.min(chr.getMaxHp() + hp, 30000);
mp = (short) Math.min(chr.getMaxMp() + mp, 30000);
return new Pair<>(hp, mp);
} }
private boolean shouldReusePot() { private boolean shouldReusePot() {
@@ -25,7 +25,6 @@ import java.util.Set;
import client.MapleCharacter; import client.MapleCharacter;
import client.MapleClient; import client.MapleClient;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet; import client.inventory.MaplePet;
import net.AbstractMaplePacketHandler; import net.AbstractMaplePacketHandler;
import server.maps.MapleMapItem; import server.maps.MapleMapItem;
@@ -58,25 +57,35 @@ public final class PetLootHandler extends AbstractMaplePacketHandler {
int oid = slea.readInt(); int oid = slea.readInt();
MapleMapObject ob = chr.getMap().getMapObject(oid); MapleMapObject ob = chr.getMap().getMapObject(oid);
if(ob == null) { if(ob == null) {
c.getSession().write(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
return; return;
} }
if (chr.getInventory(MapleInventoryType.EQUIPPED).findById(1812007) != null) {
final Set<Integer> petIgnore = chr.getExcludedItems();
MapleMapItem mapitem = (MapleMapItem) ob; MapleMapItem mapitem = (MapleMapItem) ob;
if (mapitem.getMeso() > 0) {
if (!chr.isEquippedMesoMagnet()) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if(!petIgnore.isEmpty()) { if (chr.isEquippedPetItemIgnore()) {
if (chr.getInventory(MapleInventoryType.EQUIPPED).findById(1812000) != null) { // Meso magnet final Set<Integer> petIgnore = chr.getExcludedItems();
if (mapitem.getMeso() > 0 && petIgnore.contains(Integer.MAX_VALUE)) { if(!petIgnore.isEmpty() && petIgnore.contains(Integer.MAX_VALUE)) {
c.getSession().write(MaplePacketCreator.enableActions()); c.announce(MaplePacketCreator.enableActions());
return; return;
} }
} else if (chr.getInventory(MapleInventoryType.EQUIPPED).findById(1812001) != null) { // Item Pouch }
if (petIgnore.contains(mapitem.getItem().getItemId())) { } else {
c.getSession().write(MaplePacketCreator.enableActions()); if (!chr.isEquippedItemPouch()) {
c.announce(MaplePacketCreator.enableActions());
return; return;
} }
if (chr.isEquippedPetItemIgnore()) {
final Set<Integer> petIgnore = chr.getExcludedItems();
if(!petIgnore.isEmpty() && petIgnore.contains(mapitem.getItem().getItemId())) {
c.announce(MaplePacketCreator.enableActions());
return;
} }
} }
} }
@@ -203,14 +203,14 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
} }
if (ItemConstants.isPlayerShop(itemId)) { if (ItemConstants.isPlayerShop(itemId)) {
MaplePlayerShop shop = new MaplePlayerShop(chr, desc); MaplePlayerShop shop = new MaplePlayerShop(chr, desc, itemId);
chr.setPlayerShop(shop); chr.setPlayerShop(shop);
chr.getMap().addMapObject(shop); chr.getMap().addMapObject(shop);
shop.sendShop(c); shop.sendShop(c);
c.getWorldServer().registerPlayerShop(shop); c.getWorldServer().registerPlayerShop(shop);
//c.announce(MaplePacketCreator.getPlayerShopRemoveVisitor(1)); //c.announce(MaplePacketCreator.getPlayerShopRemoveVisitor(1));
} else if (ItemConstants.isHiredMerchant(itemId)) { } else if (ItemConstants.isHiredMerchant(itemId)) {
MapleHiredMerchant merchant = new MapleHiredMerchant(chr, itemId, desc); MapleHiredMerchant merchant = new MapleHiredMerchant(chr, desc, itemId);
chr.setHiredMerchant(merchant); chr.setHiredMerchant(merchant);
c.getWorldServer().registerHiredMerchant(merchant); c.getWorldServer().registerHiredMerchant(merchant);
chr.getClient().getChannelServer().addHiredMerchant(chr.getId(), merchant); chr.getClient().getChannelServer().addHiredMerchant(chr.getId(), merchant);
@@ -304,18 +304,18 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
if(ServerConstants.USE_ERASE_PERMIT_ON_OPENSHOP) { if(ServerConstants.USE_ERASE_PERMIT_ON_OPENSHOP) {
try { try {
MapleInventoryManipulator.removeById(c, MapleInventoryType.CASH, 5140000, 1, true, false); MapleInventoryManipulator.removeById(c, MapleInventoryType.CASH, shop.getItemId(), 1, true, false);
} catch(RuntimeException re) {} // fella does not have a player shop permit... } catch(RuntimeException re) {} // fella does not have a player shop permit...
} }
chr.getMap().broadcastMessage(MaplePacketCreator.addCharBox(chr, 4)); chr.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(shop));
shop.setOpen(true); shop.setOpen(true);
} else if (merchant != null && merchant.isOwner(chr)) { } else if (merchant != null && merchant.isOwner(chr)) {
chr.setHasMerchant(true); chr.setHasMerchant(true);
merchant.setOpen(true); merchant.setOpen(true);
chr.getMap().addMapObject(merchant); chr.getMap().addMapObject(merchant);
chr.setHiredMerchant(null); chr.setHiredMerchant(null);
chr.getMap().broadcastMessage(MaplePacketCreator.spawnHiredMerchant(merchant)); chr.getMap().broadcastMessage(MaplePacketCreator.spawnHiredMerchantBox(merchant));
slea.readByte(); slea.readByte();
} }
} else if (mode == Action.READY.getCode()) { } else if (mode == Action.READY.getCode()) {
@@ -49,6 +49,9 @@ import client.MapleClient;
import client.MapleDisease; import client.MapleDisease;
import client.MapleFamily; import client.MapleFamily;
import client.SkillFactory; import client.SkillFactory;
import client.inventory.Equip;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType; import client.inventory.MapleInventoryType;
import client.inventory.MaplePet; import client.inventory.MaplePet;
import constants.GameConstants; import constants.GameConstants;
@@ -223,9 +226,18 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
player.updatePartyMemberHP(); player.updatePartyMemberHP();
} }
if (player.getInventory(MapleInventoryType.EQUIPPED).findById(1122017) != null) { MapleInventory eqpInv = player.getInventory(MapleInventoryType.EQUIPPED);
player.equipPendantOfSpirit(); eqpInv.lockInventory();
try {
player.resetEquippedHpMp();
for(Item it : eqpInv.list()) {
player.equippedItem((Equip) it);
} }
} finally {
eqpInv.unlockInventory();
}
c.announce(MaplePacketCreator.updateBuddylist(player.getBuddylist().getBuddies())); c.announce(MaplePacketCreator.updateBuddylist(player.getBuddylist().getBuddies()));
CharacterNameAndId pendingBuddyRequest = c.getPlayer().getBuddylist().pollPendingRequest(); CharacterNameAndId pendingBuddyRequest = c.getPlayer().getBuddylist().pollPendingRequest();
@@ -22,6 +22,7 @@
package net.server.channel.handlers; package net.server.channel.handlers;
import client.MapleClient; import client.MapleClient;
import client.MapleCharacter;
import client.Skill; import client.Skill;
import client.SkillFactory; import client.SkillFactory;
import client.inventory.Equip; import client.inventory.Equip;
@@ -35,7 +36,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.AbstractMaplePacketHandler; import net.AbstractMaplePacketHandler;
import client.inventory.manipulator.MapleInventoryManipulator; import client.inventory.manipulator.MapleInventoryManipulator;
import constants.ServerConstants;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor; import tools.data.input.SeekableLittleEndianAccessor;
@@ -57,16 +57,18 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
if ((ws & 2) == 2) { if ((ws & 2) == 2) {
whiteScroll = true; whiteScroll = true;
} }
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Equip toScroll = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).getItem(dst); MapleCharacter chr = c.getPlayer();
Equip toScroll = (Equip) chr.getInventory(MapleInventoryType.EQUIPPED).getItem(dst);
Skill LegendarySpirit = SkillFactory.getSkill(1003); Skill LegendarySpirit = SkillFactory.getSkill(1003);
if (c.getPlayer().getSkillLevel(LegendarySpirit) > 0 && dst >= 0) { if (chr.getSkillLevel(LegendarySpirit) > 0 && dst >= 0) {
legendarySpirit = true; legendarySpirit = true;
toScroll = (Equip) c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem(dst); toScroll = (Equip) chr.getInventory(MapleInventoryType.EQUIP).getItem(dst);
} }
byte oldLevel = toScroll.getLevel(); byte oldLevel = toScroll.getLevel();
byte oldSlots = toScroll.getUpgradeSlots(); byte oldSlots = toScroll.getUpgradeSlots();
MapleInventory useInventory = c.getPlayer().getInventory(MapleInventoryType.USE); MapleInventory useInventory = chr.getInventory(MapleInventoryType.USE);
Item scroll = useInventory.getItem(slot); Item scroll = useInventory.getItem(slot);
Item wscroll = null; Item wscroll = null;
@@ -81,7 +83,7 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
} }
if (whiteScroll) { if (whiteScroll) {
wscroll = useInventory.findById(2340000); wscroll = useInventory.findById(2340000);
if (wscroll == null || wscroll.getItemId() != 2340000) { if (wscroll == null) {
whiteScroll = false; whiteScroll = false;
} }
} }
@@ -96,7 +98,7 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
return; return;
} }
Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll, 0, c.getPlayer().isGM()); Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, scroll.getItemId(), whiteScroll, 0, chr.isGM());
ScrollResult scrollSuccess = Equip.ScrollResult.FAIL; // fail ScrollResult scrollSuccess = Equip.ScrollResult.FAIL; // fail
if (scrolled == null) { if (scrolled == null) {
scrollSuccess = Equip.ScrollResult.CURSE; scrollSuccess = Equip.ScrollResult.CURSE;
@@ -112,9 +114,17 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
if(!ItemConstants.isWeddingRing(toScroll.getItemId())) { if(!ItemConstants.isWeddingRing(toScroll.getItemId())) {
mods.add(new ModifyInventory(3, toScroll)); mods.add(new ModifyInventory(3, toScroll));
if (dst < 0) { if (dst < 0) {
c.getPlayer().getInventory(MapleInventoryType.EQUIPPED).removeItem(toScroll.getPosition()); MapleInventory inv = chr.getInventory(MapleInventoryType.EQUIPPED);
inv.lockInventory();
try {
chr.unequippedItem(toScroll);
inv.removeItem(toScroll.getPosition());
} finally {
inv.unlockInventory();
}
} else { } else {
c.getPlayer().getInventory(MapleInventoryType.EQUIP).removeItem(toScroll.getPosition()); chr.getInventory(MapleInventoryType.EQUIP).removeItem(toScroll.getPosition());
} }
} else { } else {
scrolled = toScroll; scrolled = toScroll;
@@ -128,13 +138,13 @@ public final class ScrollHandler extends AbstractMaplePacketHandler {
mods.add(new ModifyInventory(0, scrolled)); mods.add(new ModifyInventory(0, scrolled));
} }
c.announce(MaplePacketCreator.modifyInventory(true, mods)); c.announce(MaplePacketCreator.modifyInventory(true, mods));
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.getScrollEffect(c.getPlayer().getId(), scrollSuccess, legendarySpirit)); chr.getMap().broadcastMessage(MaplePacketCreator.getScrollEffect(chr.getId(), scrollSuccess, legendarySpirit));
if (dst < 0 && (scrollSuccess == Equip.ScrollResult.SUCCESS || scrollSuccess == Equip.ScrollResult.CURSE)) { if (dst < 0 && (scrollSuccess == Equip.ScrollResult.SUCCESS || scrollSuccess == Equip.ScrollResult.CURSE)) {
c.getPlayer().equipChanged(); chr.equipChanged();
} }
} }
public boolean canScroll(int scrollid, int itemid) { private static boolean canScroll(int scrollid, int itemid) {
int sid = scrollid / 100; int sid = scrollid / 100;
switch(sid) { switch(sid) {
@@ -26,16 +26,13 @@ import java.awt.Point;
import net.AbstractMaplePacketHandler; import net.AbstractMaplePacketHandler;
import server.MapleStatEffect; import server.MapleStatEffect;
import server.life.MapleMonster; import server.life.MapleMonster;
import tools.FilePrinter;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor; import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleCharacter; import client.MapleCharacter;
import client.autoban.AutobanFactory;
import client.MapleClient; import client.MapleClient;
import client.MapleStat; import client.MapleStat;
import client.Skill; import client.Skill;
import client.SkillFactory; import client.SkillFactory;
import constants.GameConstants;
import constants.ServerConstants; import constants.ServerConstants;
import constants.skills.Brawler; import constants.skills.Brawler;
import constants.skills.Corsair; import constants.skills.Corsair;
@@ -484,8 +484,10 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
for (byte i = 0; i < 3; i++) { for (byte i = 0; i < 3; i++) {
MaplePet pet = player.getPet(i); MaplePet pet = player.getPet(i);
if (pet != null) { if (pet != null) {
if (pet.canConsume(itemId)) { Pair<Integer, Boolean> p = pet.canConsume(itemId);
pet.gainClosenessFullness(player, 100, 100, 1);
if (p.getRight()) {
pet.gainClosenessFullness(player, p.getLeft(), 100, 1);
remove(c, itemId); remove(c, itemId);
break; break;
} }
@@ -30,8 +30,8 @@ import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import server.TimerManager; import server.TimerManager;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
/** /**
* *
@@ -89,6 +89,7 @@ public abstract class BaseScheduler {
private void runBaseSchedule() { private void runBaseSchedule() {
List<Object> toRemove; List<Object> toRemove;
Map<Object, Pair<Runnable, Long>> registeredEntriesCopy;
lockScheduler(); lockScheduler();
try { try {
@@ -104,11 +105,16 @@ public abstract class BaseScheduler {
return; return;
} }
idleProcs = 0; idleProcs = 0;
registeredEntriesCopy = new HashMap<>(registeredEntries);
} finally {
unlockScheduler();
}
long timeNow = System.currentTimeMillis(); long timeNow = System.currentTimeMillis();
toRemove = new LinkedList<>(); toRemove = new LinkedList<>();
for(Entry<Object, Pair<Runnable, Long>> rmd : registeredEntries.entrySet()) { for(Entry<Object, Pair<Runnable, Long>> rmd : registeredEntriesCopy.entrySet()) {
Pair<Runnable, Long> r = rmd.getValue(); Pair<Runnable, Long> r = rmd.getValue();
if(r.getRight() < timeNow) { if(r.getRight() < timeNow) {
@@ -117,12 +123,16 @@ public abstract class BaseScheduler {
} }
} }
for(Object mse : toRemove) { if(!toRemove.isEmpty()) {
registeredEntries.remove(mse); lockScheduler();
try {
for(Object o : toRemove) {
registeredEntries.remove(o);
} }
} finally { } finally {
unlockScheduler(); unlockScheduler();
} }
}
dispatchRemovedEntries(toRemove, true); dispatchRemovedEntries(toRemove, true);
} }
@@ -21,7 +21,7 @@ package net.server.channel.worker;
import java.util.Collections; import java.util.Collections;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
@@ -19,13 +19,13 @@
*/ */
package net.server.channel.worker; package net.server.channel.worker;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
/** /**
* *
@@ -0,0 +1,36 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.channel.worker;
import net.server.audit.locks.MonitoredLockType;
/**
*
* @author Ronan
*/
public class MobClearSkillScheduler extends BaseScheduler {
public MobClearSkillScheduler() {
super(MonitoredLockType.CHANNEL_MOBSKILL);
}
public void registerClearSkillAction(Runnable runAction, long delay) {
registerEntry(runAction, runAction, delay);
}
}
@@ -0,0 +1,36 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft 2016 - 2018 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.channel.worker;
import net.server.audit.locks.MonitoredLockType;
/**
*
* @author Ronan
*/
public class MobMistScheduler extends BaseScheduler {
public MobMistScheduler() {
super(MonitoredLockType.CHANNEL_MOBMIST);
}
public void registerMistCancelAction(Runnable runAction, long delay) {
registerEntry(runAction, runAction, delay);
}
}
@@ -26,8 +26,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
/** /**
* *
@@ -19,7 +19,7 @@
*/ */
package net.server.channel.worker; package net.server.channel.worker;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
+2 -2
View File
@@ -36,13 +36,13 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import net.server.Server; import net.server.Server;
import net.server.channel.Channel; import net.server.channel.Channel;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
public class MapleGuild { public class MapleGuild {
+2 -2
View File
@@ -30,9 +30,9 @@ import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Map; import java.util.Map;
import java.util.Comparator; import java.util.Comparator;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
public class MapleParty { public class MapleParty {
private int id; private int id;
+2 -2
View File
@@ -48,7 +48,7 @@ import java.util.SortedMap;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import java.util.Set; import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
@@ -75,7 +75,7 @@ import net.server.guild.MapleGuildSummary;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
+70 -2
View File
@@ -23,6 +23,7 @@ package scripting;
import java.awt.Point; import java.awt.Point;
import java.util.Arrays; import java.util.Arrays;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
@@ -36,7 +37,6 @@ import net.server.world.MaplePartyCharacter;
import scripting.event.EventInstanceManager; import scripting.event.EventInstanceManager;
import scripting.event.EventManager; import scripting.event.EventManager;
import scripting.npc.NPCScriptManager; import scripting.npc.NPCScriptManager;
import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
import server.expeditions.MapleExpedition; import server.expeditions.MapleExpedition;
import server.expeditions.MapleExpeditionType; import server.expeditions.MapleExpeditionType;
@@ -58,9 +58,11 @@ import client.SkillFactory;
import client.inventory.Equip; import client.inventory.Equip;
import client.inventory.Item; import client.inventory.Item;
import client.inventory.MapleInventory; import client.inventory.MapleInventory;
import client.inventory.MapleInventoryProof;
import client.inventory.MapleInventoryType; import client.inventory.MapleInventoryType;
import client.inventory.MaplePet; import client.inventory.MaplePet;
import client.inventory.ModifyInventory; import client.inventory.ModifyInventory;
import client.inventory.manipulator.MapleInventoryManipulator;
import constants.GameConstants; import constants.GameConstants;
import constants.ItemConstants; import constants.ItemConstants;
import constants.ServerConstants; import constants.ServerConstants;
@@ -247,7 +249,73 @@ public class AbstractPlayerInteraction {
addedItems.add(new Pair<>(it, ItemConstants.getInventoryType(itemids.get(i)))); addedItems.add(new Pair<>(it, ItemConstants.getInventoryType(itemids.get(i))));
} }
return MapleInventory.checkSpots(c.getPlayer(), addedItems); return MapleInventory.checkSpots(c.getPlayer(), addedItems, false);
}
public boolean canHold(int itemid, int quantity, int removeItemid, int removeQuantity) {
return canHoldAllAfterRemoving(Collections.singletonList(itemid), Collections.singletonList(quantity), Collections.singletonList(removeItemid), Collections.singletonList(removeQuantity));
}
private static List<Pair<Item, MapleInventoryType>> prepareProofInventoryItems(List<Pair<Integer, Integer>> items) {
List<Pair<Item, MapleInventoryType>> addedItems = new LinkedList<>();
for(Pair<Integer, Integer> p : items) {
Item it = new Item(p.getLeft(), (short) 0, p.getRight().shortValue());
addedItems.add(new Pair<>(it, MapleInventoryType.CANHOLD));
}
return addedItems;
}
private static List<List<Pair<Integer, Integer>>> prepareInventoryItemList(List<Integer> itemids, List<Integer> quantity) {
int size = Math.min(itemids.size(), quantity.size());
List<List<Pair<Integer, Integer>>> invList = new ArrayList<>(6);
for(int i = MapleInventoryType.UNDEFINED.getType(); i < MapleInventoryType.CASH.getType(); i++) {
invList.add(new LinkedList<Pair<Integer, Integer>>());
}
for(int i = 0; i < size; i++) {
int itemid = itemids.get(i);
invList.get(ItemConstants.getInventoryType(itemid).getType()).add(new Pair<>(itemid, quantity.get(i)));
}
return invList;
}
public boolean canHoldAllAfterRemoving(List<Integer> toAddItemids, List<Integer> toAddQuantity, List<Integer> toRemoveItemids, List<Integer> toRemoveQuantity) {
List<List<Pair<Integer, Integer>>> toAddItemList = prepareInventoryItemList(toAddItemids, toAddQuantity);
List<List<Pair<Integer, Integer>>> toRemoveItemList = prepareInventoryItemList(toRemoveItemids, toRemoveQuantity);
MapleInventoryProof prfInv = (MapleInventoryProof) this.getInventory(MapleInventoryType.CANHOLD);
prfInv.lockInventory();
try {
for(int i = MapleInventoryType.EQUIP.getType(); i < MapleInventoryType.CASH.getType(); i++) {
List<Pair<Integer, Integer>> toAdd = toAddItemList.get(i);
if(!toAdd.isEmpty()) {
List<Pair<Integer, Integer>> toRemove = toRemoveItemList.get(i);
MapleInventory inv = this.getInventory(i);
prfInv.cloneContents(inv);
for(Pair<Integer, Integer> p : toRemove) {
MapleInventoryManipulator.removeById(c, MapleInventoryType.CANHOLD, p.getLeft(), p.getRight(), false, false);
}
List<Pair<Item, MapleInventoryType>> addItems = prepareProofInventoryItems(toAdd);
boolean canHold = MapleInventory.checkSpots(c.getPlayer(), addItems, true);
if(!canHold) {
return false;
}
}
}
} finally {
prfInv.flushContents();
prfInv.unlockInventory();
}
return true;
} }
//---- \/ \/ \/ \/ \/ \/ \/ NOT TESTED \/ \/ \/ \/ \/ \/ \/ \/ \/ ---- //---- \/ \/ \/ \/ \/ \/ \/ NOT TESTED \/ \/ \/ \/ \/ \/ \/ \/ \/ ----
@@ -35,14 +35,13 @@ import java.util.Set;
import java.util.Iterator; import java.util.Iterator;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock;
import tools.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import javax.script.ScriptException; import javax.script.ScriptException;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
import net.server.world.MapleParty; import net.server.world.MapleParty;
import net.server.world.MaplePartyCharacter; import net.server.world.MaplePartyCharacter;
import provider.MapleDataProviderFactory; import provider.MapleDataProviderFactory;
@@ -70,7 +69,6 @@ import server.MapleItemInformationProvider;
import server.life.MapleLifeFactory; import server.life.MapleLifeFactory;
import server.life.MapleNPC; import server.life.MapleNPC;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.locks.MonitoredLockType;
/** /**
* *
+2 -2
View File
@@ -54,8 +54,8 @@ import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
/** /**
* *
+2 -2
View File
@@ -32,7 +32,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import provider.MapleData; import provider.MapleData;
import provider.MapleDataProvider; import provider.MapleDataProvider;
@@ -47,7 +47,7 @@ import client.inventory.MapleInventoryType;
import client.inventory.MaplePet; import client.inventory.MaplePet;
import constants.ItemConstants; import constants.ItemConstants;
import java.util.Collections; import java.util.Collections;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/* /*
* @author Flav * @author Flav
+29 -9
View File
@@ -123,6 +123,7 @@ public class MapleItemInformationProvider {
protected Map<Integer, Integer> makerCatalystCache = new HashMap<>(); protected Map<Integer, Integer> makerCatalystCache = new HashMap<>();
protected Map<Integer, Map<String, Integer>> skillUpgradeCache = new HashMap<>(); protected Map<Integer, Map<String, Integer>> skillUpgradeCache = new HashMap<>();
protected Map<Integer, MapleData> skillUpgradeInfoCache = new HashMap<>(); protected Map<Integer, MapleData> skillUpgradeInfoCache = new HashMap<>();
protected Map<Integer, Pair<Integer, Set<Integer>>> cashPetFoodCache = new HashMap<>();
private MapleItemInformationProvider() { private MapleItemInformationProvider() {
loadCardIdData(); loadCardIdData();
@@ -1298,18 +1299,37 @@ public class MapleItemInformationProvider {
return ret; return ret;
} }
public List<Integer> petsCanConsume(int itemId) { public Pair<Integer, Boolean> canPetConsume(Integer petId, Integer itemId) {
List<Integer> ret = new ArrayList<>(); Pair<Integer, Set<Integer>> foodData = cashPetFoodCache.get(itemId);
if(foodData == null) {
Set<Integer> pets = new HashSet<>(4);
int inc = 1;
MapleData data = getItemData(itemId); MapleData data = getItemData(itemId);
int curPetId; if(data != null) {
for (int i = 0; i < data.getChildren().size(); i++) { MapleData specData = data.getChildByPath("spec");
curPetId = MapleDataTool.getInt("spec/" + Integer.toString(i), data, 0); for(MapleData specItem : specData.getChildren()) {
if (curPetId == 0) { String itemName = specItem.getName();
break;
try {
Integer.parseInt(itemName); // check if it's a petid node
Integer petid = MapleDataTool.getInt(specItem, 0);
pets.add(petid);
} catch(NumberFormatException npe) {
if(itemName.contentEquals("inc")) {
inc = MapleDataTool.getInt(specItem, 1);
} }
ret.add(Integer.valueOf(curPetId));
} }
return ret; }
}
foodData = new Pair<>(inc, pets);
cashPetFoodCache.put(itemId, foodData);
}
return new Pair<>(foodData.getLeft(), foodData.getRight().contains(petId));
} }
public boolean isQuestItem(int itemId) { public boolean isQuestItem(int itemId) {
+37 -17
View File
@@ -718,27 +718,30 @@ public class MapleStatEffect {
} }
public boolean applyTo(MapleCharacter chr) { public boolean applyTo(MapleCharacter chr) {
return applyTo(chr, chr, true, null, false); return applyTo(chr, chr, true, null, false, 1);
} }
public boolean applyTo(MapleCharacter chr, boolean useMaxRange) { public boolean applyTo(MapleCharacter chr, boolean useMaxRange) {
return applyTo(chr, chr, true, null, useMaxRange); return applyTo(chr, chr, true, null, useMaxRange, 1);
} }
public boolean applyTo(MapleCharacter chr, Point pos) { public boolean applyTo(MapleCharacter chr, Point pos) {
return applyTo(chr, chr, true, pos, false); return applyTo(chr, chr, true, pos, false, 1);
} }
// primary: the player caster of the buff // primary: the player caster of the buff
private boolean applyTo(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary, Point pos, boolean useMaxRange) { private boolean applyTo(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary, Point pos, boolean useMaxRange, int affectedPlayers) {
if (skill && (sourceid == GM.HIDE || sourceid == SuperGM.HIDE)) { if (skill && (sourceid == GM.HIDE || sourceid == SuperGM.HIDE)) {
applyto.toggleHide(false); applyto.toggleHide(false);
return true; return true;
} }
int hpchange = calcHPChange(applyfrom, primary); if (primary && isHeal()) {
int mpchange = calcMPChange(applyfrom, primary); affectedPlayers = applyBuff(applyfrom, useMaxRange);
}
int hpchange = calcHPChange(applyfrom, primary, affectedPlayers);
int mpchange = calcMPChange(applyfrom, primary);
if (primary) { if (primary) {
if (itemConNo != 0) { if (itemConNo != 0) {
if(!applyto.getClient().getAbstractPlayerInteraction().hasItem(itemCon, itemConNo)) { if(!applyto.getClient().getAbstractPlayerInteraction().hasItem(itemCon, itemConNo)) {
@@ -747,9 +750,7 @@ public class MapleStatEffect {
} }
MapleInventoryManipulator.removeById(applyto.getClient(), ItemConstants.getInventoryType(itemCon), itemCon, itemConNo, false, true); MapleInventoryManipulator.removeById(applyto.getClient(), ItemConstants.getInventoryType(itemCon), itemCon, itemConNo, false, true);
} }
} } else {
List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<>(2);
if (!primary) {
if(isResurrection()) { if(isResurrection()) {
hpchange = applyto.getMaxHp(); hpchange = applyto.getMaxHp();
applyto.setStance(0); applyto.setStance(0);
@@ -758,6 +759,7 @@ public class MapleStatEffect {
applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapObject(applyto), false); applyto.getMap().broadcastMessage(applyto, MaplePacketCreator.spawnPlayerMapObject(applyto), false);
} }
} }
if (isDispel() && makeChanceResult()) { if (isDispel() && makeChanceResult()) {
applyto.dispelDebuffs(); applyto.dispelDebuffs();
} else if (isCureAllAbnormalStatus()) { } else if (isCureAllAbnormalStatus()) {
@@ -770,6 +772,8 @@ public class MapleStatEffect {
/*if (applyfrom.getMp() < getMpCon()) { /*if (applyfrom.getMp() < getMpCon()) {
AutobanFactory.MPCON.addPoint(applyfrom.getAutobanManager(), "mpCon hack for skill:" + sourceid + "; Player MP: " + applyto.getMp() + " MP Needed: " + getMpCon()); AutobanFactory.MPCON.addPoint(applyfrom.getAutobanManager(), "mpCon hack for skill:" + sourceid + "; Player MP: " + applyto.getMp() + " MP Needed: " + getMpCon());
} */ } */
List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<>(2);
if (hpchange != 0) { if (hpchange != 0) {
if (hpchange < 0 && (-hpchange) >= applyto.getHp() && (!applyto.hasDisease(MapleDisease.ZOMBIFY) || hpCon > 0)) { if (hpchange < 0 && (-hpchange) >= applyto.getHp() && (!applyto.hasDisease(MapleDisease.ZOMBIFY) || hpCon > 0)) {
if(!applyto.isGM()) { if(!applyto.isGM()) {
@@ -784,8 +788,9 @@ public class MapleStatEffect {
applyto.setHp(newHp); applyto.setHp(newHp);
hpmpupdate.add(new Pair<>(MapleStat.HP, Integer.valueOf(applyto.getHp()))); hpmpupdate.add(new Pair<>(MapleStat.HP, Integer.valueOf(applyto.getHp())));
} }
int newMp = applyto.getMp() + mpchange;
if (mpchange != 0) { if (mpchange != 0) {
int newMp = applyto.getMp() + mpchange;
if (mpchange < 0 && -mpchange > applyto.getMp()) { if (mpchange < 0 && -mpchange > applyto.getMp()) {
if(!applyto.isGM()) { if(!applyto.isGM()) {
applyto.getClient().announce(MaplePacketCreator.enableActions()); applyto.getClient().announce(MaplePacketCreator.enableActions());
@@ -860,13 +865,15 @@ public class MapleStatEffect {
applyBuffEffect(applyfrom, applyto, primary); applyBuffEffect(applyfrom, applyto, primary);
} }
if (primary && (overTime || isHeal())) { if (primary) {
if (overTime) {
applyBuff(applyfrom, useMaxRange); applyBuff(applyfrom, useMaxRange);
} }
if (primary && isMonsterBuff()) { if (isMonsterBuff()) {
applyMonsterBuff(applyfrom); applyMonsterBuff(applyfrom);
} }
}
if (this.getFatigue() != 0) { if (this.getFatigue() != 0) {
applyto.getMount().setTiredness(applyto.getMount().getTiredness() + this.getFatigue()); applyto.getMount().setTiredness(applyto.getMount().getTiredness() + this.getFatigue());
@@ -927,7 +934,9 @@ public class MapleStatEffect {
return true; return true;
} }
private void applyBuff(MapleCharacter applyfrom, boolean useMaxRange) { private int applyBuff(MapleCharacter applyfrom, boolean useMaxRange) {
int affectedc = 1;
if (isPartyBuff() && (applyfrom.getParty() != null || isGmBuff())) { if (isPartyBuff() && (applyfrom.getParty() != null || isGmBuff())) {
Rectangle bounds = (!useMaxRange) ? calculateBoundingBox(applyfrom.getPosition(), applyfrom.isFacingLeft()) : new Rectangle(Integer.MIN_VALUE / 2, Integer.MIN_VALUE / 2, Integer.MAX_VALUE, Integer.MAX_VALUE); Rectangle bounds = (!useMaxRange) ? calculateBoundingBox(applyfrom.getPosition(), applyfrom.isFacingLeft()) : new Rectangle(Integer.MIN_VALUE / 2, Integer.MIN_VALUE / 2, Integer.MAX_VALUE, Integer.MAX_VALUE);
List<MapleMapObject> affecteds = applyfrom.getMap().getMapObjectsInRect(bounds, Arrays.asList(MapleMapObjectType.PLAYER)); List<MapleMapObject> affecteds = applyfrom.getMap().getMapObjectsInRect(bounds, Arrays.asList(MapleMapObjectType.PLAYER));
@@ -935,17 +944,27 @@ public class MapleStatEffect {
for (MapleMapObject affectedmo : affecteds) { for (MapleMapObject affectedmo : affecteds) {
MapleCharacter affected = (MapleCharacter) affectedmo; MapleCharacter affected = (MapleCharacter) affectedmo;
if (affected != applyfrom && (isGmBuff() || applyfrom.getParty().equals(affected.getParty()))) { if (affected != applyfrom && (isGmBuff() || applyfrom.getParty().equals(affected.getParty()))) {
if ((!isResurrection() && affected.isAlive()) || (isResurrection() && !affected.isAlive())) { if (!isResurrection()) {
if (affected.isAlive()) {
affectedp.add(affected);
}
} else {
if (!affected.isAlive()) {
affectedp.add(affected); affectedp.add(affected);
} }
} }
} }
}
affectedc += affectedp.size(); // used for heal
for (MapleCharacter affected : affectedp) { for (MapleCharacter affected : affectedp) {
applyTo(applyfrom, affected, false, null, useMaxRange); applyTo(applyfrom, affected, false, null, useMaxRange, affectedc);
affected.getClient().announce(MaplePacketCreator.showOwnBuffEffect(sourceid, 2)); affected.getClient().announce(MaplePacketCreator.showOwnBuffEffect(sourceid, 2));
affected.getMap().broadcastMessage(affected, MaplePacketCreator.showBuffeffect(affected.getId(), sourceid, 2), false); affected.getMap().broadcastMessage(affected, MaplePacketCreator.showBuffeffect(affected.getId(), sourceid, 2), false);
} }
} }
return affectedc;
} }
private void applyMonsterBuff(MapleCharacter applyfrom) { private void applyMonsterBuff(MapleCharacter applyfrom) {
@@ -1158,7 +1177,7 @@ public class MapleStatEffect {
} }
} }
private int calcHPChange(MapleCharacter applyfrom, boolean primary) { private int calcHPChange(MapleCharacter applyfrom, boolean primary, int affectedPlayers) {
int hpchange = 0; int hpchange = 0;
if (hp != 0) { if (hp != 0) {
if (!skill) { if (!skill) {
@@ -1171,7 +1190,8 @@ public class MapleStatEffect {
hpchange /= 2; hpchange /= 2;
} }
} else { // assumption: this is heal } else { // assumption: this is heal
hpchange += makeHealHP(hp / 100.0, applyfrom.getTotalMagic(), 3, 5); float hpHeal = (applyfrom.getMaxHpEquipped() * (float) hp / (100.0f * affectedPlayers));
hpchange += hpHeal;
if (applyfrom.hasDisease(MapleDisease.ZOMBIFY)) { if (applyfrom.hasDisease(MapleDisease.ZOMBIFY)) {
hpchange = -hpchange; hpchange = -hpchange;
hpCon = 0; hpCon = 0;
+2 -2
View File
@@ -39,11 +39,11 @@ import provider.MapleData;
import provider.MapleDataProvider; import provider.MapleDataProvider;
import provider.MapleDataProviderFactory; import provider.MapleDataProviderFactory;
import provider.MapleDataTool; import provider.MapleDataTool;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
+12 -8
View File
@@ -55,7 +55,7 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import net.server.Server; import net.server.Server;
import net.server.channel.Channel; import net.server.channel.Channel;
import net.server.world.World; import net.server.world.World;
@@ -70,7 +70,7 @@ import server.maps.MapleMapObjectType;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.Randomizer; import tools.Randomizer;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
public class MapleMonster extends AbstractLoadedMapleLife { public class MapleMonster extends AbstractLoadedMapleLife {
private ChangeableStats ostats = null; //unused, v83 WZs offers no support for changeable stats. private ChangeableStats ostats = null; //unused, v83 WZs offers no support for changeable stats.
@@ -1248,14 +1248,15 @@ public class MapleMonster extends AbstractLoadedMapleLife {
} }
final MapleMonster mons = this; final MapleMonster mons = this;
TimerManager.getInstance().schedule( MapleMap mmap = mons.getMap();
new Runnable() { Runnable r = new Runnable() {
@Override @Override
public void run() { public void run() {
mons.clearSkill(skillId, level); mons.clearSkill(skillId, level);
} }
}, cooltime); };
mmap.getChannelServer().registerMobClearSkillAction(mmap.getId(), r, cooltime);
} }
public void clearSkill(int skillId, int level) { public void clearSkill(int skillId, int level) {
@@ -1359,8 +1360,9 @@ public class MapleMonster extends AbstractLoadedMapleLife {
final ElementalEffectiveness fEE = stats.getEffectiveness(e); final ElementalEffectiveness fEE = stats.getEffectiveness(e);
if (!fEE.equals(ElementalEffectiveness.WEAK)) { if (!fEE.equals(ElementalEffectiveness.WEAK)) {
stats.setEffectiveness(e, ee); stats.setEffectiveness(e, ee);
TimerManager.getInstance().schedule(new Runnable() {
MapleMap mmap = this.getMap();
Runnable r = new Runnable() {
@Override @Override
public void run() { public void run() {
monsterLock.lock(); monsterLock.lock();
@@ -1371,7 +1373,9 @@ public class MapleMonster extends AbstractLoadedMapleLife {
monsterLock.unlock(); monsterLock.unlock();
} }
} }
}, milli); };
mmap.getChannelServer().registerMobClearSkillAction(mmap.getId(), r, milli);
} }
} finally { } finally {
monsterLock.unlock(); monsterLock.unlock();
+1 -1
View File
@@ -196,7 +196,7 @@ public class MobSkill {
} }
break; break;
case 131: // Mist case 131: // Mist
monster.getMap().spawnMist(new MapleMist(calculateBoundingBox(monster.getPosition(), true), monster, this), x * 10, false, false, false); monster.getMap().spawnMist(new MapleMist(calculateBoundingBox(monster.getPosition(), true), monster, this), x * 100, false, false, false);
break; break;
case 132: case 132:
disease = MapleDisease.CONFUSE; disease = MapleDisease.CONFUSE;
+2 -2
View File
@@ -27,15 +27,15 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import tools.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
import provider.MapleData; import provider.MapleData;
import provider.MapleDataProvider; import provider.MapleDataProvider;
import provider.MapleDataProviderFactory; import provider.MapleDataProviderFactory;
import provider.MapleDataTool; import provider.MapleDataTool;
import tools.locks.MonitoredLockType;
/** /**
* *
+2 -2
View File
@@ -27,8 +27,8 @@ import scripting.portal.PortalScriptManager;
import server.MaplePortal; import server.MaplePortal;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
public class MapleGenericPortal implements MaplePortal { public class MapleGenericPortal implements MaplePortal {
+32 -10
View File
@@ -40,13 +40,13 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import net.server.Server; import net.server.Server;
import server.MapleItemInformationProvider; import server.MapleItemInformationProvider;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
@@ -67,7 +67,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
private MapleMap map; private MapleMap map;
private Lock visitorLock = new MonitoredReentrantLock(MonitoredLockType.VISITOR_MERCH, true); private Lock visitorLock = new MonitoredReentrantLock(MonitoredLockType.VISITOR_MERCH, true);
public MapleHiredMerchant(final MapleCharacter owner, int itemId, String desc) { public MapleHiredMerchant(final MapleCharacter owner, String desc, int itemId) {
this.setPosition(owner.getPosition()); this.setPosition(owner.getPosition());
this.start = System.currentTimeMillis(); this.start = System.currentTimeMillis();
this.ownerId = owner.getId(); this.ownerId = owner.getId();
@@ -96,6 +96,22 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
} }
} }
public byte[] getShopRoomInfo() {
visitorLock.lock();
try {
byte count = 0;
for (MapleCharacter visitor : visitors) {
if (visitor != null) {
count++;
}
}
return new byte[]{count, (byte) (visitors.length + 1)};
} finally {
visitorLock.unlock();
}
}
public boolean addVisitor(MapleCharacter visitor) { public boolean addVisitor(MapleCharacter visitor) {
visitorLock.lock(); visitorLock.lock();
try { try {
@@ -103,6 +119,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
if (i > -1) { if (i > -1) {
visitors[i] = visitor; visitors[i] = visitor;
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorAdd(visitor, i + 1)); broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorAdd(visitor, i + 1));
this.getMap().broadcastMessage(MaplePacketCreator.updateHiredMerchantBox(this));
return true; return true;
} }
@@ -123,6 +140,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
if (visitors[slot] != null && visitors[slot].getId() == visitor.getId()) { if (visitors[slot] != null && visitors[slot].getId() == visitor.getId()) {
visitors[slot] = null; visitors[slot] = null;
broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorLeave(slot + 1)); broadcastToVisitors(MaplePacketCreator.hiredMerchantVisitorLeave(slot + 1));
this.getMap().broadcastMessage(MaplePacketCreator.updateHiredMerchantBox(this));
} }
} finally { } finally {
visitorLock.unlock(); visitorLock.unlock();
@@ -151,15 +169,19 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
visitorLock.lock(); visitorLock.lock();
try { try {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
if (visitors[i] != null) { MapleCharacter visitor = visitors[i];
visitors[i].setHiredMerchant(null);
visitors[i].getClient().announce(MaplePacketCreator.leaveHiredMerchant(i + 1, 0x11)); if (visitor != null) {
visitors[i].getClient().announce(MaplePacketCreator.hiredMerchantMaintenanceMessage()); visitor.setHiredMerchant(null);
visitor.getClient().announce(MaplePacketCreator.leaveHiredMerchant(i + 1, 0x11));
visitor.getClient().announce(MaplePacketCreator.hiredMerchantMaintenanceMessage());
visitors[i] = null; visitors[i] = null;
} }
} }
this.getMap().broadcastMessage(MaplePacketCreator.updateHiredMerchantBox(this));
} finally { } finally {
visitorLock.unlock(); visitorLock.unlock();
} }
@@ -272,7 +294,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
public void forceClose() { public void forceClose() {
//Server.getInstance().getChannel(world, channel).removeHiredMerchant(ownerId); //Server.getInstance().getChannel(world, channel).removeHiredMerchant(ownerId);
map.broadcastMessage(MaplePacketCreator.destroyHiredMerchant(getOwnerId())); map.broadcastMessage(MaplePacketCreator.removeHiredMerchantBox(getOwnerId()));
map.removeMapObject(this); map.removeMapObject(this);
MapleCharacter owner = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(ownerId); MapleCharacter owner = Server.getInstance().getWorld(world).getPlayerStorage().getCharacterById(ownerId);
@@ -331,7 +353,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
public void closeShop(MapleClient c, boolean timeout) { public void closeShop(MapleClient c, boolean timeout) {
map.removeMapObject(this); map.removeMapObject(this);
map.broadcastMessage(MaplePacketCreator.destroyHiredMerchant(ownerId)); map.broadcastMessage(MaplePacketCreator.removeHiredMerchantBox(ownerId));
c.getChannelServer().removeHiredMerchant(ownerId); c.getChannelServer().removeHiredMerchant(ownerId);
try { try {
@@ -634,7 +656,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
@Override @Override
public void sendSpawnData(MapleClient client) { public void sendSpawnData(MapleClient client) {
client.announce(MaplePacketCreator.spawnHiredMerchant(this)); client.announce(MaplePacketCreator.spawnHiredMerchantBox(this));
} }
public class SoldItem { public class SoldItem {
+17 -16
View File
@@ -52,9 +52,10 @@ import java.util.Map.Entry;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import tools.locks.MonitoredReentrantLock;
import tools.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantLock;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
@@ -90,7 +91,6 @@ import tools.FilePrinter;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.Randomizer; import tools.Randomizer;
import tools.locks.MonitoredLockType;
public class MapleMap { public class MapleMap {
private static final List<MapleMapObjectType> rangedMapobjectTypes = Arrays.asList(MapleMapObjectType.SHOP, MapleMapObjectType.ITEM, MapleMapObjectType.NPC, MapleMapObjectType.MONSTER, MapleMapObjectType.DOOR, MapleMapObjectType.SUMMON, MapleMapObjectType.REACTOR); private static final List<MapleMapObjectType> rangedMapobjectTypes = Arrays.asList(MapleMapObjectType.SHOP, MapleMapObjectType.ITEM, MapleMapObjectType.NPC, MapleMapObjectType.MONSTER, MapleMapObjectType.DOOR, MapleMapObjectType.SUMMON, MapleMapObjectType.REACTOR);
@@ -1512,8 +1512,10 @@ public class MapleMap {
chrRLock.lock(); chrRLock.lock();
try { try {
for (MapleCharacter chr : characters) { for (MapleCharacter chr : characters) {
if (!chr.isHidden() && (chr.getControlledMonsters().size() < mincontrolled || mincontrolled == -1)) { int ctrlMonsSize = chr.getControlledMonsters().size();
mincontrolled = chr.getControlledMonsters().size();
if (!chr.isHidden() && (ctrlMonsSize < mincontrolled || mincontrolled == -1)) {
mincontrolled = ctrlMonsSize;
newController = chr; newController = chr;
} }
} }
@@ -1538,8 +1540,7 @@ public class MapleMap {
objectRLock.lock(); objectRLock.lock();
try { try {
return new LinkedList(mapobjects.values()); return new LinkedList(mapobjects.values());
} } finally {
finally {
objectRLock.unlock(); objectRLock.unlock();
} }
} }
@@ -1998,7 +1999,8 @@ public class MapleMap {
} else { } else {
poisonSchedule = null; poisonSchedule = null;
} }
tMan.schedule(new Runnable() {
Runnable mistSchedule = new Runnable() {
@Override @Override
public void run() { public void run() {
removeMapObject(mist); removeMapObject(mist);
@@ -2007,7 +2009,9 @@ public class MapleMap {
} }
broadcastMessage(mist.makeDestroyData()); broadcastMessage(mist.makeDestroyData());
} }
}, duration); };
this.getChannelServer().registerMobMistCancelAction(mapid, mistSchedule, duration);
} }
public void spawnKite(final MapleKite kite) { public void spawnKite(final MapleKite kite) {
@@ -2899,8 +2903,7 @@ public class MapleMap {
} }
return mapChars; return mapChars;
} } finally {
finally {
chrRLock.unlock(); chrRLock.unlock();
} }
} }
@@ -2909,8 +2912,7 @@ public class MapleMap {
chrRLock.lock(); chrRLock.lock();
try { try {
return Collections.unmodifiableCollection(this.characters); return Collections.unmodifiableCollection(this.characters);
} } finally {
finally {
chrRLock.unlock(); chrRLock.unlock();
} }
} }
@@ -2929,7 +2931,7 @@ public class MapleMap {
return null; return null;
} }
private void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) { private static void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) {
if (!chr.isMapObjectVisible(mo)) { // item entered view range if (!chr.isMapObjectVisible(mo)) { // item entered view range
if (mo.getType() == MapleMapObjectType.SUMMON || mo.getPosition().distanceSq(chr.getPosition()) <= getRangedDistance()) { if (mo.getType() == MapleMapObjectType.SUMMON || mo.getPosition().distanceSq(chr.getPosition()) <= getRangedDistance()) {
chr.addVisibleMapObject(mo); chr.addVisibleMapObject(mo);
@@ -3291,8 +3293,7 @@ public class MapleMap {
if(characters.isEmpty()) { if(characters.isEmpty()) {
return; return;
} }
} } finally {
finally {
chrRLock.unlock(); chrRLock.unlock();
} }
+3 -2
View File
@@ -33,10 +33,11 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import tools.locks.MonitoredReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
import provider.MapleData; import provider.MapleData;
import provider.MapleDataProvider; import provider.MapleDataProvider;
import provider.MapleDataTool; import provider.MapleDataTool;
@@ -49,7 +50,7 @@ import server.life.MaplePlayerNPCFactory;
import scripting.event.EventInstanceManager; import scripting.event.EventInstanceManager;
import tools.DatabaseConnection; import tools.DatabaseConnection;
import tools.StringUtil; import tools.StringUtil;
import tools.locks.MonitoredLockType;
public class MapleMapFactory { public class MapleMapFactory {
+2 -2
View File
@@ -25,9 +25,9 @@ import client.MapleClient;
import client.inventory.Item; import client.inventory.Item;
import java.awt.Point; import java.awt.Point;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
public class MapleMapItem extends AbstractMapleMapObject { public class MapleMapItem extends AbstractMapleMapObject {
protected MapleClient ownerClient; protected MapleClient ownerClient;
+2 -2
View File
@@ -26,9 +26,9 @@ import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
+35 -10
View File
@@ -37,13 +37,12 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import net.opcodes.SendOpcode; import net.opcodes.SendOpcode;
import server.MapleItemInformationProvider;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.data.output.MaplePacketLittleEndianWriter; import tools.data.output.MaplePacketLittleEndianWriter;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
@@ -53,6 +52,8 @@ import tools.locks.MonitoredLockType;
public class MaplePlayerShop extends AbstractMapleMapObject { public class MaplePlayerShop extends AbstractMapleMapObject {
private AtomicBoolean open = new AtomicBoolean(false); private AtomicBoolean open = new AtomicBoolean(false);
private MapleCharacter owner; private MapleCharacter owner;
private int itemid;
private MapleCharacter[] visitors = new MapleCharacter[3]; private MapleCharacter[] visitors = new MapleCharacter[3];
private List<MaplePlayerShopItem> items = new ArrayList<>(); private List<MaplePlayerShopItem> items = new ArrayList<>();
private List<SoldItem> sold = new LinkedList<>(); private List<SoldItem> sold = new LinkedList<>();
@@ -63,10 +64,11 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
private Map<Integer, Byte> chatSlot = new LinkedHashMap<>(); private Map<Integer, Byte> chatSlot = new LinkedHashMap<>();
private Lock visitorLock = new MonitoredReentrantLock(MonitoredLockType.VISITOR_PSHOP, true); private Lock visitorLock = new MonitoredReentrantLock(MonitoredLockType.VISITOR_PSHOP, true);
public MaplePlayerShop(MapleCharacter owner, String description) { public MaplePlayerShop(MapleCharacter owner, String description, int itemid) {
this.setPosition(owner.getPosition()); this.setPosition(owner.getPosition());
this.owner = owner; this.owner = owner;
this.description = description; this.description = description;
this.itemid = itemid;
} }
public int getChannel() { public int getChannel() {
@@ -77,6 +79,10 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
return owner.getMapId(); return owner.getMapId();
} }
public int getItemId() {
return itemid;
}
public boolean isOpen() { public boolean isOpen() {
return open.get(); return open.get();
} }
@@ -94,6 +100,22 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
} }
} }
public byte[] getShopRoomInfo() {
visitorLock.lock();
try {
byte count = 0;
for (MapleCharacter visitor : visitors) {
if (visitor != null) {
count++;
}
}
return new byte[]{count, (byte) visitors.length};
} finally {
visitorLock.unlock();
}
}
public boolean isOwner(MapleCharacter c) { public boolean isOwner(MapleCharacter c) {
return owner.equals(c); return owner.equals(c);
} }
@@ -103,9 +125,9 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
if (visitors[i] == null) { if (visitors[i] == null) {
visitors[i] = visitor; visitors[i] = visitor;
visitor.setSlot(i); visitor.setSlot(i);
this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, i + 1));
if(i == 2) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(owner, 1)); this.broadcast(MaplePacketCreator.getPlayerShopNewVisitor(visitor, i + 1));
owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
break; break;
} }
} }
@@ -123,7 +145,9 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
if (visitors[i] != null && visitors[i].getId() == visitor.getId()) { if (visitors[i] != null && visitors[i].getId() == visitor.getId()) {
visitors[i] = null; visitors[i] = null;
visitor.setSlot(-1); visitor.setSlot(-1);
this.broadcast(MaplePacketCreator.getPlayerShopRemoveVisitor(i + 1)); this.broadcast(MaplePacketCreator.getPlayerShopRemoveVisitor(i + 1));
owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
return; return;
} }
} }
@@ -154,6 +178,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
} }
this.broadcastRestoreToVisitors(); this.broadcastRestoreToVisitors();
owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
return; return;
} }
} }
@@ -161,7 +186,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
visitorLock.unlock(); visitorLock.unlock();
} }
if(owner.getPlayerShop() != null) visitor.getMap().broadcastMessage(MaplePacketCreator.addCharBox(owner, 4)); owner.getMap().broadcastMessage(MaplePacketCreator.updatePlayerShopBox(this));
} }
} }
@@ -394,7 +419,7 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
} }
public void closeShop() { public void closeShop() {
owner.getMap().broadcastMessage(MaplePacketCreator.removeCharBox(owner)); owner.getMap().broadcastMessage(MaplePacketCreator.removePlayerShopBox(this));
clearChatLog(); clearChatLog();
removeVisitors(); removeVisitors();
} }
@@ -527,12 +552,12 @@ public class MaplePlayerShop extends AbstractMapleMapObject {
@Override @Override
public void sendDestroyData(MapleClient client) { public void sendDestroyData(MapleClient client) {
client.announce(MaplePacketCreator.removeCharBox(owner)); client.announce(MaplePacketCreator.removePlayerShopBox(this));
} }
@Override @Override
public void sendSpawnData(MapleClient client) { public void sendSpawnData(MapleClient client) {
client.announce(MaplePacketCreator.addCharBox(owner, 4)); client.announce(MaplePacketCreator.updatePlayerShopBox(this));
} }
@Override @Override
+2 -2
View File
@@ -29,13 +29,13 @@ import java.util.List;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import tools.locks.MonitoredReentrantLock; import net.server.audit.locks.MonitoredReentrantLock;
import scripting.reactor.ReactorScriptManager; import scripting.reactor.ReactorScriptManager;
import server.TimerManager; import server.TimerManager;
import tools.MaplePacketCreator; import tools.MaplePacketCreator;
import tools.Pair; import tools.Pair;
import tools.locks.MonitoredLockType; import net.server.audit.locks.MonitoredLockType;
/** /**
* *
+17 -14
View File
@@ -54,7 +54,7 @@ public class MapleQuest {
private static final Set<Short> exploitableQuests = new HashSet<>(); private static final Set<Short> exploitableQuests = new HashSet<>();
static { static {
exploitableQuests.add((short) 2338); exploitableQuests.add((short) 2338); // there are a lot more exploitable quests, they need to be nit-picked
exploitableQuests.add((short) 3637); exploitableQuests.add((short) 3637);
exploitableQuests.add((short) 3714); exploitableQuests.add((short) 3714);
exploitableQuests.add((short) 21752); exploitableQuests.add((short) 21752);
@@ -106,25 +106,22 @@ public class MapleQuest {
MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(startReq.getName()); MapleQuestRequirementType type = MapleQuestRequirementType.getByWZName(startReq.getName());
if (type.equals(MapleQuestRequirementType.INTERVAL)) { if (type.equals(MapleQuestRequirementType.INTERVAL)) {
repeatable = true; repeatable = true;
} } else if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
infoNumber = (short) MapleDataTool.getInt(startReq, 0); infoNumber = (short) MapleDataTool.getInt(startReq, 0);
} } else if (type.equals(MapleQuestRequirementType.MOB)) {
MapleQuestRequirement req = this.getRequirement(type, startReq);
if(req == null)
continue;
if (type.equals(MapleQuestRequirementType.MOB)) {
for (MapleData mob : startReq.getChildren()) { for (MapleData mob : startReq.getChildren()) {
relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id"))); relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id")));
} }
} }
MapleQuestRequirement req = this.getRequirement(type, startReq);
if(req == null)
continue;
startReqs.put(type, req); startReqs.put(type, req);
} }
} }
MapleData completeReqData = reqData.getChildByPath("1"); MapleData completeReqData = reqData.getChildByPath("1");
if (completeReqData != null) { if (completeReqData != null) {
for (MapleData completeReq : completeReqData.getChildren()) { for (MapleData completeReq : completeReqData.getChildren()) {
@@ -136,8 +133,7 @@ public class MapleQuest {
if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) { if (type.equals(MapleQuestRequirementType.INFO_NUMBER)) {
infoNumber = (short) MapleDataTool.getInt(completeReq, 0); infoNumber = (short) MapleDataTool.getInt(completeReq, 0);
} } else if (type.equals(MapleQuestRequirementType.MOB)) {
if (type.equals(MapleQuestRequirementType.MOB)) {
for (MapleData mob : completeReq.getChildren()) { for (MapleData mob : completeReq.getChildren()) {
relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id"))); relevantMobs.add(MapleDataTool.getInt(mob.getChildByPath("id")));
} }
@@ -227,6 +223,13 @@ public class MapleQuest {
return str.toString(); return str.toString();
} }
public boolean isSameDayRepeatable() {
if(!repeatable) return false;
IntervalRequirement ir = (IntervalRequirement) startReqs.get(MapleQuestRequirementType.INTERVAL);
return ir.getInterval() < ServerConstants.FAME_GAIN_MIN_HOUR_INTERVAL * 60 * 60 * 1000;
}
public boolean canStartWithoutRequirements(MapleCharacter c) { public boolean canStartWithoutRequirements(MapleCharacter c) {
MapleQuestStatus mqs = c.getQuest(this); MapleQuestStatus mqs = c.getQuest(this);
return !(mqs.getStatus() != Status.NOT_STARTED && !(mqs.getStatus() == Status.COMPLETED && repeatable)); return !(mqs.getStatus() != Status.NOT_STARTED && !(mqs.getStatus() == Status.COMPLETED && repeatable));
+2 -2
View File
@@ -212,7 +212,7 @@ public class ItemAction extends MapleQuestAction {
for(Pair<Item, MapleInventoryType> it: randomList) { for(Pair<Item, MapleInventoryType> it: randomList) {
int idx = it.getRight().getType() - 1; int idx = it.getRight().getType() - 1;
result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getLeft().getItemId(), it.getLeft().getQuantity(), "", rndUsed.get(idx)); result = MapleInventoryManipulator.checkSpaceProgressively(c, it.getLeft().getItemId(), it.getLeft().getQuantity(), "", rndUsed.get(idx), false);
if(result % 2 == 0) { if(result % 2 == 0) {
chr.dropMessage(1, "Please check if you have enough space in your inventory."); chr.dropMessage(1, "Please check if you have enough space in your inventory.");
return false; return false;
@@ -227,7 +227,7 @@ public class ItemAction extends MapleQuestAction {
gainList.add(selected); gainList.add(selected);
} }
if (!MapleInventory.checkSpots(chr, gainList, allSlotUsed)) { if (!MapleInventory.checkSpots(chr, gainList, allSlotUsed, false)) {
chr.dropMessage(1, "Please check if you have enough space in your inventory."); chr.dropMessage(1, "Please check if you have enough space in your inventory.");
return false; return false;
} }
+55 -30
View File
@@ -2182,6 +2182,55 @@ public class MaplePacketCreator {
mplew.write(joinable); mplew.write(joinable);
} }
private static void updateHiredMerchantBoxInfo(MaplePacketLittleEndianWriter mplew, MapleHiredMerchant hm) {
byte[] roomInfo = hm.getShopRoomInfo();
mplew.write(5);
mplew.writeInt(hm.getObjectId());
mplew.writeMapleAsciiString(hm.getDescription());
mplew.write(hm.getItemId() % 100);
mplew.write(roomInfo);
}
public static byte[] updateHiredMerchantBox(MapleHiredMerchant hm) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.UPDATE_HIRED_MERCHANT.getValue());
mplew.writeInt(hm.getOwnerId());
updateHiredMerchantBoxInfo(mplew, hm);
return mplew.getPacket();
}
private static void updatePlayerShopBoxInfo(final MaplePacketLittleEndianWriter mplew, MaplePlayerShop shop) {
byte[] roomInfo = shop.getShopRoomInfo();
mplew.write(4);
mplew.writeInt(shop.getObjectId());
mplew.writeMapleAsciiString(shop.getDescription());
mplew.write(0); // pw
mplew.write(shop.getItemId() % 100);
mplew.write(roomInfo[0]); // curPlayers
mplew.write(roomInfo[1]); // maxPlayers
mplew.write(0);
}
public static byte[] updatePlayerShopBox(MaplePlayerShop shop) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(shop.getOwner().getId());
updatePlayerShopBoxInfo(mplew, shop);
return mplew.getPacket();
}
public static byte[] removePlayerShopBox(MaplePlayerShop shop) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7);
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(shop.getOwner().getId());
mplew.write(0);
return mplew.getPacket();
}
public static byte[] facialExpression(MapleCharacter from, int expression) { public static byte[] facialExpression(MapleCharacter from, int expression) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(10); final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(10);
mplew.writeShort(SendOpcode.FACIAL_EXPRESSION.getValue()); mplew.writeShort(SendOpcode.FACIAL_EXPRESSION.getValue());
@@ -3242,22 +3291,6 @@ public class MaplePacketCreator {
return mplew.getPacket(); return mplew.getPacket();
} }
public static byte[] addCharBox(MapleCharacter c, int type) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(c.getId());
addAnnounceBox(mplew, c.getPlayerShop(), type);
return mplew.getPacket();
}
public static byte[] removeCharBox(MapleCharacter c) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7);
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(c.getId());
mplew.write(0);
return mplew.getPacket();
}
/** /**
* Possible values for <code>speaker</code>:<br> 0: Npc talking (left)<br> * Possible values for <code>speaker</code>:<br> 0: Npc talking (left)<br>
* 1: Npc talking (right)<br> 2: Player talking (left)<br> 3: Player talking * 1: Npc talking (right)<br> 2: Player talking (left)<br> 3: Player talking
@@ -5292,14 +5325,6 @@ public class MaplePacketCreator {
return mplew.getPacket(); return mplew.getPacket();
} }
public static byte[] removeOmokBox(MapleCharacter c) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7);
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(c.getId());
mplew.write(0);
return mplew.getPacket();
}
public static byte[] addMatchCardBox(MapleCharacter c, int ammount, int type) { public static byte[] addMatchCardBox(MapleCharacter c, int ammount, int type) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
@@ -5308,10 +5333,10 @@ public class MaplePacketCreator {
return mplew.getPacket(); return mplew.getPacket();
} }
public static byte[] removeMatchCardBox(MapleCharacter c) { public static byte[] removeMinigameBox(MapleCharacter chr) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(7);
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue()); mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(c.getId()); mplew.writeInt(chr.getId());
mplew.write(0); mplew.write(0);
return mplew.getPacket(); return mplew.getPacket();
} }
@@ -5576,7 +5601,7 @@ public class MaplePacketCreator {
return mplew.getPacket(); return mplew.getPacket();
} }
public static byte[] spawnHiredMerchant(MapleHiredMerchant hm) { public static byte[] spawnHiredMerchantBox(MapleHiredMerchant hm) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.SPAWN_HIRED_MERCHANT.getValue()); mplew.writeShort(SendOpcode.SPAWN_HIRED_MERCHANT.getValue());
mplew.writeInt(hm.getOwnerId()); mplew.writeInt(hm.getOwnerId());
@@ -5588,12 +5613,12 @@ public class MaplePacketCreator {
mplew.write(0x05); mplew.write(0x05);
mplew.writeInt(hm.getObjectId()); mplew.writeInt(hm.getObjectId());
mplew.writeMapleAsciiString(hm.getDescription()); mplew.writeMapleAsciiString(hm.getDescription());
mplew.write(hm.getItemId() % 10); mplew.write(hm.getItemId() % 100);
mplew.write(new byte[]{1, 4}); mplew.write(new byte[]{1, 4});
return mplew.getPacket(); return mplew.getPacket();
} }
public static byte[] destroyHiredMerchant(int id) { public static byte[] removeHiredMerchantBox(int id) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter(); final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.DESTROY_HIRED_MERCHANT.getValue()); mplew.writeShort(SendOpcode.DESTROY_HIRED_MERCHANT.getValue());
mplew.writeInt(id); mplew.writeInt(id);
Binary file not shown.
@@ -2,8 +2,6 @@
<project-private xmlns="http://www.netbeans.org/ns/project-private/1"> <project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/> <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2"> <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group> <group/>
<file>file:/C:/Nexon/MapleSolaxia/HeavenMS/tools/MapleIdRetriever/src/mapleidretriever/MapleIdRetriever.java</file>
</group>
</open-files> </open-files>
</project-private> </project-private>
@@ -46,7 +46,7 @@ import java.util.ArrayList;
* *
*/ */
public class MapleIdRetriever { public class MapleIdRetriever {
private final static boolean INSTALL_SQLTABLE = false; private final static boolean INSTALL_SQLTABLE = true;
static String host = "jdbc:mysql://localhost:3306/heavenms"; static String host = "jdbc:mysql://localhost:3306/heavenms";
static String driver = "com.mysql.jdbc.Driver"; static String driver = "com.mysql.jdbc.Driver";