Using Java ThreadPool + Mob Skills & Event Instance patch + Eqp Merge
Server source now uses Java ThreadPool, recycling used thread resources for next uses. Added Grenade visual effect for other players. Implemented an attempt towards unsynced mob behavior, where reportedly players were able to pin same mob in different sections of the map. Solved several deadlock issues, mostly regarding character synchronized methods, event instance scripts and player/item vision-unvision. Solved an issue where mobs would not cast some skills of it's skillset. Frequent behavior on low-leveled mobs. Fixed a bug on 2nd Maker quest where players could complete it by merely disassembling an equipment. New custom mechanic: equipment merge. Similarly to the Bazaar NPC, every equipment after the selected one is used up, and a fraction of their stat amounts are used as stat gains on the currently equipped items. If restrictions are enabled, players must be high-leveled and Maker lv3 to use it. Skill Storm Break no longer uses up arrows. Added a server flag to allow access for all Aran job skills from the beginning. Implemented Battleship and Super Transformation questline scripts. Fixed a desynchronization within pet position and cash inventory position, that could potentially lead to some inventory issues until relogin. Improved timestamp handling in some handler classes. Spam detection is entirely a server-side matter, hence removed usage of client-sided timestamp content. Refactored some pet response packets, improving some of their behaviors. Fixed some quest issues: Maker lv1 and Omega Sector meteorite one.
This commit is contained in:
+304
-106
@@ -72,6 +72,7 @@ import server.MapleStatEffect;
|
||||
import server.MapleStorage;
|
||||
import server.MapleTrade;
|
||||
import server.TimerManager;
|
||||
import server.ThreadManager;
|
||||
import server.events.MapleEvents;
|
||||
import server.events.RescueGaga;
|
||||
import server.events.gm.MapleFitness;
|
||||
@@ -109,6 +110,7 @@ import tools.packets.Wedding;
|
||||
import client.autoban.AutobanManager;
|
||||
import client.creator.CharacterFactoryRecipe;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Equip.StatUpgrade;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.ItemFactory;
|
||||
import client.inventory.MapleInventory;
|
||||
@@ -159,12 +161,10 @@ import server.life.MobSkillFactory;
|
||||
import server.maps.MapleMapItem;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import server.movement.AbsoluteLifeMovement;
|
||||
import server.movement.LifeMovementFragment;
|
||||
|
||||
public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
private static final MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
private static final String LEVEL_200 = "[Congrats] %s has reached Level 200! Congratulate %s on such an amazing achievement!";
|
||||
private static final String LEVEL_200 = "[Congrats] %s has reached Level %d! Congratulate %s on such an amazing achievement!";
|
||||
private static final String[] BLOCKED_NAMES = {"admin", "owner", "moderator", "intern", "donor", "administrator", "help", "helper", "alert", "notice", "maplestory", "fuck", "wizet", "fucking", "negro", "fuk", "fuc", "penis", "pussy", "asshole", "gay",
|
||||
"nigger", "homo", "suck", "cum", "shit", "shitty", "condom", "security", "official", "rape", "nigga", "sex", "tit", "boner", "orgy", "clit", "asshole", "fatass", "bitch", "support", "gamemaster", "cock", "gaay", "gm",
|
||||
"operate", "master", "sysop", "party", "GameMaster", "community", "message", "event", "test", "meso", "Scania", "yata", "AsiaSoft", "henesys"};
|
||||
@@ -853,10 +853,15 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
List<Pair<MapleBuffStat, Integer>> ldsstat = Collections.singletonList(new Pair<MapleBuffStat, Integer>(MapleBuffStat.DARKSIGHT, 0));
|
||||
getMap().broadcastGMMessage(this, MaplePacketCreator.giveForeignBuff(id, ldsstat), false);
|
||||
for (MapleMonster mon : this.getControlledMonsters()) {
|
||||
mon.setController(null);
|
||||
mon.setControllerHasAggro(false);
|
||||
mon.setControllerKnowsAboutAggro(false);
|
||||
mon.getMap().updateMonsterController(mon);
|
||||
mon.lockMonster();
|
||||
try {
|
||||
mon.setController(null);
|
||||
mon.setControllerHasAggro(false);
|
||||
mon.setControllerKnowsAboutAggro(false);
|
||||
mon.getMap().updateMonsterController(mon);
|
||||
} finally {
|
||||
mon.unlockMonster();
|
||||
}
|
||||
}
|
||||
}
|
||||
announce(MaplePacketCreator.enableActions());
|
||||
@@ -1178,11 +1183,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
|
||||
public void broadcastStance() {
|
||||
AbsoluteLifeMovement alm = new AbsoluteLifeMovement(0, getPosition(), 0, getStance());
|
||||
alm.setPixelsPerSecond(new Point(0, 0));
|
||||
List<LifeMovementFragment> moveUpdate = Collections.singletonList((LifeMovementFragment) alm);
|
||||
|
||||
map.broadcastMessage(this, MaplePacketCreator.movePlayer(id, moveUpdate), false);
|
||||
map.broadcastMessage(this, MaplePacketCreator.movePlayer(id, this.getIdleMovement()), false);
|
||||
}
|
||||
|
||||
public MapleMap getWarpMap(int map) {
|
||||
@@ -1592,11 +1593,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
map.addPlayer(this);
|
||||
visitMap(map);
|
||||
|
||||
silentPartyUpdateInternal(getParty()); // EIM script calls inside
|
||||
prtLock.lock();
|
||||
try {
|
||||
if (party != null) {
|
||||
mpc.setMapId(to.getId());
|
||||
silentPartyUpdateInternal();
|
||||
client.announce(MaplePacketCreator.updateParty(client.getChannel(), party, PartyOperation.SILENT_UPDATE, null));
|
||||
updatePartyMemberHPInternal();
|
||||
}
|
||||
@@ -1605,8 +1606,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
|
||||
if (getMap().getHPDec() > 0) resetHpDecreaseTask();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
FilePrinter.printError(FilePrinter.MAPLE_MAP, "Character " + this.getName() + " got stuck when moving to map " + map.getId() + ".");
|
||||
}
|
||||
|
||||
@@ -1708,19 +1708,29 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
|
||||
public void checkMonsterAggro(MapleMonster monster) {
|
||||
if (!monster.isControllerHasAggro()) {
|
||||
if (monster.getController() == this) {
|
||||
monster.setControllerHasAggro(true);
|
||||
} else {
|
||||
monster.switchController(this, true);
|
||||
monster.lockMonster();
|
||||
try {
|
||||
if (!monster.isControllerHasAggro()) {
|
||||
if (monster.getController() == this) {
|
||||
monster.setControllerHasAggro(true);
|
||||
} else {
|
||||
monster.switchController(this, true);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
}
|
||||
|
||||
public void controlMonster(MapleMonster monster, boolean aggro) {
|
||||
monster.setController(this);
|
||||
controlled.add(monster);
|
||||
client.announce(MaplePacketCreator.controlMonster(monster, false, aggro));
|
||||
monster.lockMonster();
|
||||
try {
|
||||
monster.setController(this);
|
||||
controlled.add(monster);
|
||||
client.announce(MaplePacketCreator.controlMonster(monster, false, aggro));
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean useItem(final int id) {
|
||||
@@ -1768,7 +1778,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
|
||||
if (ob instanceof MapleMapItem) {
|
||||
MapleMapItem mapitem = (MapleMapItem) ob;
|
||||
if (System.currentTimeMillis() - mapitem.getDropTime() < 900 || !mapitem.canBePickedBy(this)) {
|
||||
if (System.currentTimeMillis() - mapitem.getDropTime() < 400 || !mapitem.canBePickedBy(this)) {
|
||||
client.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
@@ -1778,6 +1788,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
mpcs = getPartyMembersOnSameMap();
|
||||
}
|
||||
|
||||
String itemScriptName = null;
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
if (mapitem.isPickedUp()) {
|
||||
@@ -1852,12 +1863,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
} else if (mItem.getItemId() / 10000 == 243) {
|
||||
MapleItemInformationProvider.scriptedItem info = ii.getScriptedItemInfo(mItem.getItemId());
|
||||
if (info.runOnPickup()) {
|
||||
ItemScriptManager ism = ItemScriptManager.getInstance();
|
||||
String scriptName = info.getScript();
|
||||
if (ism.scriptExists(scriptName)) {
|
||||
ism.getItemScript(client, scriptName);
|
||||
}
|
||||
|
||||
itemScriptName = info.getScript();
|
||||
} else {
|
||||
if (!MapleInventoryManipulator.addFromDrop(client, mItem, true)) {
|
||||
client.announce(MaplePacketCreator.enableActions());
|
||||
@@ -1890,6 +1896,13 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
}
|
||||
|
||||
if (itemScriptName != null) {
|
||||
ItemScriptManager ism = ItemScriptManager.getInstance();
|
||||
if (ism.scriptExists(itemScriptName)) {
|
||||
ism.runItemScript(client, itemScriptName);
|
||||
}
|
||||
}
|
||||
}
|
||||
client.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
@@ -2913,16 +2926,21 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized int applyFame(int delta) {
|
||||
int newFame = fame + delta;
|
||||
if (newFame < -30000) {
|
||||
delta = -(30000 + fame);
|
||||
} else if (newFame > 30000) {
|
||||
delta = 30000 - fame;
|
||||
private Pair<Integer, Integer> applyFame(int delta) {
|
||||
petLock.lock();
|
||||
try {
|
||||
int newFame = fame + delta;
|
||||
if (newFame < -30000) {
|
||||
delta = -(30000 + fame);
|
||||
} else if (newFame > 30000) {
|
||||
delta = 30000 - fame;
|
||||
}
|
||||
|
||||
fame += delta;
|
||||
return new Pair<>(fame, delta);
|
||||
} finally {
|
||||
petLock.unlock();
|
||||
}
|
||||
|
||||
fame += delta;
|
||||
return delta;
|
||||
}
|
||||
|
||||
public void gainFame(int delta) {
|
||||
@@ -2930,9 +2948,10 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
|
||||
public boolean gainFame(int delta, MapleCharacter fromPlayer, int mode) {
|
||||
delta = applyFame(delta);
|
||||
Pair<Integer, Integer> fameRes = applyFame(delta);
|
||||
delta = fameRes.getRight();
|
||||
if (delta != 0) {
|
||||
int thisFame = fame;
|
||||
int thisFame = fameRes.getLeft();
|
||||
updateSingleStat(MapleStat.FAME, thisFame);
|
||||
|
||||
if (fromPlayer != null) {
|
||||
@@ -3571,10 +3590,10 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
for (MapleCharacter chr : townChars) {
|
||||
destroyDoor.getTownDoor().sendDestroyData(chr.getClient());
|
||||
}
|
||||
if(destroyDoor.getTownPortal().getId() == 0x80) {
|
||||
if (destroyDoor.getTownPortal().getId() == 0x80) {
|
||||
for (MapleCharacter chr : townChars) {
|
||||
MapleDoor door = chr.getMainTownDoor();
|
||||
if(door != null) {
|
||||
if (door != null) {
|
||||
destroyDoor.getTownDoor().sendSpawnData(chr.getClient());
|
||||
}
|
||||
}
|
||||
@@ -4180,29 +4199,33 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
|
||||
public void applyPartyDoor(MapleDoor door, boolean partyUpdate) {
|
||||
MapleParty chrParty;
|
||||
prtLock.lock();
|
||||
try {
|
||||
if (!partyUpdate) {
|
||||
pdoor = door;
|
||||
}
|
||||
|
||||
if (party != null) {
|
||||
party.addDoor(id, door);
|
||||
silentPartyUpdateInternal();
|
||||
chrParty = getParty();
|
||||
if (chrParty != null) {
|
||||
chrParty.addDoor(id, door);
|
||||
}
|
||||
} finally {
|
||||
prtLock.unlock();
|
||||
}
|
||||
|
||||
silentPartyUpdateInternal(chrParty);
|
||||
}
|
||||
|
||||
private MapleDoor removePartyDoor(boolean partyUpdate) {
|
||||
MapleDoor ret = null;
|
||||
MapleParty chrParty;
|
||||
|
||||
prtLock.lock();
|
||||
try {
|
||||
if (party != null) {
|
||||
party.removeDoor(id);
|
||||
silentPartyUpdateInternal();
|
||||
chrParty = getParty();
|
||||
if (chrParty != null) {
|
||||
chrParty.removeDoor(id);
|
||||
}
|
||||
|
||||
if (!partyUpdate) {
|
||||
@@ -4213,6 +4236,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
prtLock.unlock();
|
||||
}
|
||||
|
||||
silentPartyUpdateInternal(chrParty);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -5796,18 +5820,16 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
if (level == maxClassLevel) {
|
||||
if (!this.isGM()) {
|
||||
if (ServerConstants.PLAYERNPC_AUTODEPLOY) {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MaplePlayerNPC.spawnPlayerNPC(GameConstants.getHallOfFameMapid(job), MapleCharacter.this);
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
}
|
||||
|
||||
final String names = (getMedalText() + name);
|
||||
getWorldServer().broadcastPacket(MaplePacketCreator.serverNotice(6, String.format(LEVEL_200, names, names)));
|
||||
getWorldServer().broadcastPacket(MaplePacketCreator.serverNotice(6, String.format(LEVEL_200, names, maxClassLevel, names)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5874,22 +5896,27 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
Runnable r = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MapleParty party;
|
||||
boolean partyLeader;
|
||||
|
||||
prtLock.lock();
|
||||
try {
|
||||
if (party != null) {
|
||||
if(isPartyLeader()) party.assignNewLeader(client);
|
||||
PartyOperationHandler.leaveParty(party, mpc, client);
|
||||
|
||||
showHint("You have reached #blevel 10#k, therefore you must leave your #rstarter party#k.");
|
||||
}
|
||||
party = getParty();
|
||||
partyLeader = party != null && isPartyLeader();
|
||||
} finally {
|
||||
prtLock.unlock();
|
||||
}
|
||||
|
||||
if (party != null) {
|
||||
if(partyLeader) party.assignNewLeader(client);
|
||||
PartyOperationHandler.leaveParty(party, mpc, client);
|
||||
|
||||
showHint("You have reached #blevel 10#k, therefore you must leave your #rstarter party#k.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread t = new Thread(r);
|
||||
t.start();
|
||||
ThreadManager.getInstance().newTask(r);
|
||||
}
|
||||
|
||||
levelUpMessages();
|
||||
@@ -7567,8 +7594,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
};
|
||||
|
||||
Thread t = new Thread(r); //spawns a new thread to deal with this
|
||||
t.start();
|
||||
ThreadManager.getInstance().newTask(r); //spawns a new thread to deal with this
|
||||
} else {
|
||||
saveCharToDB(true);
|
||||
}
|
||||
@@ -8439,23 +8465,34 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
|
||||
public int sellAllItemsFromName(byte invTypeId, String name) {
|
||||
//player decides from which inventory items should be sold.
|
||||
|
||||
MapleInventoryType type = MapleInventoryType.getByType(invTypeId);
|
||||
|
||||
Item it = getInventory(type).findByName(name);
|
||||
if(it == null) {
|
||||
return(-1);
|
||||
MapleInventory inv = getInventory(type);
|
||||
inv.lockInventory();
|
||||
try {
|
||||
Item it = inv.findByName(name);
|
||||
if(it == null) {
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(sellAllItemsFromPosition(ii, type, it.getPosition()));
|
||||
} finally {
|
||||
inv.unlockInventory();
|
||||
}
|
||||
|
||||
return(sellAllItemsFromPosition(ii, type, it.getPosition()));
|
||||
}
|
||||
|
||||
public int sellAllItemsFromPosition(MapleItemInformationProvider ii, MapleInventoryType type, short pos) {
|
||||
int mesoGain = 0;
|
||||
|
||||
for(short i = pos; i <= getInventory(type).getSlotLimit(); i++) {
|
||||
if(getInventory(type).getItem(i) == null) continue;
|
||||
mesoGain += standaloneSell(getClient(), ii, type, i, getInventory(type).getItem(i).getQuantity());
|
||||
MapleInventory inv = getInventory(type);
|
||||
inv.lockInventory();
|
||||
try {
|
||||
for(short i = pos; i <= inv.getSlotLimit(); i++) {
|
||||
if(inv.getItem(i) == null) continue;
|
||||
mesoGain += standaloneSell(getClient(), ii, type, i, inv.getItem(i).getQuantity());
|
||||
}
|
||||
} finally {
|
||||
inv.unlockInventory();
|
||||
}
|
||||
|
||||
return(mesoGain);
|
||||
@@ -8465,36 +8502,199 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
if (quantity == 0xFFFF || quantity == 0) {
|
||||
quantity = 1;
|
||||
}
|
||||
Item item = getInventory(type).getItem((short) slot);
|
||||
if (item == null){ //Basic check
|
||||
return(0);
|
||||
}
|
||||
|
||||
int itemid = item.getItemId();
|
||||
if (ItemConstants.isRechargeable(itemid)) {
|
||||
quantity = item.getQuantity();
|
||||
} else if (ItemConstants.isWeddingToken(itemid) || ItemConstants.isWeddingRing(itemid)) {
|
||||
MapleInventory inv = getInventory(type);
|
||||
inv.lockInventory();
|
||||
try {
|
||||
Item item = inv.getItem((short) slot);
|
||||
if (item == null){ //Basic check
|
||||
return(0);
|
||||
}
|
||||
|
||||
int itemid = item.getItemId();
|
||||
if (ItemConstants.isRechargeable(itemid)) {
|
||||
quantity = item.getQuantity();
|
||||
} else if (ItemConstants.isWeddingToken(itemid) || ItemConstants.isWeddingRing(itemid)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (quantity < 0) {
|
||||
return(0);
|
||||
}
|
||||
short iQuant = item.getQuantity();
|
||||
if (iQuant == 0xFFFF) {
|
||||
iQuant = 1;
|
||||
}
|
||||
|
||||
if (quantity <= iQuant && iQuant > 0) {
|
||||
MapleInventoryManipulator.removeFromSlot(c, type, (byte) slot, quantity, false);
|
||||
int recvMesos = ii.getPrice(itemid, quantity);
|
||||
if (recvMesos > 0) {
|
||||
gainMeso(recvMesos, false);
|
||||
return(recvMesos);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
} finally {
|
||||
inv.unlockInventory();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasMergeFlag(Item item) {
|
||||
return (item.getFlag() & ItemConstants.MERGE_UNTRADEABLE) == ItemConstants.MERGE_UNTRADEABLE;
|
||||
}
|
||||
|
||||
private static void setMergeFlag(Item item) {
|
||||
int flag = item.getFlag();
|
||||
flag |= ItemConstants.MERGE_UNTRADEABLE;
|
||||
flag |= ItemConstants.UNTRADEABLE;
|
||||
item.setFlag((byte) flag);
|
||||
}
|
||||
|
||||
private List<Equip> getUpgradeableEquipped() {
|
||||
List<Equip> list = new LinkedList<>();
|
||||
|
||||
if (quantity < 0) {
|
||||
return(0);
|
||||
}
|
||||
short iQuant = item.getQuantity();
|
||||
if (iQuant == 0xFFFF) {
|
||||
iQuant = 1;
|
||||
}
|
||||
|
||||
if (quantity <= iQuant && iQuant > 0) {
|
||||
MapleInventoryManipulator.removeFromSlot(c, type, (byte) slot, quantity, false);
|
||||
int recvMesos = ii.getPrice(itemid, quantity);
|
||||
if (recvMesos > 0) {
|
||||
gainMeso(recvMesos, false);
|
||||
return(recvMesos);
|
||||
for (Item item : getInventory(MapleInventoryType.EQUIPPED)) {
|
||||
if (ii.isUpgradeable(item.getItemId())) {
|
||||
list.add((Equip) item);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<Equip> getEquipsWithStat(List<Pair<Equip, Map<StatUpgrade, Short>>> equipped, StatUpgrade stat) {
|
||||
List<Equip> equippedWithStat = new LinkedList<>();
|
||||
|
||||
for (Pair<Equip, Map<StatUpgrade, Short>> eq : equipped) {
|
||||
if (eq.getRight().containsKey(stat)) {
|
||||
equippedWithStat.add(eq.getLeft());
|
||||
}
|
||||
}
|
||||
|
||||
return equippedWithStat;
|
||||
}
|
||||
|
||||
public boolean mergeAllItemsFromName(String name) {
|
||||
MapleInventoryType type = MapleInventoryType.EQUIP;
|
||||
|
||||
MapleInventory inv = getInventory(type);
|
||||
inv.lockInventory();
|
||||
try {
|
||||
Item it = inv.findByName(name);
|
||||
if(it == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<StatUpgrade, Float> statups = new LinkedHashMap<>();
|
||||
mergeAllItemsFromPosition(statups, it.getPosition());
|
||||
|
||||
List<Pair<Equip, Map<StatUpgrade, Short>>> upgradeableEquipped = new LinkedList<>();
|
||||
Map<Equip, List<Pair<StatUpgrade, Integer>>> equipUpgrades = new LinkedHashMap<>();
|
||||
for (Equip eq : getUpgradeableEquipped()) {
|
||||
upgradeableEquipped.add(new Pair<>(eq, eq.getStats()));
|
||||
equipUpgrades.put(eq, new LinkedList<Pair<StatUpgrade, Integer>>());
|
||||
}
|
||||
|
||||
/*
|
||||
for (Entry<StatUpgrade, Float> e : statups.entrySet()) {
|
||||
System.out.println(e);
|
||||
}
|
||||
*/
|
||||
|
||||
for (Entry<StatUpgrade, Float> e : statups.entrySet()) {
|
||||
Double ev = Math.sqrt(e.getValue());
|
||||
|
||||
Set<Equip> extraEquipped = new LinkedHashSet<>(equipUpgrades.keySet());
|
||||
List<Equip> statEquipped = getEquipsWithStat(upgradeableEquipped, e.getKey());
|
||||
float extraRate = (float)(0.2 * Math.random());
|
||||
|
||||
if (!statEquipped.isEmpty()) {
|
||||
float statRate = 1.0f - extraRate;
|
||||
|
||||
int statup = (int) Math.ceil((ev * statRate) / statEquipped.size());
|
||||
for (Equip statEq : statEquipped) {
|
||||
equipUpgrades.get(statEq).add(new Pair<>(e.getKey(), statup));
|
||||
extraEquipped.remove(statEq);
|
||||
}
|
||||
}
|
||||
|
||||
if (!extraEquipped.isEmpty()) {
|
||||
int statup = (int) Math.round((ev * extraRate) / extraEquipped.size());
|
||||
if (statup > 0) {
|
||||
for (Equip extraEq : extraEquipped) {
|
||||
equipUpgrades.get(extraEq).add(new Pair<>(e.getKey(), statup));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dropMessage(6, "EQUIPMENT MERGE operation results:");
|
||||
for (Entry<Equip, List<Pair<StatUpgrade, Integer>>> eqpUpg : equipUpgrades.entrySet()) {
|
||||
List<Pair<StatUpgrade, Integer>> eqpStatups = eqpUpg.getValue();
|
||||
if (!eqpStatups.isEmpty()) {
|
||||
Equip eqp = eqpUpg.getKey();
|
||||
setMergeFlag(eqp);
|
||||
|
||||
String showStr = " '" + MapleItemInformationProvider.getInstance().getName(eqp.getItemId()) + "': ";
|
||||
String upgdStr = eqp.gainStats(eqpStatups).getLeft();
|
||||
|
||||
this.forceUpdateItem(eqp);
|
||||
|
||||
showStr += upgdStr;
|
||||
dropMessage(6, showStr);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
inv.unlockInventory();
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeAllItemsFromPosition(Map<StatUpgrade, Float> statups, short pos) {
|
||||
MapleInventory inv = getInventory(MapleInventoryType.EQUIP);
|
||||
inv.lockInventory();
|
||||
try {
|
||||
for(short i = pos; i <= inv.getSlotLimit(); i++) {
|
||||
standaloneMerge(statups, getClient(), MapleInventoryType.EQUIP, i, inv.getItem(i));
|
||||
}
|
||||
} finally {
|
||||
inv.unlockInventory();
|
||||
}
|
||||
}
|
||||
|
||||
private void standaloneMerge(Map<StatUpgrade, Float> statups, MapleClient c, MapleInventoryType type, short slot, Item item) {
|
||||
short quantity;
|
||||
if (item == null || (quantity = item.getQuantity()) < 1 || ii.isCash(item.getItemId()) || !ii.isUpgradeable(item.getItemId()) || hasMergeFlag(item)){
|
||||
return;
|
||||
}
|
||||
|
||||
Equip e = (Equip) item;
|
||||
for (Entry<StatUpgrade, Short> s : e.getStats().entrySet()) {
|
||||
Float newVal = statups.get(s.getKey());
|
||||
|
||||
float incVal = s.getValue().floatValue();
|
||||
switch (s.getKey()) {
|
||||
case incPAD:
|
||||
case incMAD:
|
||||
case incPDD:
|
||||
case incMDD:
|
||||
incVal = (float) Math.log(incVal);
|
||||
break;
|
||||
}
|
||||
|
||||
if (newVal != null) {
|
||||
newVal += incVal;
|
||||
} else {
|
||||
newVal = incVal;
|
||||
}
|
||||
|
||||
statups.put(s.getKey(), newVal);
|
||||
}
|
||||
|
||||
MapleInventoryManipulator.removeFromSlot(c, type, (byte) slot, quantity, false);
|
||||
}
|
||||
|
||||
public void setShop(MapleShop shop) {
|
||||
@@ -8599,17 +8799,12 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
|
||||
public void silentPartyUpdate() {
|
||||
prtLock.lock();
|
||||
try {
|
||||
silentPartyUpdateInternal();
|
||||
} finally {
|
||||
prtLock.unlock();
|
||||
}
|
||||
silentPartyUpdateInternal(getParty());
|
||||
}
|
||||
|
||||
private void silentPartyUpdateInternal() {
|
||||
if (party != null) {
|
||||
getWorldServer().updateParty(party.getId(), PartyOperation.SILENT_UPDATE, getMPC());
|
||||
private void silentPartyUpdateInternal(MapleParty chrParty) {
|
||||
if (chrParty != null) {
|
||||
getWorldServer().updateParty(chrParty.getId(), PartyOperation.SILENT_UPDATE, getMPC());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8662,7 +8857,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
}
|
||||
}
|
||||
|
||||
public void runTirednessSchedule() {
|
||||
public boolean runTirednessSchedule() {
|
||||
if(maplemount != null) {
|
||||
int tiredness = maplemount.incrementAndGetTiredness();
|
||||
|
||||
@@ -8671,8 +8866,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
maplemount.setTiredness(99);
|
||||
this.dispelSkill(this.getJobType() * 10000000 + 1004);
|
||||
this.dropMessage(6, "Your mount grew tired! Treat it some revitalizer before riding it again!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void startMapEffect(String msg, int itemId) {
|
||||
@@ -8956,7 +9154,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
|
||||
if (!this.isHidden() || client.getPlayer().gmLevel() > 1) {
|
||||
client.announce(MaplePacketCreator.spawnPlayerMapObject(client, this, false));
|
||||
|
||||
if(hasBuffFromSourceid(getJobMapChair(job))) {
|
||||
if (buffEffects.containsKey(getJobMapChair(job))) { // mustn't effLock, chrLock this function
|
||||
client.announce(MaplePacketCreator.giveForeignChairSkillEffect(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ import scripting.quest.QuestActionManager;
|
||||
import scripting.quest.QuestScriptManager;
|
||||
import server.life.MapleMonster;
|
||||
import server.MapleTrade;
|
||||
import server.ThreadManager;
|
||||
import server.maps.*;
|
||||
import server.quest.MapleQuest;
|
||||
|
||||
@@ -159,7 +160,7 @@ public class MapleClient {
|
||||
}
|
||||
|
||||
public void sendCharList(int server) {
|
||||
this.announce(MaplePacketCreator.getCharList(this, server));
|
||||
this.announce(MaplePacketCreator.getCharList(this, server, 0));
|
||||
}
|
||||
|
||||
public List<MapleCharacter> loadCharacters(int serverId) {
|
||||
@@ -878,11 +879,33 @@ public class MapleClient {
|
||||
}
|
||||
}
|
||||
|
||||
public final synchronized void disconnect(boolean shutdown, boolean cashshop) {//once per MapleClient instance
|
||||
public final void disconnect(final boolean shutdown, final boolean cashshop) {
|
||||
if (isDisconnecting()) {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
disconnectInternal(shutdown, cashshop);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public final void forceDisconnect() {
|
||||
if (isDisconnecting()) {
|
||||
disconnectInternal(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized boolean isDisconnecting() {
|
||||
if (disconnecting) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
disconnecting = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void disconnectInternal(boolean shutdown, boolean cashshop) {//once per MapleClient instance
|
||||
if (player != null && player.isLoggedin() && player.getClient() != null) {
|
||||
final int messengerid = player.getMessenger() == null ? 0 : player.getMessenger().getId();
|
||||
//final int fid = player.getFamilyId();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package client.autoban;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import constants.ServerConstants;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import net.server.Server;
|
||||
@@ -109,11 +110,15 @@ public class AutobanManager {
|
||||
if (this.timestamp[type] == time) {
|
||||
this.timestampcounter[type]++;
|
||||
if (this.timestampcounter[type] >= times) {
|
||||
chr.getClient().disconnect(false, false);
|
||||
if (ServerConstants.USE_AUTOBAN) {
|
||||
chr.getClient().disconnect(false, false);
|
||||
}
|
||||
|
||||
FilePrinter.print(FilePrinter.EXPLOITS, "Player " + chr + " was caught spamming TYPE " + type + " and has been disconnected.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.timestamp[type] = time;
|
||||
this.timestampcounter[type] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class TimeCommand extends Command {
|
||||
@Override
|
||||
public void execute(MapleClient client, String[] params) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
client.getPlayer().yellowMessage("HeavenMS Server Time: " + dateFormat.format(new Date()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,9 @@ public class SummonCommand extends Command {
|
||||
}
|
||||
|
||||
MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(params[0]);
|
||||
if (victim == null) {//If victim isn't on current channel, loop all channels on current world.
|
||||
if (victim == null) {
|
||||
//If victim isn't on current channel, loop all channels on current world.
|
||||
|
||||
for (Channel ch : Server.getInstance().getChannelsFromWorld(c.getWorld())) {
|
||||
victim = ch.getPlayerStorage().getCharacterByName(params[0]);
|
||||
if (victim != null) {
|
||||
@@ -61,9 +63,10 @@ public class SummonCommand extends Command {
|
||||
victim.getEventInstance().unregisterPlayer(victim);
|
||||
}
|
||||
}
|
||||
|
||||
//Attempt to join the warpers instance.
|
||||
if (player.getEventInstance() != null && changingEvent) {
|
||||
if (player.getClient().getChannel() == victim.getClient().getChannel()) {//just in case.. you never know...
|
||||
if (player.getClient().getChannel() == victim.getClient().getChannel()) {
|
||||
player.getEventInstance().registerPlayer(victim);
|
||||
victim.changeMap(player.getEventInstance().getMapInstance(player.getMapId()), player.getMap().findClosestPortal(player.getPosition()));
|
||||
} else {
|
||||
|
||||
@@ -71,7 +71,8 @@ public class DebugCommand extends Command {
|
||||
List<MapleMapObject> monsters = player.getMap().getMapObjectsInRange(player.getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.MONSTER));
|
||||
for (MapleMapObject monstermo : monsters) {
|
||||
MapleMonster monster = (MapleMonster) monstermo;
|
||||
player.message("Monster ID: " + monster.getId() + " Aggro target: " + ((monster.getController() != null) ? monster.getController().getName() : "<none>"));
|
||||
MapleCharacter controller = monster.getController();
|
||||
player.message("Monster ID: " + monster.getId() + " Aggro target: " + ((controller != null) ? controller.getName() : "<none>"));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import client.MapleCharacter;
|
||||
import client.command.Command;
|
||||
import client.MapleClient;
|
||||
import net.server.Server;
|
||||
import server.ThreadManager;
|
||||
|
||||
public class ServerAddChannelCommand extends Command {
|
||||
{
|
||||
@@ -44,7 +45,7 @@ public class ServerAddChannelCommand extends Command {
|
||||
|
||||
final int worldid = Integer.parseInt(params[0]);
|
||||
|
||||
new Thread(new Runnable() {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int chid = Server.getInstance().addChannel(worldid);
|
||||
@@ -64,6 +65,6 @@ public class ServerAddChannelCommand extends Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import client.MapleCharacter;
|
||||
import client.command.Command;
|
||||
import client.MapleClient;
|
||||
import net.server.Server;
|
||||
import server.ThreadManager;
|
||||
|
||||
public class ServerAddWorldCommand extends Command {
|
||||
{
|
||||
@@ -37,7 +38,7 @@ public class ServerAddWorldCommand extends Command {
|
||||
public void execute(MapleClient c, String[] params) {
|
||||
final MapleCharacter player = c.getPlayer();
|
||||
|
||||
new Thread(new Runnable() {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int wid = Server.getInstance().addWorld();
|
||||
@@ -54,6 +55,6 @@ public class ServerAddWorldCommand extends Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import client.MapleCharacter;
|
||||
import client.command.Command;
|
||||
import client.MapleClient;
|
||||
import net.server.Server;
|
||||
import server.ThreadManager;
|
||||
|
||||
public class ServerRemoveChannelCommand extends Command {
|
||||
{
|
||||
@@ -43,7 +44,7 @@ public class ServerRemoveChannelCommand extends Command {
|
||||
}
|
||||
|
||||
final int worldId = Integer.parseInt(params[0]);
|
||||
new Thread(new Runnable() {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(Server.getInstance().removeChannel(worldId)) {
|
||||
@@ -56,6 +57,6 @@ public class ServerRemoveChannelCommand extends Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import client.MapleCharacter;
|
||||
import client.command.Command;
|
||||
import client.MapleClient;
|
||||
import net.server.Server;
|
||||
import server.ThreadManager;
|
||||
|
||||
public class ServerRemoveWorldCommand extends Command {
|
||||
{
|
||||
@@ -43,7 +44,7 @@ public class ServerRemoveWorldCommand extends Command {
|
||||
return;
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(Server.getInstance().removeWorld()) {
|
||||
@@ -60,6 +61,6 @@ public class ServerRemoveWorldCommand extends Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,10 @@ package client.inventory;
|
||||
import client.MapleClient;
|
||||
import constants.ServerConstants;
|
||||
import constants.ExpTable;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import server.MapleItemInformationProvider;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Pair;
|
||||
@@ -47,7 +49,7 @@ public class Equip extends Item {
|
||||
}
|
||||
}
|
||||
|
||||
private static enum StatUpgrade {
|
||||
public static enum StatUpgrade {
|
||||
|
||||
incDEX(0), incSTR(1), incINT(2), incLUK(3),
|
||||
incMHP(4), incMMP(5), incPAD(6), incMAD(7),
|
||||
@@ -332,49 +334,30 @@ public class Equip extends Item {
|
||||
if(jump > 0) getUnitStatUpgrade(stats, StatUpgrade.incJump, jump, false);
|
||||
}
|
||||
|
||||
private void gainLevel(MapleClient c) {
|
||||
List<Pair<StatUpgrade, Integer>> stats = new LinkedList<>();
|
||||
|
||||
if(isElemental) {
|
||||
List<Pair<String, Integer>> elementalStats = MapleItemInformationProvider.getInstance().getItemLevelupStats(getItemId(), itemLevel);
|
||||
|
||||
for(Pair<String, Integer> p: elementalStats) {
|
||||
if(p.getRight() > 0) stats.add(new Pair<>(StatUpgrade.valueOf(p.getLeft()), p.getRight()));
|
||||
}
|
||||
}
|
||||
public Map<StatUpgrade, Short> getStats() {
|
||||
Map<StatUpgrade, Short> stats = new HashMap<>(5);
|
||||
|
||||
if(!stats.isEmpty()) {
|
||||
if(ServerConstants.USE_EQUIPMNT_LVLUP_SLOTS) {
|
||||
if(vicious > 0) getUnitSlotUpgrade(stats, StatUpgrade.incVicious);
|
||||
getUnitSlotUpgrade(stats, StatUpgrade.incSlot);
|
||||
}
|
||||
}
|
||||
else {
|
||||
isUpgradeable = false;
|
||||
|
||||
improveDefaultStats(stats);
|
||||
if(ServerConstants.USE_EQUIPMNT_LVLUP_SLOTS) {
|
||||
if(vicious > 0) getUnitSlotUpgrade(stats, StatUpgrade.incVicious);
|
||||
getUnitSlotUpgrade(stats, StatUpgrade.incSlot);
|
||||
}
|
||||
|
||||
if(isUpgradeable) {
|
||||
while(stats.isEmpty()) {
|
||||
improveDefaultStats(stats);
|
||||
if(ServerConstants.USE_EQUIPMNT_LVLUP_SLOTS) {
|
||||
if(vicious > 0) getUnitSlotUpgrade(stats, StatUpgrade.incVicious);
|
||||
getUnitSlotUpgrade(stats, StatUpgrade.incSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemLevel++;
|
||||
boolean gotVicious = false, gotSlot = false;
|
||||
|
||||
String lvupStr = "'" + MapleItemInformationProvider.getInstance().getName(this.getItemId()) + "' is now level " + itemLevel + "! ";
|
||||
String showStr = "#e'" + MapleItemInformationProvider.getInstance().getName(this.getItemId()) + "'#b is now #elevel #r" + itemLevel + "#k#b!";
|
||||
if(dex > 0) stats.put(StatUpgrade.incDEX, dex);
|
||||
if(str > 0) stats.put(StatUpgrade.incSTR, str);
|
||||
if(_int > 0) stats.put(StatUpgrade.incINT,_int);
|
||||
if(luk > 0) stats.put(StatUpgrade.incLUK, luk);
|
||||
if(hp > 0) stats.put(StatUpgrade.incMHP, hp);
|
||||
if(mp > 0) stats.put(StatUpgrade.incMMP, mp);
|
||||
if(watk > 0) stats.put(StatUpgrade.incPAD, watk);
|
||||
if(matk > 0) stats.put(StatUpgrade.incMAD, matk);
|
||||
if(wdef > 0) stats.put(StatUpgrade.incPDD, wdef);
|
||||
if(mdef > 0) stats.put(StatUpgrade.incMDD, mdef);
|
||||
if(avoid > 0) stats.put(StatUpgrade.incEVA, avoid);
|
||||
if(acc > 0) stats.put(StatUpgrade.incACC, acc);
|
||||
if(speed > 0) stats.put(StatUpgrade.incSpeed, speed);
|
||||
if(jump > 0) stats.put(StatUpgrade.incJump, jump);
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
public Pair<String, Pair<Boolean, Boolean>> gainStats(List<Pair<StatUpgrade, Integer>> stats) {
|
||||
boolean gotSlot = false, gotVicious = false;
|
||||
String lvupStr = "";
|
||||
Integer statUp, maxStat = ServerConstants.MAX_EQUIPMNT_STAT;
|
||||
for (Pair<StatUpgrade, Integer> stat : stats) {
|
||||
switch (stat.getLeft()) {
|
||||
@@ -460,6 +443,55 @@ public class Equip extends Item {
|
||||
}
|
||||
}
|
||||
|
||||
return new Pair<>(lvupStr, new Pair<>(gotSlot, gotVicious));
|
||||
}
|
||||
|
||||
private void gainLevel(MapleClient c) {
|
||||
List<Pair<StatUpgrade, Integer>> stats = new LinkedList<>();
|
||||
|
||||
if(isElemental) {
|
||||
List<Pair<String, Integer>> elementalStats = MapleItemInformationProvider.getInstance().getItemLevelupStats(getItemId(), itemLevel);
|
||||
|
||||
for(Pair<String, Integer> p: elementalStats) {
|
||||
if(p.getRight() > 0) stats.add(new Pair<>(StatUpgrade.valueOf(p.getLeft()), p.getRight()));
|
||||
}
|
||||
}
|
||||
|
||||
if(!stats.isEmpty()) {
|
||||
if(ServerConstants.USE_EQUIPMNT_LVLUP_SLOTS) {
|
||||
if(vicious > 0) getUnitSlotUpgrade(stats, StatUpgrade.incVicious);
|
||||
getUnitSlotUpgrade(stats, StatUpgrade.incSlot);
|
||||
}
|
||||
} else {
|
||||
isUpgradeable = false;
|
||||
|
||||
improveDefaultStats(stats);
|
||||
if(ServerConstants.USE_EQUIPMNT_LVLUP_SLOTS) {
|
||||
if(vicious > 0) getUnitSlotUpgrade(stats, StatUpgrade.incVicious);
|
||||
getUnitSlotUpgrade(stats, StatUpgrade.incSlot);
|
||||
}
|
||||
|
||||
if(isUpgradeable) {
|
||||
while(stats.isEmpty()) {
|
||||
improveDefaultStats(stats);
|
||||
if(ServerConstants.USE_EQUIPMNT_LVLUP_SLOTS) {
|
||||
if(vicious > 0) getUnitSlotUpgrade(stats, StatUpgrade.incVicious);
|
||||
getUnitSlotUpgrade(stats, StatUpgrade.incSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemLevel++;
|
||||
|
||||
String lvupStr = "'" + MapleItemInformationProvider.getInstance().getName(this.getItemId()) + "' is now level " + itemLevel + "! ";
|
||||
String showStr = "#e'" + MapleItemInformationProvider.getInstance().getName(this.getItemId()) + "'#b is now #elevel #r" + itemLevel + "#k#b!";
|
||||
|
||||
Pair<String, Pair<Boolean, Boolean>> res = gainStats(stats);
|
||||
lvupStr += res.getLeft();
|
||||
boolean gotSlot = res.getRight().getLeft();
|
||||
boolean gotVicious = res.getRight().getRight();
|
||||
|
||||
if(gotVicious) {
|
||||
//c.getPlayer().dropMessage(6, "A new Vicious Hammer opportunity has been found on the '" + MapleItemInformationProvider.getInstance().getName(getItemId()) + "'!");
|
||||
lvupStr += "+VICIOUS ";
|
||||
|
||||
@@ -73,6 +73,7 @@ public class Item implements Comparable<Item> {
|
||||
|
||||
public void setPosition(short position) {
|
||||
this.position = position;
|
||||
if (this.pet != null) this.pet.setPosition(position);
|
||||
}
|
||||
|
||||
public void setQuantity(short quantity) {
|
||||
|
||||
@@ -215,7 +215,7 @@ public class MaplePet extends Item {
|
||||
enjoyed = false;
|
||||
}
|
||||
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.commandResponse(owner.getId(), slot, type, enjoyed));
|
||||
owner.getMap().broadcastMessage(MaplePacketCreator.petFoodResponse(owner.getId(), slot, enjoyed, false));
|
||||
saveToDb();
|
||||
|
||||
Item petz = owner.getInventory(MapleInventoryType.CASH).getItem(getPosition());
|
||||
|
||||
@@ -188,6 +188,7 @@ public class MapleInventoryManipulator {
|
||||
short newQ = (short) Math.min(oldQ + quantity, slotMax);
|
||||
quantity -= (newQ - oldQ);
|
||||
eItem.setQuantity(newQ);
|
||||
item.setPosition(eItem.getPosition());
|
||||
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(1, eItem))));
|
||||
}
|
||||
} else {
|
||||
@@ -209,6 +210,8 @@ public class MapleInventoryManipulator {
|
||||
item.setQuantity((short) (quantity + newQ));
|
||||
return false;
|
||||
}
|
||||
nItem.setPosition(newSlot);
|
||||
item.setPosition(newSlot);
|
||||
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
|
||||
if(MapleInventoryManipulator.isSandboxItem(nItem)) chr.setHasSandboxItem();
|
||||
}
|
||||
@@ -223,6 +226,8 @@ public class MapleInventoryManipulator {
|
||||
c.announce(MaplePacketCreator.getShowInventoryFull());
|
||||
return false;
|
||||
}
|
||||
nItem.setPosition(newSlot);
|
||||
item.setPosition(newSlot);
|
||||
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, nItem))));
|
||||
if(MapleInventoryManipulator.isSandboxItem(nItem)) chr.setHasSandboxItem();
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
@@ -234,6 +239,7 @@ public class MapleInventoryManipulator {
|
||||
c.announce(MaplePacketCreator.getShowInventoryFull());
|
||||
return false;
|
||||
}
|
||||
item.setPosition(newSlot);
|
||||
c.announce(MaplePacketCreator.modifyInventory(true, Collections.singletonList(new ModifyInventory(0, item))));
|
||||
if(MapleInventoryManipulator.isSandboxItem(item)) chr.setHasSandboxItem();
|
||||
} else {
|
||||
|
||||
@@ -43,6 +43,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import server.ThreadManager;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.Randomizer;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
@@ -333,13 +334,12 @@ public class AssignAPProcessor {
|
||||
AutobanFactory.PACKET_EDIT.alert(chr, "Didn't send full packet for Auto Assign.");
|
||||
|
||||
final MapleClient client = c;
|
||||
Thread t = new Thread(new Runnable() {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
client.disconnect(false, false);
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import client.SkillFactory;
|
||||
import client.autoban.AutobanFactory;
|
||||
import constants.GameConstants;
|
||||
import constants.skills.Aran;
|
||||
import server.ThreadManager;
|
||||
import tools.FilePrinter;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
@@ -55,13 +56,12 @@ public class AssignSPProcessor {
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use skill " + skillid + " without it being in their job.\r\n");
|
||||
|
||||
final MapleClient client = c;
|
||||
Thread t = new Thread(new Runnable() {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
client.disconnect(true, false);
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
package client.processor;
|
||||
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import client.inventory.Equip;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventoryType;
|
||||
@@ -199,7 +200,7 @@ public class MakerProcessor {
|
||||
c.announce(MaplePacketCreator.showMakerEffect(makerSucceeded));
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignMakerEffect(c.getPlayer().getId(), makerSucceeded), false);
|
||||
|
||||
if(toCreate == 4260003 && c.getPlayer().getQuestStatus(6033) == 1) {
|
||||
if(toCreate == 4260003 && type == 3 && c.getPlayer().getQuestStatus(6033) == 1) {
|
||||
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
|
||||
}
|
||||
} else {
|
||||
@@ -282,6 +283,10 @@ public class MakerProcessor {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int getMakerSkillLevel(MapleCharacter chr) {
|
||||
return chr.getSkillLevel((chr.getJob().getId() / 1000) * 10000000 + 1007);
|
||||
}
|
||||
|
||||
private static short getCreateStatus(MapleClient c, MakerItemFactory.MakerItemCreateEntry recipe) {
|
||||
if(recipe == null) {
|
||||
return -1;
|
||||
@@ -299,7 +304,7 @@ public class MakerProcessor {
|
||||
return 3;
|
||||
}
|
||||
|
||||
if(c.getPlayer().getSkillLevel((c.getPlayer().getJob().getId() / 1000) * 10000000 + 1007) < recipe.getReqSkillLevel()) {
|
||||
if(getMakerSkillLevel(c.getPlayer()) < recipe.getReqSkillLevel()) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ public final class ItemConstants {
|
||||
public final static int SANDBOX = 0x40; // let 0x40 until it's proven something uses this
|
||||
public final static int PET_COME = 0x80;
|
||||
public final static int ACCOUNT_SHARING = 0x100;
|
||||
public final static int MERGE_UNTRADEABLE = 0x200;
|
||||
|
||||
public final static boolean EXPIRING_ITEMS = true;
|
||||
public final static Set<Integer> permanentItemids = new HashSet<>();
|
||||
|
||||
@@ -82,7 +82,7 @@ public class ServerConstants {
|
||||
public static final boolean USE_ENFORCE_HPMP_SWAP = false; //Forces players to reuse stats (via AP Resetting) located on HP/MP pool only inside the HP/MP stats.
|
||||
public static final boolean USE_ENFORCE_MOB_LEVEL_RANGE = true; //Players N levels below the killed mob will gain no experience from defeating it.
|
||||
public static final boolean USE_ENFORCE_JOB_LEVEL_RANGE = false;//Caps the player level on the minimum required to advance their current jobs.
|
||||
public static final boolean USE_ENFORCE_JOB_SP_RANGE = true; //Caps the player SP level on the total obtainable by their current jobs. After changing jobs, missing SP will be retrieved.
|
||||
public static final boolean USE_ENFORCE_JOB_SP_RANGE = false; //Caps the player SP level on the total obtainable by their current jobs. After changing jobs, missing SP will be retrieved.
|
||||
public static final boolean USE_ENFORCE_ITEM_SUGGESTION = false;//Forces the Owl of Minerva and the Cash Shop to always display the defined item array instead of those featured by the players.
|
||||
public static final boolean USE_ENFORCE_UNMERCHABLE_CASH = true;//Forces players to not sell CASH items via merchants.
|
||||
public static final boolean USE_ENFORCE_UNMERCHABLE_PET = true; //Forces players to not sell pets via merchants. (since non-named pets gets dirty name and other possible DB-related issues)
|
||||
@@ -115,6 +115,10 @@ public class ServerConstants {
|
||||
public static final boolean USE_MAKER_PERMISSIVE_ATKUP = true; //Allows players to use attack-based strengthening gems on non-weapon items.
|
||||
public static final boolean USE_MAKER_FEE_HEURISTICS = true; //Apply compiled values for stimulants and reagents into the Maker fee calculations (max error revolves around 50k mesos). Set false to use basic constant values instead (results are never higher than requested by the client-side).
|
||||
|
||||
//Custom Configuration
|
||||
public static final boolean USE_ENABLE_CUSTOM_NPC_SCRIPT = true;//Enables usage of custom HeavenMS NPC scripts (Agent E, Coco, etc). Will not disable Abdula (it's actually useful for the gameplay), quests or NPC shops.
|
||||
public static final boolean USE_STARTER_MERGE = false; //Allows any players to use the Equipment Merge custom mechanic (as opposed to the high-level, Maker lv3 requisites).
|
||||
|
||||
//Commands Configuration
|
||||
public static final boolean BLOCK_GENERATE_CASH_ITEM = false; //Prevents creation of cash items with the item/drop command.
|
||||
public static final boolean USE_WHOLE_SERVER_RANKING = false; //Enables a ranking pool made from every character registered on the server for the "ranks" command, instead of separated by worlds.
|
||||
@@ -133,7 +137,7 @@ public class ServerConstants {
|
||||
public static final int PARTY_EXPERIENCE_MOD = 1; //Change for event stuff.
|
||||
|
||||
//Miscellaneous Configuration
|
||||
public static String TIMEZONE = "-GMT3";
|
||||
public static String TIMEZONE = "GMT-3";
|
||||
public static boolean USE_DISPLAY_NUMBERS_WITH_COMMA = true; //Enforce comma on displayed strings (use this when USE_UNITPRICE_WITH_COMMA is active and you still want to display comma-separated values).
|
||||
public static boolean USE_UNITPRICE_WITH_COMMA = true; //Set this accordingly with the layout of the unitPrices on Item.wz XML's, whether it's using commas or dots to represent fractions.
|
||||
public static final byte MIN_UNDERLEVEL_TO_EXP_GAIN = 20; //Characters are unable to get EXP from a mob if their level are under this threshold, only if "USE_ENFORCE_MOB_LEVEL_RANGE" is enabled. For bosses, this attribute is doubled.
|
||||
@@ -178,6 +182,7 @@ public class ServerConstants {
|
||||
public static final boolean USE_ULTRA_THREE_SNAILS = true; //Massive damage on shell toss.
|
||||
|
||||
//Other Skills Configuration
|
||||
public static final boolean USE_FULL_ARAN_SKILLSET = false; //Enables starter availability to all Aran job skills. Suggestion thanks to Masterrulax.
|
||||
public static final boolean USE_FAST_REUSE_HERO_WILL = true;//Greatly reduce cooldown on Hero's Will.
|
||||
public static final boolean USE_ANTI_IMMUNITY_CRASH = true; //Crash skills additionally removes the mob's invincibility buffs. Suggestion thanks to Celestial.
|
||||
public static final boolean USE_UNDISPEL_HOLY_SHIELD = true;//Holy shield buff also prevents players from suffering dispel from mobs.
|
||||
@@ -245,6 +250,7 @@ public class ServerConstants {
|
||||
public static final long EVENT_LOBBY_DELAY = 10; //Cooldown duration in seconds before reopening an event lobby.
|
||||
|
||||
//Dojo Configuration
|
||||
public static final boolean USE_FAST_DOJO_UPGRADE = true; //Reduced Dojo training points amount required for a belt upgrade.
|
||||
public static final boolean USE_DEADLY_DOJO = false; //Should bosses really use 1HP,1MP attacks in dojo?
|
||||
public static final int DOJO_ENERGY_ATK = 100; //Dojo energy gain when deal attack
|
||||
public static final int DOJO_ENERGY_DMG = 20; //Dojo energy gain when recv attack
|
||||
|
||||
@@ -33,6 +33,7 @@ public class WindArcher {
|
||||
public static final int BOW_BOOSTER = 13101001;
|
||||
public static final int FINAL_ATTACK = 13101002;
|
||||
public static final int SOUL_ARROW = 13101003;
|
||||
public static final int STORM_BREAK = 13101005;
|
||||
public static final int WIND_WALK = 13101006;
|
||||
public static final int HURRICANE = 13111002;
|
||||
public static final int PUPPET = 13111004;
|
||||
|
||||
@@ -136,6 +136,7 @@ public final class PacketProcessor {
|
||||
registerHandler(RecvOpcode.NPC_TALK, new NPCTalkHandler());
|
||||
registerHandler(RecvOpcode.NPC_TALK_MORE, new NPCMoreTalkHandler());
|
||||
registerHandler(RecvOpcode.QUEST_ACTION, new QuestActionHandler());
|
||||
registerHandler(RecvOpcode.GRENADE_EFFECT, new GrenadeEffectHandler());
|
||||
registerHandler(RecvOpcode.NPC_SHOP, new NPCShopHandler());
|
||||
registerHandler(RecvOpcode.ITEM_SORT, new InventoryMergeHandler());
|
||||
registerHandler(RecvOpcode.ITEM_MOVE, new ItemMoveHandler());
|
||||
|
||||
@@ -114,7 +114,8 @@ public enum RecvOpcode {
|
||||
TROCK_ADD_MAP(0x66),
|
||||
REPORT(0x6A),
|
||||
QUEST_ACTION(0x6B),
|
||||
//lolno
|
||||
//USER_CALC_DAMAGE_STAT_SET_REQUEST(0x6C),
|
||||
GRENADE_EFFECT(0x6D),
|
||||
SKILL_MACRO(0x6E),
|
||||
USE_ITEM_REWARD(0x70),
|
||||
MAKER_SKILL(0x71),
|
||||
|
||||
@@ -228,6 +228,7 @@ public enum SendOpcode {
|
||||
GIVE_FOREIGN_BUFF(0xC7),
|
||||
CANCEL_FOREIGN_BUFF(0xC8),
|
||||
UPDATE_PARTYMEMBER_HP(0xC9),
|
||||
THROW_GRENADE(0xCC),
|
||||
CANCEL_CHAIR(0xCD),
|
||||
SHOW_ITEM_GAIN_INCHAT(0xCE),
|
||||
DOJO_WARP_UP(0xCF),
|
||||
|
||||
@@ -102,7 +102,7 @@ public class PlayerStorage {
|
||||
for(MapleCharacter mc : chrList) {
|
||||
MapleClient client = mc.getClient();
|
||||
if(client != null) {
|
||||
client.disconnect(true, false);
|
||||
client.forceDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,10 @@ import client.newyear.NewYearCardRecord;
|
||||
import constants.ItemConstants;
|
||||
import constants.GameConstants;
|
||||
import constants.ServerConstants;
|
||||
import java.util.TimeZone;
|
||||
import server.CashShop.CashItemFactory;
|
||||
import server.MapleSkillbookInformationProvider;
|
||||
import server.ThreadManager;
|
||||
import server.TimerManager;
|
||||
import server.life.MaplePlayerNPCFactory;
|
||||
import server.quest.MapleQuest;
|
||||
@@ -147,6 +149,10 @@ public class Server {
|
||||
private boolean online = false;
|
||||
public static long uptime = System.currentTimeMillis();
|
||||
|
||||
public int getCurrentTimestamp() {
|
||||
return (int) (Server.getInstance().getCurrentTime() - Server.uptime);
|
||||
}
|
||||
|
||||
public long getCurrentTime() { // returns a slightly delayed time value, under frequency of UPDATE_INTERVAL
|
||||
return serverCurrentTime;
|
||||
}
|
||||
@@ -825,6 +831,33 @@ public class Server {
|
||||
return rankSystem;
|
||||
}
|
||||
|
||||
private static void clearUnreferencedPetIds() {
|
||||
PreparedStatement ps = null;
|
||||
Connection con = null;
|
||||
try {
|
||||
con = DatabaseConnection.getConnection();
|
||||
|
||||
ps = con.prepareStatement("UPDATE inventoryitems SET petid = -1, expiration = 0 WHERE petid != -1 AND petid NOT IN (SELECT petid FROM pets)");
|
||||
ps.executeUpdate();
|
||||
|
||||
ps.close();
|
||||
con.close();
|
||||
} catch(SQLException ex) {
|
||||
ex.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if(ps != null && !ps.isClosed()) {
|
||||
ps.close();
|
||||
}
|
||||
if(con != null && !con.isClosed()) {
|
||||
con.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
Properties p = loadWorldINI();
|
||||
if(p == null) {
|
||||
@@ -832,11 +865,12 @@ public class Server {
|
||||
}
|
||||
|
||||
System.out.println("HeavenMS v" + ServerConstants.VERSION + " starting up.\r\n");
|
||||
|
||||
|
||||
if(ServerConstants.SHUTDOWNHOOK)
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(shutdown(false)));
|
||||
|
||||
TimeZone.setDefault(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
|
||||
Connection c = null;
|
||||
try {
|
||||
c = DatabaseConnection.getConnection();
|
||||
@@ -856,6 +890,7 @@ public class Server {
|
||||
sqle.printStackTrace();
|
||||
}
|
||||
|
||||
clearUnreferencedPetIds();
|
||||
MapleCashidGenerator.loadExistentCashIdsFromDb();
|
||||
|
||||
IoBuffer.setUseDirectBuffer(false);
|
||||
@@ -863,6 +898,7 @@ public class Server {
|
||||
acceptor = new NioSocketAcceptor();
|
||||
acceptor.getFilterChain().addLast("codec", (IoFilter) new ProtocolCodecFilter(new MapleCodecFactory()));
|
||||
|
||||
ThreadManager.getInstance().start();
|
||||
TimerManager tMan = TimerManager.getInstance();
|
||||
tMan.start();
|
||||
tMan.register(tMan.purge(), ServerConstants.PURGING_INTERVAL);//Purging ftw...
|
||||
@@ -1716,6 +1752,7 @@ public class Server {
|
||||
|
||||
resetServerWorlds();
|
||||
|
||||
ThreadManager.getInstance().stop();
|
||||
TimerManager.getInstance().purge();
|
||||
TimerManager.getInstance().stop();
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ public class ThreadTracker {
|
||||
StackTraceElement[] ste = threads.get(l).getStackTrace();
|
||||
if(ste.length > 0) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
String df = dateFormat.format(new Date());
|
||||
|
||||
FilePrinter.print(FilePrinter.DEADLOCK_LOCKS, printThreadLog(tt, df));
|
||||
@@ -195,7 +195,7 @@ public class ThreadTracker {
|
||||
}
|
||||
} else { // print status
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
FilePrinter.printError(FilePrinter.DEADLOCK_STATE, printThreadTrackerState(dateFormat.format(new Date())));
|
||||
//FilePrinter.printError(FilePrinter.DEADLOCK_STATE, "[" + dateFormat.format(new Date()) + "] Presenting current lock path for lockid " + lockId.name() + ".\r\n" + printLockStatus(lockId) + "\r\n-------------------------------\r\n");
|
||||
|
||||
@@ -62,7 +62,7 @@ public class TrackerReadLock extends ReentrantReadWriteLock.ReadLock implements
|
||||
if(ServerConstants.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
//FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "[CRITICAL] " + dateFormat.format(new Date()) + " Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState) + "\r\n\r\n");
|
||||
ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode);
|
||||
|
||||
@@ -64,7 +64,7 @@ public class TrackerReentrantLock extends ReentrantLock implements MonitoredReen
|
||||
if(ServerConstants.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
//FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "[CRITICAL] " + dateFormat.format(new Date()) + " Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState) + "\r\n\r\n");
|
||||
ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode);
|
||||
|
||||
@@ -60,7 +60,7 @@ public class TrackerWriteLock extends ReentrantReadWriteLock.WriteLock implement
|
||||
if(ServerConstants.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
//FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "[CRITICAL] " + dateFormat.format(new Date()) + " Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState) + "\r\n\r\n");
|
||||
ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode);
|
||||
|
||||
@@ -41,7 +41,7 @@ public class EmptyReadLock implements MonitoredReadLock {
|
||||
|
||||
private static String printThreadStack(StackTraceElement[] list) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
String df = dateFormat.format(new Date());
|
||||
|
||||
String s = "\r\n" + df + "\r\n";
|
||||
|
||||
@@ -41,7 +41,7 @@ public class EmptyReentrantLock implements MonitoredReentrantLock {
|
||||
|
||||
private static String printThreadStack(StackTraceElement[] list) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
String df = dateFormat.format(new Date());
|
||||
|
||||
String s = "\r\n" + df + "\r\n";
|
||||
|
||||
@@ -41,7 +41,7 @@ public class EmptyWriteLock implements MonitoredWriteLock {
|
||||
|
||||
private static String printThreadStack(StackTraceElement[] list) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone(ServerConstants.TIMEZONE));
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
String df = dateFormat.format(new Date());
|
||||
|
||||
String s = "\r\n" + df + "\r\n";
|
||||
|
||||
@@ -259,8 +259,9 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
|
||||
else if(attack.skill == Shadower.BOOMERANG_STEP)
|
||||
distanceToDetect += 60000;
|
||||
|
||||
if(distance > distanceToDetect) {
|
||||
if (distance > distanceToDetect) {
|
||||
AutobanFactory.DISTANCE_HACK.alert(player, "Distance Sq to monster: " + distance + " SID: " + attack.skill + " MID: " + monster.getId());
|
||||
monster.refreshMobPosition();
|
||||
}
|
||||
|
||||
int totDamageToOneMonster = 0;
|
||||
@@ -338,7 +339,7 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
|
||||
}
|
||||
}
|
||||
|
||||
if (job == 2111 || job == 2112) {
|
||||
if (player.isAran()) {
|
||||
if (player.getBuffedValue(MapleBuffStat.WK_CHARGE) != null) {
|
||||
Skill snowCharge = SkillFactory.getSkill(Aran.SNOW_CHARGE);
|
||||
if (totDamageToOneMonster > 0) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.AbstractMaplePacketHandler;
|
||||
import server.life.MapleMonster;
|
||||
import server.maps.MapleMap;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import client.MapleCharacter;
|
||||
|
||||
public final class AutoAggroHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@@ -38,18 +39,26 @@ public final class AutoAggroHandler extends AbstractMaplePacketHandler {
|
||||
int oid = slea.readInt();
|
||||
|
||||
MapleMonster monster = map.getMonsterByOid(oid);
|
||||
if (monster != null && monster.getController() != null) {
|
||||
if (!monster.isControllerHasAggro()) {
|
||||
if (map.getCharacterById(monster.getController().getId()) == null) {
|
||||
monster.switchController(c.getPlayer(), true);
|
||||
if (monster != null) {
|
||||
MapleCharacter currentController = monster.getController();
|
||||
monster.lockMonster();
|
||||
try {
|
||||
if (currentController != null) {
|
||||
if (!monster.isControllerHasAggro()) {
|
||||
if (map.getCharacterById(currentController.getId()) == null) {
|
||||
monster.switchController(c.getPlayer(), true);
|
||||
} else {
|
||||
monster.switchController(currentController, true);
|
||||
}
|
||||
} else if (map.getCharacterById(currentController.getId()) == null) {
|
||||
monster.switchController(c.getPlayer(), true);
|
||||
}
|
||||
} else {
|
||||
monster.switchController(monster.getController(), true);
|
||||
monster.switchController(c.getPlayer(), true);
|
||||
}
|
||||
} else if (map.getCharacterById(monster.getController().getId()) == null) {
|
||||
monster.switchController(c.getPlayer(), true);
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
} else if (monster != null && monster.getController() == null) {
|
||||
monster.switchController(c.getPlayer(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import net.AbstractMaplePacketHandler;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import client.MapleClient;
|
||||
import client.autoban.AutobanFactory;
|
||||
import net.server.Server;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -35,7 +36,8 @@ public final class ChangeChannelHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
int channel = slea.readByte() + 1;
|
||||
c.getPlayer().getAutobanManager().setTimestamp(6, slea.readInt(), 2);
|
||||
slea.readInt();
|
||||
c.getPlayer().getAutobanManager().setTimestamp(6, Server.getInstance().getCurrentTimestamp(), 3);
|
||||
if(c.getChannel() == channel) {
|
||||
AutobanFactory.GENERAL.alert(c.getPlayer(), "CCing to same channel.");
|
||||
c.disconnect(false, false);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 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.handlers;
|
||||
|
||||
import client.MapleClient;
|
||||
import client.MapleCharacter;
|
||||
import constants.skills.Gunslinger;
|
||||
import constants.skills.NightWalker;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import java.awt.Point;
|
||||
import tools.FilePrinter;
|
||||
|
||||
/*
|
||||
* @author GabrielSin
|
||||
*/
|
||||
public class GrenadeEffectHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
Point position = new Point(slea.readInt(), slea.readInt());
|
||||
int keyDown = slea.readInt();
|
||||
int skillId = slea.readInt();
|
||||
|
||||
switch (skillId) {
|
||||
case NightWalker.POISON_BOMB:
|
||||
case Gunslinger.GRENADE:
|
||||
int skillLevel = chr.getSkillLevel(skillId);
|
||||
if (skillLevel > 0) {
|
||||
chr.getMap().broadcastMessage(chr, MaplePacketCreator.throwGrenade(chr.getId(), position, keyDown, skillId, skillLevel), position);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FilePrinter.printError(FilePrinter.UNHANDLED_EVENT, "The skill id: " + skillId + " is not coded in " + this.getClass().getName() + ".");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,12 +38,12 @@ public final class HealOvertimeHandler extends AbstractMaplePacketHandler {
|
||||
if(!chr.isLoggedinWorld()) return;
|
||||
|
||||
AutobanManager abm = chr.getAutobanManager();
|
||||
int timestamp = (int) (Server.getInstance().getCurrentTime() - Server.uptime);
|
||||
int timestamp = Server.getInstance().getCurrentTimestamp();
|
||||
slea.skip(8);
|
||||
|
||||
short healHP = slea.readShort();
|
||||
if (healHP != 0) {
|
||||
abm.setTimestamp(8, timestamp, 3); // thanks Vcoc for pointing out d/c happening here
|
||||
abm.setTimestamp(8, timestamp, 4); // thanks Vcoc for pointing out d/c happening here
|
||||
if ((abm.getLastSpam(0) + 1500) > timestamp) AutobanFactory.FAST_HP_HEALING.addPoint(abm, "Fast hp healing");
|
||||
|
||||
int abHeal = 120 + (int)(20 * MapleMapFactory.getMapRecoveryRate(chr.getMapId())); // Sleepywood sauna and showa spa...
|
||||
@@ -58,7 +58,7 @@ public final class HealOvertimeHandler extends AbstractMaplePacketHandler {
|
||||
}
|
||||
short healMP = slea.readShort();
|
||||
if (healMP != 0 && healMP < 1000) {
|
||||
abm.setTimestamp(9, timestamp, 3);
|
||||
abm.setTimestamp(9, timestamp, 4);
|
||||
if ((abm.getLastSpam(1) + 1500) > timestamp) AutobanFactory.FAST_MP_HEALING.addPoint(abm, "Fast mp healing");
|
||||
chr.addMP(healMP);
|
||||
abm.spam(1, timestamp);
|
||||
|
||||
@@ -31,6 +31,7 @@ import client.MapleClient;
|
||||
import client.inventory.Item;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import net.server.Server;
|
||||
import server.MapleItemInformationProvider;
|
||||
|
||||
public final class InventoryMergeHandler extends AbstractMaplePacketHandler {
|
||||
@@ -38,7 +39,8 @@ public final class InventoryMergeHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
chr.getAutobanManager().setTimestamp(2, slea.readInt(), 3);
|
||||
slea.readInt();
|
||||
chr.getAutobanManager().setTimestamp(2, Server.getInstance().getCurrentTimestamp(), 4);
|
||||
|
||||
if(!ServerConstants.USE_ITEM_SORT) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
|
||||
@@ -24,7 +24,6 @@ package net.server.channel.handlers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import constants.ServerConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
@@ -35,7 +34,9 @@ import client.inventory.Equip;
|
||||
import client.inventory.MapleInventory;
|
||||
import client.inventory.MapleInventoryType;
|
||||
import client.inventory.ModifyInventory;
|
||||
import constants.ServerConstants;
|
||||
import server.MapleItemInformationProvider;
|
||||
import net.server.Server;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -187,7 +188,8 @@ public final class InventorySortHandler extends AbstractMaplePacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
chr.getAutobanManager().setTimestamp(3, slea.readInt(), 3);
|
||||
slea.readInt();
|
||||
chr.getAutobanManager().setTimestamp(3, Server.getInstance().getCurrentTimestamp(), 4);
|
||||
|
||||
if(!ServerConstants.USE_ITEM_SORT) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
|
||||
@@ -61,7 +61,7 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
}
|
||||
|
||||
MapleMonster monster = (MapleMonster) mmo;
|
||||
List<MapleCharacter> banishPlayers = new LinkedList<>();
|
||||
List<MapleCharacter> banishPlayers = null;
|
||||
|
||||
byte pNibbles = slea.readByte();
|
||||
byte rawActivity = slea.readByte();
|
||||
@@ -70,7 +70,7 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
short pOption = slea.readShort();
|
||||
slea.skip(8);
|
||||
|
||||
if (rawActivity >= 0) {
|
||||
if (rawActivity >= 0) {
|
||||
rawActivity = (byte) (rawActivity & 0xFF >> 1);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,9 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
boolean isSkill = inRangeInclusive(rawActivity, 21, 25);
|
||||
|
||||
byte attackId = (byte) (isAttack ? rawActivity - 12 : -1);
|
||||
boolean nextMovementCouldBeSkill = (pNibbles & 0x0F) != 0;
|
||||
isSkill |= (pNibbles != 0);
|
||||
|
||||
boolean nextMovementCouldBeSkill = true;
|
||||
boolean pUnk = (pNibbles & 0xF0) != 0;
|
||||
|
||||
boolean currentController = (monster.getController() == player);
|
||||
@@ -86,6 +88,7 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
MobSkill toUse = null;
|
||||
int useSkillId = 0, useSkillLevel = 0;
|
||||
|
||||
int rnd = 0;
|
||||
if (isSkill) {
|
||||
int noSkills = monster.getNoSkills();
|
||||
if (noSkills > 0) {
|
||||
@@ -95,21 +98,21 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
useSkillId = skillToUse.getLeft();
|
||||
useSkillLevel = skillToUse.getRight();
|
||||
toUse = MobSkillFactory.getMobSkill(useSkillId, useSkillLevel);
|
||||
} else {
|
||||
|
||||
rnd = rndSkill;
|
||||
nextMovementCouldBeSkill = false;
|
||||
}
|
||||
} else {
|
||||
nextMovementCouldBeSkill = false;
|
||||
}
|
||||
|
||||
int mobMp;
|
||||
if (toUse != null && toUse.getHP() >= (int) (((float) monster.getHp() / monster.getMaxHp()) * 100) && monster.canUseSkill(toUse)) {
|
||||
mobMp = monster.getMp();
|
||||
|
||||
|
||||
int animationTime = MapleMonsterInformationProvider.getInstance().getMobSkillAnimationTime(toUse);
|
||||
if(animationTime > 0) {
|
||||
toUse.applyDelayedEffect(player, monster, true, banishPlayers, animationTime);
|
||||
if(animationTime > 0 && toUse.getSkillId() != 129) {
|
||||
toUse.applyDelayedEffect(player, monster, true, animationTime);
|
||||
} else {
|
||||
banishPlayers = new LinkedList<>();
|
||||
toUse.applyEffect(player, monster, true, banishPlayers);
|
||||
}
|
||||
} else {
|
||||
@@ -138,36 +141,45 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
short start_y = slea.readShort(); // hmm...
|
||||
Point startPos = new Point(start_x, start_y - 2);
|
||||
List<LifeMovementFragment> res = parseMovement(slea);
|
||||
if (!currentController) {
|
||||
if (monster.isAttackedBy(player)) {
|
||||
monster.switchController(player, true);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (rawActivity == -1 && monster.isControllerKnowsAboutAggro() && !monster.isMobile() && !monster.isFirstAttack()) {
|
||||
monster.setControllerHasAggro(false);
|
||||
monster.setControllerKnowsAboutAggro(false);
|
||||
}
|
||||
|
||||
boolean aggro;
|
||||
monster.lockMonster();
|
||||
try {
|
||||
if (!currentController) {
|
||||
if (monster.isAttackedBy(player)) {
|
||||
monster.switchController(player, true);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (rawActivity == -1 && monster.isControllerKnowsAboutAggro() && !monster.isMobile() && !monster.isFirstAttack()) {
|
||||
monster.setControllerHasAggro(false);
|
||||
monster.setControllerKnowsAboutAggro(false);
|
||||
}
|
||||
|
||||
aggro = monster.isControllerHasAggro();
|
||||
if (aggro) {
|
||||
monster.setControllerKnowsAboutAggro(true);
|
||||
}
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
|
||||
boolean aggro = monster.isControllerHasAggro();
|
||||
if (toUse != null) {
|
||||
c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro, toUse.getSkillId(), toUse.getSkillLevel()));
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro));
|
||||
}
|
||||
|
||||
if (aggro) {
|
||||
monster.setControllerKnowsAboutAggro(true);
|
||||
}
|
||||
|
||||
if (res != null) {
|
||||
map.broadcastMessage(player, MaplePacketCreator.moveMonster(objectid, nextMovementCouldBeSkill, rawActivity, useSkillId, useSkillLevel, pOption, startPos, res), monster.getPosition());
|
||||
updatePosition(res, monster, -2);
|
||||
map.moveMonster(monster, monster.getPosition());
|
||||
}
|
||||
|
||||
for (MapleCharacter chr : banishPlayers) {
|
||||
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
if (banishPlayers != null) {
|
||||
for (MapleCharacter chr : banishPlayers) {
|
||||
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,9 @@ public final class PetCommandHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
if (Randomizer.nextInt(101) <= petCommand.getProbability()) {
|
||||
pet.gainClosenessFullness(chr, petCommand.getIncrease(), 0, command);
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.commandResponse(chr.getId(), petIndex, false, command, false));
|
||||
} else {
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.commandResponse(chr.getId(), petIndex, command, false));
|
||||
chr.getMap().broadcastMessage(MaplePacketCreator.commandResponse(chr.getId(), petIndex, true, command, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.inventory.MapleInventory;
|
||||
@@ -28,8 +29,8 @@ import client.inventory.MapleInventoryType;
|
||||
import client.inventory.MaplePet;
|
||||
import client.autoban.AutobanManager;
|
||||
import client.inventory.Item;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import net.server.Server;
|
||||
import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
@@ -44,7 +45,8 @@ public final class PetFoodHandler extends AbstractMaplePacketHandler {
|
||||
return;
|
||||
}
|
||||
abm.spam(2);
|
||||
abm.setTimestamp(1, slea.readInt(), 3);
|
||||
slea.readInt(); // timestamp issue detected thanks to Masterrulax
|
||||
abm.setTimestamp(1, Server.getInstance().getCurrentTimestamp(), 3);
|
||||
if (chr.getNoPets() == 0) {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
|
||||
@@ -163,7 +163,7 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean soulArrow = chr.getBuffedValue(MapleBuffStat.SOULARROW) != null;
|
||||
boolean shadowClaw = chr.getBuffedValue(MapleBuffStat.SHADOW_CLAW) != null;
|
||||
if (projectile != 0) {
|
||||
@@ -179,7 +179,7 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (projectile != 0 || soulArrow || attack.skill == 11101004 || attack.skill == 15111007 || attack.skill == 14101006 || attack.skill == 4111004) {
|
||||
if (projectile != 0 || soulArrow || attack.skill == 11101004 || attack.skill == 15111007 || attack.skill == 14101006 || attack.skill == 4111004 || attack.skill == 13101005) {
|
||||
int visProjectile = projectile; //visible projectile sent to players
|
||||
if (ItemConstants.isThrowingStar(projectile)) {
|
||||
MapleInventory cash = chr.getInventory(MapleInventoryType.CASH);
|
||||
@@ -192,7 +192,7 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (soulArrow || attack.skill == 3111004 || attack.skill == 3211004 || attack.skill == 11101004 || attack.skill == 15111007 || attack.skill == 14101006) {
|
||||
} else if (soulArrow || attack.skill == 3111004 || attack.skill == 3211004 || attack.skill == 11101004 || attack.skill == 15111007 || attack.skill == 14101006 || attack.skill == 13101005) {
|
||||
visProjectile = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public final class ScriptedItemHandler extends AbstractMaplePacketHandler {
|
||||
if (item == null || item.getItemId() != itemId || item.getQuantity() < 1 || !ism.scriptExists(info.getScript())) {
|
||||
return;
|
||||
}
|
||||
ism.getItemScript(c, info.getScript());
|
||||
ism.runItemScript(c, info.getScript());
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
//NPCScriptManager.getInstance().start(c, info.getNpc(), null, null);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import tools.MaplePacketCreator;
|
||||
import tools.data.input.SeekableLittleEndianAccessor;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import client.MapleStat;
|
||||
import client.Skill;
|
||||
import client.SkillFactory;
|
||||
import constants.ServerConstants;
|
||||
@@ -41,14 +40,15 @@ import constants.skills.Hero;
|
||||
import constants.skills.Paladin;
|
||||
import constants.skills.Priest;
|
||||
import constants.skills.SuperGM;
|
||||
|
||||
import net.server.Server;
|
||||
|
||||
public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
chr.getAutobanManager().setTimestamp(4, slea.readInt(), 3);
|
||||
slea.readInt();
|
||||
chr.getAutobanManager().setTimestamp(4, Server.getInstance().getCurrentTimestamp(), 5);
|
||||
int skillid = slea.readInt();
|
||||
|
||||
/*
|
||||
@@ -99,9 +99,14 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
|
||||
chr.getMap().broadcastMessage(chr, MaplePacketCreator.showMagnet(mobId, success), false);
|
||||
MapleMonster monster = chr.getMap().getMonsterByOid(mobId);
|
||||
if (monster != null) {
|
||||
if (!monster.isBoss()) {
|
||||
monster.switchController(chr, monster.isControllerHasAggro());
|
||||
}
|
||||
if (!monster.isBoss()) {
|
||||
monster.lockMonster();
|
||||
try {
|
||||
monster.switchController(chr, monster.isControllerHasAggro());
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
byte direction = slea.readByte();
|
||||
|
||||
@@ -32,6 +32,8 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
* @author Generic
|
||||
*/
|
||||
public final class TouchReactorHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
int oid = slea.readInt();
|
||||
MapleReactor reactor = c.getPlayer().getMap().getReactorByOid(oid);
|
||||
|
||||
@@ -27,6 +27,7 @@ import client.inventory.MapleInventoryType;
|
||||
import client.autoban.AutobanManager;
|
||||
import constants.ItemConstants;
|
||||
import net.AbstractMaplePacketHandler;
|
||||
import net.server.Server;
|
||||
import client.inventory.manipulator.MapleInventoryManipulator;
|
||||
import server.life.MapleMonster;
|
||||
import tools.MaplePacketCreator;
|
||||
@@ -41,7 +42,8 @@ public final class UseCatchItemHandler extends AbstractMaplePacketHandler {
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
AutobanManager abm = chr.getAutobanManager();
|
||||
abm.setTimestamp(5, slea.readInt(), 3);
|
||||
slea.readInt();
|
||||
abm.setTimestamp(5, Server.getInstance().getCurrentTimestamp(), 4);
|
||||
slea.readShort();
|
||||
int itemId = slea.readInt();
|
||||
int monsterid = slea.readInt();
|
||||
|
||||
@@ -35,7 +35,6 @@ import constants.GameConstants;
|
||||
/**
|
||||
* @author Ronan
|
||||
*/
|
||||
|
||||
public final class UseOwlOfMinervaHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1402,7 +1402,9 @@ public class World {
|
||||
|
||||
int dpVal = dp.getValue() + 1;
|
||||
if(dpVal == ServerConstants.MOUNT_EXHAUST_COUNT) {
|
||||
chr.runTirednessSchedule();
|
||||
if (!chr.runTirednessSchedule()) {
|
||||
continue;
|
||||
}
|
||||
dpVal = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -512,21 +512,21 @@ public class AbstractPlayerInteraction {
|
||||
petId = MaplePet.createPet(id);
|
||||
|
||||
if(from != null) {
|
||||
evolved = MaplePet.loadFromDb(id, (short) 0, petId);
|
||||
evolved = MaplePet.loadFromDb(id, (short) 0, petId);
|
||||
|
||||
Point pos = getPlayer().getPosition();
|
||||
pos.y -= 12;
|
||||
evolved.setPos(pos);
|
||||
evolved.setFh(getPlayer().getMap().getFootholds().findBelow(evolved.getPos()).getId());
|
||||
evolved.setStance(0);
|
||||
evolved.setSummoned(true);
|
||||
Point pos = getPlayer().getPosition();
|
||||
pos.y -= 12;
|
||||
evolved.setPos(pos);
|
||||
evolved.setFh(getPlayer().getMap().getFootholds().findBelow(evolved.getPos()).getId());
|
||||
evolved.setStance(0);
|
||||
evolved.setSummoned(true);
|
||||
|
||||
evolved.setName(from.getName().compareTo(MapleItemInformationProvider.getInstance().getName(from.getItemId())) != 0 ? from.getName() : MapleItemInformationProvider.getInstance().getName(id));
|
||||
evolved.setCloseness(from.getCloseness());
|
||||
evolved.setFullness(from.getFullness());
|
||||
evolved.setLevel(from.getLevel());
|
||||
evolved.setExpiration(System.currentTimeMillis() + expires);
|
||||
evolved.saveToDb();
|
||||
evolved.setName(from.getName().compareTo(MapleItemInformationProvider.getInstance().getName(from.getItemId())) != 0 ? from.getName() : MapleItemInformationProvider.getInstance().getName(id));
|
||||
evolved.setCloseness(from.getCloseness());
|
||||
evolved.setFullness(from.getFullness());
|
||||
evolved.setLevel(from.getLevel());
|
||||
evolved.setExpiration(System.currentTimeMillis() + expires);
|
||||
evolved.saveToDb();
|
||||
}
|
||||
|
||||
//MapleInventoryManipulator.addById(c, id, (short) 1, null, petId, expires == -1 ? -1 : System.currentTimeMillis() + expires);
|
||||
|
||||
@@ -69,6 +69,7 @@ import net.server.coordinator.MapleEventRecallCoordinator;
|
||||
import scripting.AbstractPlayerInteraction;
|
||||
import scripting.event.worker.EventScriptScheduler;
|
||||
import server.MapleItemInformationProvider;
|
||||
import server.ThreadManager;
|
||||
import server.life.MapleLifeFactory;
|
||||
import server.life.MapleNPC;
|
||||
import tools.MaplePacketCreator;
|
||||
@@ -228,51 +229,42 @@ public class EventInstanceManager {
|
||||
|
||||
}
|
||||
|
||||
public synchronized void registerPlayer(MapleCharacter chr) {
|
||||
public synchronized void registerPlayer(final MapleCharacter chr) {
|
||||
if (chr == null || !chr.isLoggedinWorld() || disposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
wL.lock();
|
||||
try {
|
||||
wL.lock();
|
||||
try {
|
||||
if(chars.containsKey(chr.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
chars.put(chr.getId(), chr);
|
||||
chr.setEventInstance(this);
|
||||
} finally {
|
||||
wL.unlock();
|
||||
if(chars.containsKey(chr.getId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("playerEntry", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
chars.put(chr.getId(), chr);
|
||||
chr.setEventInstance(this);
|
||||
} finally {
|
||||
wL.unlock();
|
||||
}
|
||||
|
||||
try {
|
||||
em.getIv().invokeFunction("playerEntry", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void exitPlayer(MapleCharacter chr) {
|
||||
public void exitPlayer(final MapleCharacter chr) {
|
||||
if (chr == null || !chr.isLoggedin()){
|
||||
return;
|
||||
}
|
||||
try {
|
||||
unregisterPlayer(chr);
|
||||
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("playerExit", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
unregisterPlayer(chr);
|
||||
|
||||
try {
|
||||
em.getIv().invokeFunction("playerExit", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void dropMessage(int type, String message) {
|
||||
@@ -297,15 +289,10 @@ public class EventInstanceManager {
|
||||
event_schedule = TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dismissEventTimer();
|
||||
|
||||
try {
|
||||
dismissEventTimer();
|
||||
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement scheduledTimeout function.", ex);
|
||||
}
|
||||
@@ -314,31 +301,25 @@ public class EventInstanceManager {
|
||||
}
|
||||
|
||||
public void addEventTimer(long time) {
|
||||
if(event_schedule != null) {
|
||||
if(event_schedule.cancel(false)) {
|
||||
if (event_schedule != null) {
|
||||
if (event_schedule.cancel(false)) {
|
||||
long nextTime = getTimeLeft() + time;
|
||||
eventTime += time;
|
||||
|
||||
event_schedule = TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dismissEventTimer();
|
||||
|
||||
try {
|
||||
dismissEventTimer();
|
||||
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
em.getIv().invokeFunction("scheduledTimeout", EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement scheduledTimeout function.", ex);
|
||||
}
|
||||
}
|
||||
}, nextTime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
startEventTimer(time);
|
||||
}
|
||||
}
|
||||
@@ -358,6 +339,7 @@ public class EventInstanceManager {
|
||||
event_schedule.cancel(false);
|
||||
event_schedule = null;
|
||||
}
|
||||
|
||||
dismissEventTimer();
|
||||
}
|
||||
|
||||
@@ -370,7 +352,7 @@ public class EventInstanceManager {
|
||||
}
|
||||
|
||||
public void registerParty(MapleCharacter chr) {
|
||||
if(chr.isPartyLeader()) {
|
||||
if (chr.isPartyLeader()) {
|
||||
registerParty(chr.getParty(), chr.getMap());
|
||||
}
|
||||
}
|
||||
@@ -390,20 +372,16 @@ public class EventInstanceManager {
|
||||
private void registerExpeditionTeam(MapleExpedition exped, int recruitMap) {
|
||||
expedition = exped;
|
||||
|
||||
for(MapleCharacter chr: exped.getMembers()) {
|
||||
if(chr.getMapId() == recruitMap)
|
||||
for (MapleCharacter chr: exped.getMembers()) {
|
||||
if (chr.getMapId() == recruitMap) {
|
||||
registerPlayer(chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterPlayer(MapleCharacter chr) {
|
||||
public void unregisterPlayer(final MapleCharacter chr) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("playerUnregistered", EventInstanceManager.this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
em.getIv().invokeFunction("playerUnregistered", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
Logger.getLogger(EventManager.class.getName()).log(Level.SEVERE, "Event '" + em.getName() + "' does not implement playerUnregistered function.", ex);
|
||||
}
|
||||
@@ -462,180 +440,140 @@ public class EventInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void movePlayer(MapleCharacter chr) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("moveMap", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void changedMap(MapleCharacter chr, int mapId) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("changedMap", this, chr, mapId);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
}
|
||||
|
||||
public void afterChangedMap(MapleCharacter chr, int mapId) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("afterChangedMap", this, chr, mapId);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
}
|
||||
|
||||
public void changedLeader(MapleCharacter ldr) {
|
||||
public void movePlayer(final MapleCharacter chr) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("changedLeader", this, ldr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
em.getIv().invokeFunction("moveMap", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void changedMap(final MapleCharacter chr, final int mapId) {
|
||||
try {
|
||||
em.getIv().invokeFunction("changedMap", EventInstanceManager.this, chr, mapId);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
}
|
||||
|
||||
public void afterChangedMap(final MapleCharacter chr, final int mapId) {
|
||||
try {
|
||||
em.getIv().invokeFunction("afterChangedMap", EventInstanceManager.this, chr, mapId);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
}
|
||||
|
||||
public synchronized void changedLeader(final MapleCharacter ldr) {
|
||||
try {
|
||||
em.getIv().invokeFunction("changedLeader", EventInstanceManager.this, ldr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
leaderId = ldr.getId();
|
||||
}
|
||||
|
||||
public void monsterKilled(MapleMonster mob, boolean hasKiller) {
|
||||
public void monsterKilled(final MapleMonster mob, final boolean hasKiller) {
|
||||
int scriptResult = 0;
|
||||
|
||||
sL.lock();
|
||||
try {
|
||||
mobs.remove(mob);
|
||||
|
||||
if(eventStarted) {
|
||||
try {
|
||||
em.getIv().invokeFunction("monsterKilled", mob, this, hasKiller);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
scriptResult = 1;
|
||||
|
||||
if (mobs.isEmpty()) {
|
||||
try {
|
||||
em.getIv().invokeFunction("allMonstersDead", this, hasKiller);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
scriptResult = 2;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
|
||||
if (scriptResult > 0) {
|
||||
try {
|
||||
em.getIv().invokeFunction("monsterKilled", mob, EventInstanceManager.this, hasKiller);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
if (scriptResult > 1) {
|
||||
try {
|
||||
em.getIv().invokeFunction("allMonstersDead", EventInstanceManager.this, hasKiller);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void friendlyKilled(MapleMonster mob, boolean hasKiller) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("friendlyKilled", mob, this, hasKiller);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
public void friendlyKilled(final MapleMonster mob, final boolean hasKiller) {
|
||||
try {
|
||||
em.getIv().invokeFunction("friendlyKilled", mob, EventInstanceManager.this, hasKiller);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} //optional
|
||||
}
|
||||
|
||||
public void playerKilled(MapleCharacter chr) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("playerDead", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
public void playerKilled(final MapleCharacter chr) {
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
em.getIv().invokeFunction("playerDead", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
});
|
||||
}
|
||||
|
||||
public void reviveMonster(MapleMonster mob) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("monsterRevive", this, mob);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
public void reviveMonster(final MapleMonster mob) {
|
||||
try {
|
||||
em.getIv().invokeFunction("monsterRevive", EventInstanceManager.this, mob);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
}
|
||||
|
||||
public boolean revivePlayer(MapleCharacter chr) {
|
||||
try {
|
||||
Object b;
|
||||
|
||||
sL.lock();
|
||||
try {
|
||||
b = em.getIv().invokeFunction("playerRevive", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
public boolean revivePlayer(final MapleCharacter chr) {
|
||||
try {
|
||||
Object b = em.getIv().invokeFunction("playerRevive", EventInstanceManager.this, chr);
|
||||
if (b instanceof Boolean) {
|
||||
return (Boolean) b;
|
||||
}
|
||||
|
||||
if (b instanceof Boolean) {
|
||||
return (Boolean) b;
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
} catch (ScriptException | NoSuchMethodException ex) {} // optional
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void playerDisconnected(MapleCharacter chr) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("playerDisconnected", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
public void playerDisconnected(final MapleCharacter chr) {
|
||||
try {
|
||||
em.getIv().invokeFunction("playerDisconnected", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
MapleEventRecallCoordinator.getInstance().storeEventInstance(chr.getId(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param chr
|
||||
* @param mob
|
||||
*/
|
||||
public void monsterKilled(MapleCharacter chr, MapleMonster mob) {
|
||||
try {
|
||||
Integer kc = killCount.get(chr);
|
||||
|
||||
public void monsterKilled(MapleCharacter chr, final MapleMonster mob) {
|
||||
try {
|
||||
int inc;
|
||||
|
||||
sL.lock();
|
||||
try {
|
||||
if(ServerConstants.JAVA_8)
|
||||
inc = (int)em.getIv().invokeFunction("monsterValue", this, mob.getId());
|
||||
else
|
||||
inc = ((Double) em.getIv().invokeFunction("monsterValue", this, mob.getId())).intValue();
|
||||
} finally {
|
||||
sL.unlock();
|
||||
if (ServerConstants.JAVA_8) {
|
||||
inc = (int)em.getIv().invokeFunction("monsterValue", EventInstanceManager.this, mob.getId());
|
||||
} else {
|
||||
inc = ((Double) em.getIv().invokeFunction("monsterValue", EventInstanceManager.this, mob.getId())).intValue();
|
||||
}
|
||||
|
||||
if (kc == null) {
|
||||
kc = inc;
|
||||
} else {
|
||||
kc += inc;
|
||||
}
|
||||
killCount.put(chr, kc);
|
||||
if (expedition != null){
|
||||
expedition.monsterKilled(chr, mob);
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
if (inc != 0) {
|
||||
Integer kc = killCount.get(chr);
|
||||
if (kc == null) {
|
||||
kc = inc;
|
||||
} else {
|
||||
kc += inc;
|
||||
}
|
||||
killCount.put(chr, kc);
|
||||
if (expedition != null){
|
||||
expedition.monsterKilled(chr, mob);
|
||||
}
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getKillCount(MapleCharacter chr) {
|
||||
@@ -650,15 +588,8 @@ public class EventInstanceManager {
|
||||
} finally {
|
||||
rL.unlock();
|
||||
}
|
||||
|
||||
Thread t = new Thread( new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dispose(false);
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
dispose(false);
|
||||
}
|
||||
|
||||
public synchronized void dispose(boolean shutdown) { // should not trigger any event script method after disposed
|
||||
@@ -666,16 +597,11 @@ public class EventInstanceManager {
|
||||
|
||||
disposed = true;
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("dispose", this);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
em.getIv().invokeFunction("dispose", EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
mapFactory.dispose();
|
||||
ess.dispose();
|
||||
|
||||
@@ -738,13 +664,8 @@ public class EventInstanceManager {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
if(em == null) return;
|
||||
em.getIv().invokeFunction(methodName, EventInstanceManager.this);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
if(em == null) return;
|
||||
em.getIv().invokeFunction(methodName, EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
@@ -848,56 +769,36 @@ public class EventInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void leftParty(MapleCharacter chr) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("leftParty", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
public void leftParty(final MapleCharacter chr) {
|
||||
try {
|
||||
em.getIv().invokeFunction("leftParty", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void disbandParty() {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("disbandParty", this);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
em.getIv().invokeFunction("disbandParty", EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearPQ() {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("clearPQ", this);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
em.getIv().invokeFunction("clearPQ", EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayer(MapleCharacter chr) {
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
em.getIv().invokeFunction("playerExit", this, chr);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
public void removePlayer(final MapleCharacter chr) {
|
||||
try {
|
||||
em.getIv().invokeFunction("playerExit", EventInstanceManager.this, chr);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLeader(MapleCharacter chr) {
|
||||
@@ -1158,15 +1059,11 @@ public class EventInstanceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public final void startEvent() {
|
||||
public final synchronized void startEvent() {
|
||||
eventStarted = true;
|
||||
|
||||
try {
|
||||
sL.lock();
|
||||
try {
|
||||
eventStarted = true;
|
||||
em.getIv().invokeFunction("afterSetup", this);
|
||||
} finally {
|
||||
sL.unlock();
|
||||
}
|
||||
em.getIv().invokeFunction("afterSetup", EventInstanceManager.this);
|
||||
} catch (ScriptException | NoSuchMethodException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ import net.server.audit.LockCollector;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import server.ThreadManager;
|
||||
//import jdk.nashorn.api.scripting.ScriptUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -647,12 +649,11 @@ public class EventManager {
|
||||
if(p != null) {
|
||||
List<MaplePartyCharacter> lmpc;
|
||||
|
||||
/*
|
||||
if(ServerConstants.JAVA_8)
|
||||
/*if(ServerConstants.JAVA_8) {
|
||||
lmpc = new ArrayList<>(((Map<String, MaplePartyCharacter>)(ScriptUtils.convert(p, Map.class))).values());
|
||||
else
|
||||
} else {
|
||||
lmpc = new ArrayList<>((List<MaplePartyCharacter>) p);
|
||||
*/
|
||||
}*/
|
||||
|
||||
lmpc = new ArrayList<>((List<MaplePartyCharacter>) p);
|
||||
party.setEligibleMembers(lmpc);
|
||||
@@ -809,8 +810,7 @@ public class EventManager {
|
||||
}
|
||||
|
||||
private void fillEimQueue() {
|
||||
Thread t = new Thread(new EventManagerWorker()); //call new thread to fill up readied instances queue
|
||||
t.start();
|
||||
ThreadManager.getInstance().newTask(new EventManagerWorker()); //call new thread to fill up readied instances queue
|
||||
}
|
||||
|
||||
private EventInstanceManager getReadyInstance() {
|
||||
|
||||
@@ -32,6 +32,7 @@ import net.server.audit.LockCollector;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
|
||||
import server.ThreadManager;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -105,68 +106,62 @@ public class EventScriptScheduler {
|
||||
|
||||
public void registerEntry(final Runnable scheduledAction, final long duration) {
|
||||
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
idleProcs = 0;
|
||||
if(schedulerTask == null) {
|
||||
if(disposed) return;
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
idleProcs = 0;
|
||||
if(schedulerTask == null) {
|
||||
if(disposed) return;
|
||||
|
||||
schedulerTask = TimerManager.getInstance().register(monitorTask, ServerConstants.MOB_STATUS_MONITOR_PROC, ServerConstants.MOB_STATUS_MONITOR_PROC);
|
||||
}
|
||||
schedulerTask = TimerManager.getInstance().register(monitorTask, ServerConstants.MOB_STATUS_MONITOR_PROC, ServerConstants.MOB_STATUS_MONITOR_PROC);
|
||||
}
|
||||
|
||||
registeredEntries.put(scheduledAction, Server.getInstance().getCurrentTime() + duration);
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
registeredEntries.put(scheduledAction, Server.getInstance().getCurrentTime() + duration);
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void cancelEntry(final Runnable scheduledAction) {
|
||||
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
registeredEntries.remove(scheduledAction);
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
registeredEntries.remove(scheduledAction);
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
||||
Thread t = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
if(schedulerTask != null) {
|
||||
schedulerTask.cancel(false);
|
||||
schedulerTask = null;
|
||||
}
|
||||
ThreadManager.getInstance().newTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
schedulerLock.lock();
|
||||
try {
|
||||
if(schedulerTask != null) {
|
||||
schedulerTask.cancel(false);
|
||||
schedulerTask = null;
|
||||
}
|
||||
|
||||
registeredEntries.clear();
|
||||
disposed = true;
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
|
||||
disposeLocks();
|
||||
}
|
||||
});
|
||||
|
||||
t.start();
|
||||
registeredEntries.clear();
|
||||
disposed = true;
|
||||
} finally {
|
||||
schedulerLock.unlock();
|
||||
}
|
||||
|
||||
disposeLocks();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void disposeLocks() {
|
||||
|
||||
@@ -59,7 +59,7 @@ public class ItemScriptManager {
|
||||
return scriptFile.exists();
|
||||
}
|
||||
|
||||
public void getItemScript(MapleClient c, String scriptName) {
|
||||
public void runItemScript(MapleClient c, String scriptName) {
|
||||
if (scripts.containsKey(scriptName)) {
|
||||
try {
|
||||
scripts.get(scriptName).invokeFunction("start", new ItemScriptMethods(c));
|
||||
|
||||
@@ -62,7 +62,7 @@ public class MapScriptManager {
|
||||
return scriptFile.exists();
|
||||
}
|
||||
|
||||
public void getMapScript(MapleClient c, String scriptName, boolean firstUser) {
|
||||
public void runMapScript(MapleClient c, String scriptName, boolean firstUser) {
|
||||
if (scripts.containsKey(scriptName)) {
|
||||
try {
|
||||
scripts.get(scriptName).invokeFunction("start", new MapScriptMethods(c));
|
||||
|
||||
@@ -646,7 +646,7 @@ public class MapleItemInformationProvider {
|
||||
}
|
||||
|
||||
public static boolean rollSuccessChance(double prop) {
|
||||
return Math.random() > testYourLuck(prop / 100.0, ServerConstants.SCROLL_CHANCE_RATE);
|
||||
return Math.random() >= testYourLuck(prop / 100.0, ServerConstants.SCROLL_CHANCE_RATE);
|
||||
}
|
||||
|
||||
private static short getMaximumShortMaxIfOverflow(int value1, int value2) {
|
||||
@@ -1238,9 +1238,11 @@ public class MapleItemInformationProvider {
|
||||
boolean bRestricted = false;
|
||||
if(itemId != 0) {
|
||||
MapleData data = getItemData(itemId);
|
||||
bRestricted = MapleDataTool.getIntConvert("info/tradeBlock", data, 0) == 1;
|
||||
if (!bRestricted) {
|
||||
bRestricted = MapleDataTool.getIntConvert("info/accountSharable", data, 0) == 1;
|
||||
if (data != null) {
|
||||
bRestricted = MapleDataTool.getIntConvert("info/tradeBlock", data, 0) == 1;
|
||||
if (!bRestricted) {
|
||||
bRestricted = MapleDataTool.getIntConvert("info/accountSharable", data, 0) == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 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 server;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.RejectedExecutionHandler;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public class ThreadManager {
|
||||
private static ThreadManager instance = new ThreadManager();
|
||||
|
||||
public static ThreadManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ThreadPoolExecutor tpe;
|
||||
|
||||
private ThreadManager() {}
|
||||
|
||||
private class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
|
||||
|
||||
@Override
|
||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||
Thread t = new Thread(r);
|
||||
t.start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void newTask(Runnable r) {
|
||||
tpe.execute(r);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
RejectedExecutionHandler reh = new RejectedExecutionHandlerImpl();
|
||||
ThreadFactory tf = Executors.defaultThreadFactory();
|
||||
|
||||
tpe = new ThreadPoolExecutor(20, 1000, 77, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(50), tf, reh);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
tpe.shutdown();
|
||||
try {
|
||||
tpe.awaitTermination(5, TimeUnit.MINUTES);
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -573,15 +573,28 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}
|
||||
|
||||
private void removeController() {
|
||||
this.lockMonster();
|
||||
try {
|
||||
MapleCharacter chrController = getController();
|
||||
if (chrController != null) { // this can/should only happen when a hidden gm attacks the monster
|
||||
chrController.announce(MaplePacketCreator.stopControllingMonster(this.getObjectId()));
|
||||
chrController.stopControllingMonster(this);
|
||||
}
|
||||
|
||||
setController(null);
|
||||
setControllerHasAggro(false);
|
||||
setControllerKnowsAboutAggro(false);
|
||||
} finally {
|
||||
this.unlockMonster();
|
||||
}
|
||||
}
|
||||
|
||||
public MapleCharacter killBy(final MapleCharacter killer) {
|
||||
distributeExperience(killer != null ? killer.getId() : 0);
|
||||
|
||||
MapleCharacter chrController = getController();
|
||||
if (chrController != null) { // this can/should only happen when a hidden gm attacks the monster
|
||||
chrController.announce(MaplePacketCreator.stopControllingMonster(this.getObjectId()));
|
||||
chrController.stopControllingMonster(this);
|
||||
}
|
||||
|
||||
|
||||
removeController();
|
||||
|
||||
final List<Integer> toSpawn = this.getRevives(); // this doesn't work (?)
|
||||
if (toSpawn != null) {
|
||||
final MapleMap reviveMap = map;
|
||||
@@ -647,8 +660,9 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 8810017; i >= 8810010; i--)
|
||||
for(int i = 8810017; i >= 8810010; i--) {
|
||||
reviveMap.killMonster(reviveMap.getMonsterById(i), killer, true);
|
||||
}
|
||||
}
|
||||
|
||||
if(eim != null) {
|
||||
@@ -787,20 +801,24 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
|
||||
public void switchController(MapleCharacter newController, boolean immediateAggro) {
|
||||
MapleCharacter controllers = getController();
|
||||
if (controllers == newController) {
|
||||
return;
|
||||
this.lockMonster();
|
||||
try {
|
||||
MapleCharacter controllers = getController();
|
||||
if (controllers == newController) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeController();
|
||||
|
||||
newController.controlMonster(this, immediateAggro);
|
||||
setController(newController);
|
||||
if (immediateAggro) {
|
||||
setControllerHasAggro(true);
|
||||
}
|
||||
setControllerKnowsAboutAggro(false);
|
||||
} finally {
|
||||
this.unlockMonster();
|
||||
}
|
||||
if (controllers != null) {
|
||||
controllers.stopControllingMonster(this);
|
||||
controllers.getClient().announce(MaplePacketCreator.stopControllingMonster(getObjectId()));
|
||||
}
|
||||
newController.controlMonster(this, immediateAggro);
|
||||
setController(newController);
|
||||
if (immediateAggro) {
|
||||
setControllerHasAggro(true);
|
||||
}
|
||||
setControllerKnowsAboutAggro(false);
|
||||
}
|
||||
|
||||
public void addListener(MonsterListener listener) {
|
||||
@@ -863,20 +881,21 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient c) {
|
||||
if (!isAlive()) {
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
if (hp.get() <= 0) { // mustn't monsterLock this function
|
||||
return;
|
||||
}
|
||||
if (isFake()) {
|
||||
c.announce(MaplePacketCreator.spawnFakeMonster(this, 0));
|
||||
if (fake) {
|
||||
client.announce(MaplePacketCreator.spawnFakeMonster(this, 0));
|
||||
} else {
|
||||
c.announce(MaplePacketCreator.spawnMonster(this, false));
|
||||
client.announce(MaplePacketCreator.spawnMonster(this, false));
|
||||
}
|
||||
|
||||
statiLock.lock();
|
||||
try {
|
||||
if (stati.size() > 0) {
|
||||
for (final MonsterStatusEffect mse : this.stati.values()) {
|
||||
c.announce(MaplePacketCreator.applyMonsterStatus(getObjectId(), mse, null));
|
||||
client.announce(MaplePacketCreator.applyMonsterStatus(getObjectId(), mse, null));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -884,7 +903,7 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
}
|
||||
|
||||
if (hasBossHPBar()) {
|
||||
c.announceBossHpBar(this, this.hashCode(), makeBossHPBarPacket());
|
||||
client.announceBossHpBar(this, this.hashCode(), makeBossHPBarPacket());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1155,6 +1174,18 @@ public class MapleMonster extends AbstractLoadedMapleLife {
|
||||
|
||||
map.getChannelServer().registerMobStatus(map.getId(), effect, cancelTask, duration);
|
||||
}
|
||||
|
||||
public void refreshMobPosition() {
|
||||
updateMobPosition(getPosition());
|
||||
}
|
||||
|
||||
public void updateMobPosition(Point newPoint) {
|
||||
removeController();
|
||||
setPosition(newPoint);
|
||||
map.broadcastMessage(MaplePacketCreator.moveMonster(this.getObjectId(), false, -1, 0, 0, 0, this.getPosition(), this.getIdleMovement()));
|
||||
map.moveMonster(this, this.getPosition());
|
||||
map.updateMonsterController(this);
|
||||
}
|
||||
|
||||
private void debuffMobStat(MonsterStatus stat) {
|
||||
statiLock.lock();
|
||||
|
||||
@@ -44,12 +44,8 @@ public class MapleNPC extends AbstractLoadedMapleLife {
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
if (this.getId() > 9010010 && this.getId() < 9010014) {
|
||||
client.announce(MaplePacketCreator.spawnNPCRequestController(this, false));
|
||||
} else {
|
||||
client.announce(MaplePacketCreator.spawnNPC(this));
|
||||
client.announce(MaplePacketCreator.spawnNPCRequestController(this, true));
|
||||
}
|
||||
client.announce(MaplePacketCreator.spawnNPC(this));
|
||||
client.announce(MaplePacketCreator.spawnNPCRequestController(this, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -103,12 +103,12 @@ public class MobSkill {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public void applyDelayedEffect(final MapleCharacter player, final MapleMonster monster, final boolean skill, final List<MapleCharacter> banishPlayers, int animationTime) {
|
||||
public void applyDelayedEffect(final MapleCharacter player, final MapleMonster monster, final boolean skill, int animationTime) {
|
||||
Runnable toRun = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if(monster.isAlive()) {
|
||||
applyEffect(player, monster, skill, banishPlayers);
|
||||
applyEffect(player, monster, skill, null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,18 +21,35 @@
|
||||
*/
|
||||
package server.maps;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import server.movement.AbsoluteLifeMovement;
|
||||
import server.movement.LifeMovementFragment;
|
||||
|
||||
public abstract class AbstractAnimatedMapleMapObject extends AbstractMapleMapObject implements AnimatedMapleMapObject {
|
||||
private int stance;
|
||||
|
||||
@Override
|
||||
public int getStance() {
|
||||
return stance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStance(int stance) {
|
||||
this.stance = stance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFacingLeft() {
|
||||
return Math.abs(stance) % 2 == 1;
|
||||
}
|
||||
|
||||
public List<LifeMovementFragment> getIdleMovement() {
|
||||
AbsoluteLifeMovement alm = new AbsoluteLifeMovement(0, getPosition(), 0, getStance());
|
||||
alm.setPixelsPerSecond(new Point(0, 0));
|
||||
|
||||
List<LifeMovementFragment> moveUpdate = Collections.singletonList((LifeMovementFragment) alm);
|
||||
return moveUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||
import net.server.world.MapleParty;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
@@ -84,10 +85,9 @@ public class MapleDoorObject extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void warp(final MapleCharacter chr) {
|
||||
boolean onParty = chr.getParty() != null;
|
||||
|
||||
if (chr.getId() == ownerId || (onParty && chr.getParty().getMemberById(ownerId) != null)) {
|
||||
if(!inTown() && !onParty) {
|
||||
MapleParty party = chr.getParty();
|
||||
if (chr.getId() == ownerId || (party != null && party.getMemberById(ownerId) != null)) {
|
||||
if(!inTown() && party == null) {
|
||||
chr.changeMap(to, getLinkedPortalId());
|
||||
} else {
|
||||
chr.changeMap(to, getLinkedPortalPosition());
|
||||
@@ -100,8 +100,10 @@ public class MapleDoorObject extends AbstractMapleMapObject {
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
if (from.getId() == client.getPlayer().getMapId()) {
|
||||
if (client.getPlayer().getParty() != null && (ownerId == client.getPlayer().getId() || client.getPlayer().getParty().getMemberById(ownerId) != null)) {
|
||||
MapleCharacter chr = client.getPlayer();
|
||||
if (from.getId() == chr.getMapId()) {
|
||||
MapleParty party = chr.getParty();
|
||||
if (party != null && (ownerId == chr.getId() || party.getMemberById(ownerId) != null)) {
|
||||
client.announce(MaplePacketCreator.partyPortal(this.getFrom().getId(), this.getTo().getId(), this.toPosition()));
|
||||
}
|
||||
|
||||
@@ -112,8 +114,10 @@ public class MapleDoorObject extends AbstractMapleMapObject {
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
if (from.getId() == client.getPlayer().getMapId()) {
|
||||
if (client.getPlayer().getParty() != null && (ownerId == client.getPlayer().getId() || client.getPlayer().getParty().getMemberById(ownerId) != null)) {
|
||||
MapleCharacter chr = client.getPlayer();
|
||||
if (from.getId() == chr.getMapId()) {
|
||||
MapleParty party = chr.getParty();
|
||||
if (party != null && (ownerId == chr.getId() || party.getMemberById(ownerId) != null)) {
|
||||
client.announce(MaplePacketCreator.partyPortal(999999999, 999999999, new Point(-1, -1)));
|
||||
}
|
||||
client.announce(MaplePacketCreator.removeDoor(ownerId, inTown()));
|
||||
|
||||
@@ -35,8 +35,8 @@ public class MapleDragon extends AbstractAnimatedMapleMapObject {
|
||||
super();
|
||||
this.owner = chr;
|
||||
this.setPosition(chr.getPosition());
|
||||
this.setStance(chr.getStance());
|
||||
sendSpawnData(chr.getClient());
|
||||
this.setStance(chr.getStance());
|
||||
this.sendSpawnData(chr.getClient());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,8 +45,8 @@ public class MapleDragon extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient c) {
|
||||
c.announce(MaplePacketCreator.spawnDragon(this));
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.spawnDragon(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -645,15 +645,14 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
|
||||
return mesos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapleMapObjectType getType() {
|
||||
return MapleMapObjectType.HIRED_MERCHANT;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.spawnHiredMerchantBox(this));
|
||||
|
||||
@@ -3,7 +3,6 @@ package server.maps;
|
||||
import java.awt.Point;
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import constants.ServerConstants;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
public class MapleKite extends AbstractMapleMapObject {
|
||||
|
||||
@@ -1552,9 +1552,11 @@ public class MapleMap {
|
||||
if (!monster.isAlive()) {
|
||||
return;
|
||||
}
|
||||
if (monster.getController() != null) {
|
||||
if (monster.getController().getMap() != this) {
|
||||
monster.getController().stopControllingMonster(monster);
|
||||
|
||||
MapleCharacter chrController = monster.getController();
|
||||
if (chrController != null) {
|
||||
if (chrController.getMap() != this) {
|
||||
chrController.stopControllingMonster(monster);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@@ -1574,7 +1576,7 @@ public class MapleMap {
|
||||
} finally {
|
||||
chrRLock.unlock();
|
||||
}
|
||||
if (newController != null) {// was a new controller found? (if not no one is on the map)
|
||||
if (newController != null) { // was a new controller found? (if not no one is on the map)
|
||||
if (monster.isFirstAttack()) {
|
||||
newController.controlMonster(monster, true);
|
||||
monster.setControllerHasAggro(true);
|
||||
@@ -1588,6 +1590,15 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Integer, MapleMapObject> getCopyMapObjects() {
|
||||
objectRLock.lock();
|
||||
try {
|
||||
return new HashMap<>(mapobjects);
|
||||
} finally {
|
||||
objectRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public List<MapleMapObject> getMapObjects() {
|
||||
objectRLock.lock();
|
||||
try {
|
||||
@@ -2340,14 +2351,14 @@ public class MapleMap {
|
||||
|
||||
if (onFirstUserEnter.length() != 0 && !chr.hasEntered(onFirstUserEnter, mapid) && MapScriptManager.getInstance().scriptExists(onFirstUserEnter, true)) {
|
||||
chr.enteredScript(onFirstUserEnter, mapid);
|
||||
MapScriptManager.getInstance().getMapScript(chr.getClient(), onFirstUserEnter, true);
|
||||
MapScriptManager.getInstance().runMapScript(chr.getClient(), onFirstUserEnter, true);
|
||||
}
|
||||
}
|
||||
if (onUserEnter.length() != 0) {
|
||||
if (onUserEnter.equals("cygnusTest") && (mapid < 913040000 || mapid > 913040006)) {
|
||||
chr.saveLocation("INTRO");
|
||||
}
|
||||
MapScriptManager.getInstance().getMapScript(chr.getClient(), onUserEnter, false);
|
||||
MapScriptManager.getInstance().runMapScript(chr.getClient(), onUserEnter, false);
|
||||
}
|
||||
if (FieldLimit.CANNOTUSEMOUNTS.check(fieldLimit) && chr.getBuffedValue(MapleBuffStat.MONSTER_RIDING) != null) {
|
||||
chr.cancelEffectFromBuffStat(MapleBuffStat.MONSTER_RIDING);
|
||||
@@ -2629,10 +2640,15 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
for (MapleMonster monster : chr.getControlledMonsters()) {
|
||||
monster.setController(null);
|
||||
monster.setControllerHasAggro(false);
|
||||
monster.setControllerKnowsAboutAggro(false);
|
||||
updateMonsterController(monster);
|
||||
monster.lockMonster();
|
||||
try {
|
||||
monster.setController(null);
|
||||
monster.setControllerHasAggro(false);
|
||||
monster.setControllerKnowsAboutAggro(false);
|
||||
updateMonsterController(monster);
|
||||
} finally {
|
||||
monster.unlockMonster();
|
||||
}
|
||||
}
|
||||
|
||||
chr.leaveMap();
|
||||
@@ -3042,7 +3058,7 @@ public class MapleMap {
|
||||
}
|
||||
|
||||
private static void updateMapObjectVisibility(MapleCharacter chr, MapleMapObject mo) {
|
||||
if (!chr.isMapObjectVisible(mo)) { // item entered view range
|
||||
if (!chr.isMapObjectVisible(mo)) { // object entered view range
|
||||
if (mo.getType() == MapleMapObjectType.SUMMON || mo.getPosition().distanceSq(chr.getPosition()) <= getRangedDistance()) {
|
||||
chr.addVisibleMapObject(mo);
|
||||
mo.sendSpawnData(chr.getClient());
|
||||
@@ -3055,27 +3071,22 @@ public class MapleMap {
|
||||
|
||||
public void moveMonster(MapleMonster monster, Point reportedPos) {
|
||||
monster.setPosition(reportedPos);
|
||||
chrRLock.lock();
|
||||
try {
|
||||
for (MapleCharacter chr : characters) {
|
||||
updateMapObjectVisibility(chr, monster);
|
||||
}
|
||||
} finally {
|
||||
chrRLock.unlock();
|
||||
for (MapleCharacter chr : getAllPlayers()) {
|
||||
updateMapObjectVisibility(chr, monster);
|
||||
}
|
||||
}
|
||||
|
||||
public void movePlayer(MapleCharacter player, Point newPosition) {
|
||||
player.setPosition(newPosition);
|
||||
Collection<MapleMapObject> visibleObjects = player.getVisibleMapObjects();
|
||||
|
||||
objectRLock.lock();
|
||||
try {
|
||||
Collection<MapleMapObject> visibleObjects = player.getVisibleMapObjects();
|
||||
MapleMapObject[] visibleObjectsNow = visibleObjects.toArray(new MapleMapObject[visibleObjects.size()]);
|
||||
|
||||
|
||||
Map<Integer, MapleMapObject> mapObjects = getCopyMapObjects();
|
||||
for (MapleMapObject mo : visibleObjectsNow) {
|
||||
if (mo != null) {
|
||||
if (mapobjects.get(mo.getObjectId()) == mo) {
|
||||
if (mapObjects.get(mo.getObjectId()) == mo) {
|
||||
updateMapObjectVisibility(player, mo);
|
||||
} else {
|
||||
player.removeVisibleMapObject(mo);
|
||||
@@ -3084,8 +3095,6 @@ public class MapleMap {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
objectRLock.unlock();
|
||||
}
|
||||
|
||||
for (MapleMapObject mo : getMapObjectsInRange(player.getPosition(), getRangedDistance(), rangedMapobjectTypes)) {
|
||||
|
||||
@@ -47,11 +47,12 @@ public class MapleSummon extends AbstractAnimatedMapleMapObject {
|
||||
setPosition(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSpawnData(MapleClient client) {
|
||||
if (this != null) client.announce(MaplePacketCreator.spawnSummon(this, false));
|
||||
|
||||
client.announce(MaplePacketCreator.spawnSummon(this, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDestroyData(MapleClient client) {
|
||||
client.announce(MaplePacketCreator.removeSummon(this, true));
|
||||
}
|
||||
|
||||
@@ -877,12 +877,28 @@ public class MaplePacketCreator {
|
||||
*
|
||||
* @param c The MapleClient to load characters of.
|
||||
* @param serverId The ID of the server requested.
|
||||
* @param status The charlist request result.
|
||||
* @return The character list packet.
|
||||
*
|
||||
* Possible values for <code>status</code>:
|
||||
* <br> 2: ID deleted or blocked<br>
|
||||
* <br> 3: ID deleted or blocked<br>
|
||||
* <br> 4: Incorrect password<br>
|
||||
* <br> 5: Not an registered ID<br>
|
||||
* <br> 6: Trouble logging in?<br>
|
||||
* <br> 10: Server handling too many connections<br>
|
||||
* <br> 11: Only 20 years or older<br>
|
||||
* <br> 13: Unable to log as master at IP<br>
|
||||
* <br> 14: Wrong gateway or personal info<br>
|
||||
* <br> 15: Still processing request<br>
|
||||
* <br> 16: Verify account via email<br>
|
||||
* <br> 17: Wrong gateway or personal info<br>
|
||||
* <br> 21: Verify account via email<br>
|
||||
*/
|
||||
public static byte[] getCharList(MapleClient c, int serverId) {
|
||||
public static byte[] getCharList(MapleClient c, int serverId, int status) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.CHARLIST.getValue());
|
||||
mplew.write(0);
|
||||
mplew.write(status);
|
||||
List<MapleCharacter> chars = c.loadCharacters(serverId);
|
||||
mplew.write((byte) chars.size());
|
||||
for (MapleCharacter chr : chars) {
|
||||
@@ -1425,7 +1441,6 @@ public class MaplePacketCreator {
|
||||
mplew.write(1);
|
||||
mplew.writeInt(life.getObjectId());
|
||||
return mplew.getPacket();
|
||||
//return spawnMonsterInternal(life, true, false, false, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2140,11 +2155,11 @@ public class MaplePacketCreator {
|
||||
|
||||
MapleCharacter targetChr = target.getPlayer();
|
||||
if (targetChr != null && targetChr.getPartnerId() == chr.getId()) {
|
||||
mplew.writeInt(0); // 1a pessoa: ser 0 0 implica match...
|
||||
mplew.writeInt(0); // 3a pessoa: 1 2 2 1 funciona!
|
||||
mplew.writeInt(0);
|
||||
mplew.writeInt(0);
|
||||
} else {
|
||||
mplew.writeInt(chr.getId()); // 1a pessoa: ser 0 0 implica match...
|
||||
mplew.writeInt(ring.getPartnerChrId()); // 3a pessoa: 1 2 2 1 funciona!
|
||||
mplew.writeInt(chr.getId());
|
||||
mplew.writeInt(ring.getPartnerChrId());
|
||||
}
|
||||
|
||||
mplew.writeInt(ring.getItemId());
|
||||
@@ -2386,6 +2401,18 @@ public class MaplePacketCreator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] throwGrenade(int cid, Point p, int keyDown, int skillId, int skillLevel) { // packets found thanks to GabrielSin
|
||||
MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.THROW_GRENADE.getValue());
|
||||
mplew.writeInt(cid);
|
||||
mplew.writeInt(p.x);
|
||||
mplew.writeInt(p.y);
|
||||
mplew.writeInt(keyDown);
|
||||
mplew.writeInt(skillId);
|
||||
mplew.writeInt(skillLevel);
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
// someone thought it was a good idea to handle floating point representation through packets ROFL
|
||||
private static int doubleToShortBits(double d) {
|
||||
@@ -4765,19 +4792,26 @@ public class MaplePacketCreator {
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
public static byte[] commandResponse(int cid, byte index, int animation, boolean success) {
|
||||
//AE 00 01 00 00 00 00 01 00 00
|
||||
public static byte[] petFoodResponse(int cid, byte index, boolean success, boolean balloonType) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.PET_COMMAND.getValue());
|
||||
mplew.writeInt(cid);
|
||||
mplew.write(index);
|
||||
mplew.write((animation == 1 || !success) ? 1 : 0);
|
||||
mplew.write(1);
|
||||
mplew.writeBool(success);
|
||||
mplew.writeBool(balloonType);
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
public static byte[] commandResponse(int cid, byte index, boolean talk, int animation, boolean balloonType) {
|
||||
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
|
||||
mplew.writeShort(SendOpcode.PET_COMMAND.getValue());
|
||||
mplew.writeInt(cid);
|
||||
mplew.write(index);
|
||||
mplew.write(0);
|
||||
mplew.write(animation);
|
||||
if (animation == 1) {
|
||||
mplew.write(0);
|
||||
} else {
|
||||
mplew.writeShort(success ? 1 : 0);
|
||||
}
|
||||
mplew.writeBool(!talk);
|
||||
mplew.writeBool(balloonType);
|
||||
return mplew.getPacket();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user