Antibanish mechanics + Limited drops on map + SQL tidy-up
Added antibanish mechanics: as like other "diseases" that can be treated with some useable items, banish will be able to be recovered as well. Fixed some SQL issues introduced on the last commit, as well as lingering inexistent ids on drop data. Fixed some concurrency issues with MapleMapFactory. Set a ceiling for simultaneous items available per map, where old ones are promptly discarded. Patched MWLB attack block for higher level GMs.
This commit is contained in:
@@ -294,6 +294,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private short extraRecInterval;
|
||||
private int targetHpBarHash = 0;
|
||||
private long targetHpBarTime = 0;
|
||||
private int banishMap = -1;
|
||||
private int banishSp = -1;
|
||||
private long banishTime = 0;
|
||||
|
||||
private MapleCharacter() {
|
||||
useCS = false;
|
||||
@@ -1192,10 +1195,42 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
if (getEventInstance() != null) getEventInstance().changedMap(this, map);
|
||||
}
|
||||
|
||||
public boolean canRecoverLastBanish() {
|
||||
return System.currentTimeMillis() - this.banishTime < 5 * 60 * 1000;
|
||||
}
|
||||
|
||||
public Pair<Integer, Integer> getLastBanishData() {
|
||||
return new Pair<>(this.banishMap, this.banishSp);
|
||||
}
|
||||
|
||||
private void clearBanishPlayerData() {
|
||||
this.banishMap = -1;
|
||||
this.banishSp = -1;
|
||||
this.banishTime = 0;
|
||||
}
|
||||
|
||||
private void setBanishPlayerData(int banishMap, int banishSp, long banishTime) {
|
||||
this.banishMap = banishMap;
|
||||
this.banishSp = banishSp;
|
||||
this.banishTime = banishTime;
|
||||
}
|
||||
|
||||
public void changeMapBanish(int mapid, String portal, String msg) {
|
||||
if(ServerConstants.USE_SPIKES_AVOID_BANISH) {
|
||||
for(Item it: this.getInventory(MapleInventoryType.EQUIPPED).list()) {
|
||||
if((it.getFlag() & ItemConstants.SPIKES) == ItemConstants.SPIKES) return;
|
||||
}
|
||||
}
|
||||
|
||||
int banMap = this.getMapId();
|
||||
int banSp = this.getMap().findClosestPlayerSpawnpoint(this.getPosition()).getId();
|
||||
long banTime = System.currentTimeMillis();
|
||||
|
||||
dropMessage(5, msg);
|
||||
MapleMap map_ = client.getChannelServer().getMapFactory().getMap(mapid);
|
||||
changeMap(map_, map_.getPortal(portal));
|
||||
|
||||
setBanishPlayerData(banMap, banSp, banTime);
|
||||
}
|
||||
|
||||
public void changeMap(int map) {
|
||||
@@ -1298,6 +1333,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
private void changeMapInternal(final MapleMap to, final Point pos, final byte[] warpPacket) {
|
||||
if(!canWarpMap) return;
|
||||
|
||||
this.clearBanishPlayerData();
|
||||
this.closePlayerInteractions();
|
||||
this.resetPlayerAggro();
|
||||
|
||||
@@ -1468,19 +1504,13 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
if (!mapitem.isPlayerDrop() || mapitem.getDropper().getObjectId() == client.getPlayer().getObjectId()) {
|
||||
if(mapitem.getMeso() > 0) {
|
||||
this.gainMeso(mapitem.getMeso(), true, true, false);
|
||||
this.getMap().broadcastMessage(pickupPacket, mapitem.getPosition());
|
||||
this.getMap().removeMapObject(ob);
|
||||
mapitem.setPickedUp(true);
|
||||
this.getMap().pickItemDrop(pickupPacket, mapitem);
|
||||
} else if(mapitem.getItemId() == 4031865 || mapitem.getItemId() == 4031866) {
|
||||
// Add NX to account, show effect and make item disappear
|
||||
this.getCashShop().gainCash(1, mapitem.getItemId() == 4031865 ? 100 : 250);
|
||||
this.getMap().broadcastMessage(pickupPacket, mapitem.getPosition());
|
||||
this.getMap().removeMapObject(ob);
|
||||
mapitem.setPickedUp(true);
|
||||
this.getMap().pickItemDrop(pickupPacket, mapitem);
|
||||
} else if (MapleInventoryManipulator.addFromDrop(client, mapitem.getItem(), true)) {
|
||||
this.getMap().broadcastMessage(pickupPacket, mapitem.getPosition());
|
||||
this.getMap().removeMapObject(ob);
|
||||
mapitem.setPickedUp(true);
|
||||
this.getMap().pickItemDrop(pickupPacket, mapitem);
|
||||
} else {
|
||||
client.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
@@ -1558,9 +1588,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
client.announce(MaplePacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
mapitem.setPickedUp(true);
|
||||
this.getMap().broadcastMessage(pickupPacket, mapitem.getPosition());
|
||||
this.getMap().removeMapObject(ob);
|
||||
|
||||
this.getMap().pickItemDrop(pickupPacket, mapitem);
|
||||
}
|
||||
} else if(!hasSpaceInventory) {
|
||||
client.announce(MaplePacketCreator.getInventoryFull());
|
||||
@@ -5473,13 +5502,13 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
|
||||
}
|
||||
psf.close();
|
||||
ps = con.prepareStatement("UPDATE accounts SET gm = ? WHERE id = ?");
|
||||
ps.setInt(1, gmLevel);
|
||||
ps.setInt(1, gmLevel > 1 ? 1 : 0);
|
||||
ps.setInt(2, client.getAccID());
|
||||
ps.executeUpdate();
|
||||
ps.close();
|
||||
|
||||
con.commit();
|
||||
con.setAutoCommit(true);
|
||||
con.setAutoCommit(true);
|
||||
|
||||
if (cashshop != null) {
|
||||
cashshop.save(con);
|
||||
|
||||
@@ -1961,9 +1961,8 @@ public class Commands {
|
||||
} else {
|
||||
MapleInventoryManipulator.addFromDrop(c, mapItem.getItem(), true);
|
||||
}
|
||||
mapItem.setPickedUp(true);
|
||||
player.getMap().removeMapObject(item);
|
||||
player.getMap().broadcastMessage(MaplePacketCreator.removeItemFromMap(mapItem.getObjectId(), 2, player.getId()), mapItem.getPosition());
|
||||
|
||||
player.getMap().pickItemDrop(MaplePacketCreator.removeItemFromMap(mapItem.getObjectId(), 2, player.getId()), mapItem);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public class ServerConstants {
|
||||
public static boolean SHUTDOWNHOOK;
|
||||
|
||||
//Gameplay Configuration
|
||||
public static final boolean USE_CUSTOM_KEYSET = true;
|
||||
public static final boolean USE_CUSTOM_KEYSET = true; //Enables auto-setup of the MapleSolaxiaV2's custom keybindings when creating characters.
|
||||
public static final boolean USE_MAXRANGE_ECHO_OF_HERO = true;
|
||||
public static final boolean USE_MAXRANGE = true; //Will send and receive packets from all events of a map, rather than those of only view range.
|
||||
public static final boolean USE_DEBUG = false; //Will enable some text prints on the client, oriented for debugging purposes.
|
||||
@@ -56,7 +56,10 @@ public class ServerConstants {
|
||||
public static final long BLOCK_NPC_RACE_CONDT = (long)(0.5 * 1000); //Time the player client must wait before reopening a conversation with an NPC.
|
||||
public static final long PET_LOOT_UPON_ATTACK = (long)(0.7 * 1000); //Time the pet must wait before trying to pick items up.
|
||||
|
||||
public static final int ITEM_EXPIRE_TIME = 3 * 60 * 1000; //Time before items start disappearing. Recommended to be set up to 3 minutes.
|
||||
//Dangling Items Configuration
|
||||
public static final int ITEM_EXPIRE_TIME = 3 * 60 * 1000; //Time before items start disappearing. Recommended to be set up to 3 minutes.
|
||||
public static final int ITEM_MONITOR_TIME = 5 * 60 * 1000; //Interval between item monitoring task on maps, which checks for dangling item objects on the map item history.
|
||||
public static final int ITEM_LIMIT_ON_MAP = 777; //Max number of items allowed on a map.
|
||||
|
||||
//Some Gameplay Enhancing Configuration
|
||||
public static final boolean USE_PERFECT_SCROLLING = true; //Scrolls doesn't use slots upon failure.
|
||||
@@ -70,6 +73,7 @@ public class ServerConstants {
|
||||
public static final boolean USE_STACK_COUPON_RATES = true; //Multiple coupons effects builds up together.
|
||||
public static final boolean USE_EQUIPMNT_LVLUP_SLOTS = true;//Equips can upgrade slots at level up.
|
||||
public static final boolean USE_EQUIPMNT_LVLUP_POWER = true;//Enable more powerful stats upgrades at equip level up.
|
||||
public static final boolean USE_SPIKES_AVOID_BANISH = true; //Shoes equipped with spikes blocks mobs from banishing wearer.
|
||||
public static final boolean USE_CHAIR_EXTRAHEAL = true; //Enable map chairs to futher recover player`s HP and MP.
|
||||
public static final int MAX_EQUIPMNT_LVLUP_STAT_GAIN = 10000; //Max stat upgrade an equipment can have on a levelup.
|
||||
public static final int MAX_EQUIPMNT_STAT = 32767; //Max stat on an equipment by leveling up.
|
||||
|
||||
@@ -278,7 +278,7 @@ public class Server implements Runnable {
|
||||
System.out.println("Skills loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds");
|
||||
|
||||
timeToTake = System.currentTimeMillis();
|
||||
MapleItemInformationProvider.getInstance().getAllItems();
|
||||
//MapleItemInformationProvider.getInstance().getAllItems(); //unused, rofl
|
||||
|
||||
CashItemFactory.getSpecialCashItems();
|
||||
System.out.println("Items loaded in " + ((System.currentTimeMillis() - timeToTake) / 1000.0) + " seconds");
|
||||
|
||||
@@ -216,9 +216,7 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
map.removeMapObject(mapitem);
|
||||
map.broadcastMessage(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 4, 0), mapitem.getPosition());
|
||||
mapitem.setPickedUp(true);
|
||||
map.pickItemDrop(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 4, 0), mapitem);
|
||||
}
|
||||
}, delay);
|
||||
delay += 100;
|
||||
|
||||
@@ -45,14 +45,16 @@ public final class KeymapChangeHandler extends AbstractMaplePacketHandler {
|
||||
int action = slea.readInt();
|
||||
|
||||
Skill skill = SkillFactory.getSkill(action);
|
||||
boolean isBanndedSkill = false;
|
||||
boolean isBanndedSkill;
|
||||
if (skill != null) {
|
||||
isBanndedSkill = GameConstants.bannedBindSkills(skill.getId());
|
||||
if (isBanndedSkill || (!c.getPlayer().isGM() && GameConstants.isGMSkills(skill.getId())) || (!GameConstants.isInJobTree(skill.getId(), c.getPlayer().getJob().getId()) && !c.getPlayer().isGM())) { //for those skills are are "technically" in the beginner tab, like bamboo rain in Dojo or skills you find in PYPQ
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit keymapping.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use skill " + skill.getId() + "\r\n");
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
//AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit keymapping.");
|
||||
//FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use skill " + skill.getId() + "\r\n");
|
||||
//c.disconnect(true, false);
|
||||
//return;
|
||||
|
||||
continue; // fk that
|
||||
}
|
||||
/* if (c.getPlayer().getSkillLevel(skill) < 1) { HOW WOULD A SKILL EVEN BE AVAILABLE TO KEYBINDING
|
||||
continue; IF THERE IS NOT EVEN A SINGLE POINT USED INTO IT??
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
*/
|
||||
package net.server.channel.handlers;
|
||||
|
||||
import client.MapleCharacter;
|
||||
import client.MapleClient;
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import server.life.MapleMonster;
|
||||
import server.life.MobSkill;
|
||||
@@ -38,6 +40,8 @@ import tools.data.input.SeekableLittleEndianAccessor;
|
||||
public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
List<MapleCharacter> banishPlayers = new ArrayList<>();
|
||||
|
||||
int objectid = slea.readInt();
|
||||
short moveid = slea.readShort();
|
||||
MapleMapObject mmo = c.getPlayer().getMap().getMapObject(objectid);
|
||||
@@ -66,7 +70,7 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
if ((skill_1 >= 100 && skill_1 <= 200) && monster.hasSkill(skill_1, skill_2)) {
|
||||
MobSkill skillData = MobSkillFactory.getMobSkill(skill_1, skill_2);
|
||||
if (skillData != null && monster.canUseSkill(skillData)) {
|
||||
skillData.applyEffect(c.getPlayer(), monster, true);
|
||||
skillData.applyEffect(c.getPlayer(), monster, true, banishPlayers);
|
||||
}
|
||||
}
|
||||
slea.readByte();
|
||||
@@ -99,5 +103,9 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
updatePosition(res, monster, -1);
|
||||
c.getPlayer().getMap().moveMonster(monster, monster.getPosition());
|
||||
}
|
||||
|
||||
for (MapleCharacter chr : banishPlayers) {
|
||||
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import constants.skills.Corsair;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.AbstractMaplePacketHandler;
|
||||
@@ -58,6 +59,8 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
List<MapleCharacter> banishPlayers = new ArrayList<>();
|
||||
|
||||
MapleCharacter player = c.getPlayer();
|
||||
slea.readInt();
|
||||
byte damagefrom = slea.readByte();
|
||||
@@ -125,28 +128,27 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
||||
mpattack += attackInfo.getMpBurn();
|
||||
MobSkill skill = MobSkillFactory.getMobSkill(attackInfo.getDiseaseSkill(), attackInfo.getDiseaseLevel());
|
||||
if (skill != null && damage > 0) {
|
||||
skill.applyEffect(player, attacker, false);
|
||||
}
|
||||
if (attacker != null) {
|
||||
attacker.setMp(attacker.getMp() - attackInfo.getMpCon());
|
||||
if (player.getBuffedValue(MapleBuffStat.MANA_REFLECTION) != null && damage > 0 && !attacker.isBoss()) {
|
||||
int jobid = player.getJob().getId();
|
||||
if (jobid == 212 || jobid == 222 || jobid == 232) {
|
||||
int id = jobid * 10000 + 1002;
|
||||
Skill manaReflectSkill = SkillFactory.getSkill(id);
|
||||
if (player.isBuffFrom(MapleBuffStat.MANA_REFLECTION, manaReflectSkill) && player.getSkillLevel(manaReflectSkill) > 0 && manaReflectSkill.getEffect(player.getSkillLevel(manaReflectSkill)).makeChanceResult()) {
|
||||
int bouncedamage = (damage * manaReflectSkill.getEffect(player.getSkillLevel(manaReflectSkill)).getX() / 100);
|
||||
if (bouncedamage > attacker.getMaxHp() / 5) {
|
||||
bouncedamage = attacker.getMaxHp() / 5;
|
||||
}
|
||||
map.damageMonster(player, attacker, bouncedamage);
|
||||
map.broadcastMessage(player, MaplePacketCreator.damageMonster(oid, bouncedamage), true);
|
||||
player.getClient().announce(MaplePacketCreator.showOwnBuffEffect(id, 5));
|
||||
map.broadcastMessage(player, MaplePacketCreator.showBuffeffect(player.getId(), id, 5), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
skill.applyEffect(player, attacker, false, banishPlayers);
|
||||
}
|
||||
|
||||
attacker.setMp(attacker.getMp() - attackInfo.getMpCon());
|
||||
if (player.getBuffedValue(MapleBuffStat.MANA_REFLECTION) != null && damage > 0 && !attacker.isBoss()) {
|
||||
int jobid = player.getJob().getId();
|
||||
if (jobid == 212 || jobid == 222 || jobid == 232) {
|
||||
int id = jobid * 10000 + 1002;
|
||||
Skill manaReflectSkill = SkillFactory.getSkill(id);
|
||||
if (player.isBuffFrom(MapleBuffStat.MANA_REFLECTION, manaReflectSkill) && player.getSkillLevel(manaReflectSkill) > 0 && manaReflectSkill.getEffect(player.getSkillLevel(manaReflectSkill)).makeChanceResult()) {
|
||||
int bouncedamage = (damage * manaReflectSkill.getEffect(player.getSkillLevel(manaReflectSkill)).getX() / 100);
|
||||
if (bouncedamage > attacker.getMaxHp() / 5) {
|
||||
bouncedamage = attacker.getMaxHp() / 5;
|
||||
}
|
||||
map.damageMonster(player, attacker, bouncedamage);
|
||||
map.broadcastMessage(player, MaplePacketCreator.damageMonster(oid, bouncedamage), true);
|
||||
player.getClient().announce(MaplePacketCreator.showOwnBuffEffect(id, 5));
|
||||
map.broadcastMessage(player, MaplePacketCreator.showBuffeffect(player.getId(), id, 5), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (damage == -1) {
|
||||
@@ -234,5 +236,9 @@ public final class TakeDamageHandler extends AbstractMaplePacketHandler {
|
||||
player.setDojoEnergy(player.isGM() ? 300 : player.getDojoEnergy() < 300 ? player.getDojoEnergy() + 1 : 0); //Fking gm's
|
||||
player.getClient().announce(MaplePacketCreator.getEnergy("energy", player.getDojoEnergy()));
|
||||
}
|
||||
|
||||
for (MapleCharacter chr : banishPlayers) { // chill, if this list ever gets non-empty an attacker does exist, trust me :)
|
||||
chr.changeMapBanish(attacker.getBanish().getMap(), attacker.getBanish().getPortal(), attacker.getBanish().getMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,12 +66,21 @@ public final class UseItemHandler extends AbstractMaplePacketHandler {
|
||||
remove(c, slot);
|
||||
return;
|
||||
}
|
||||
if (isTownScroll(itemId)) {
|
||||
else if (isTownScroll(itemId)) {
|
||||
if (ii.getItemEffect(toUse.getItemId()).applyTo(c.getPlayer())) {
|
||||
remove(c, slot);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (isAntibanishScroll(itemId)) {
|
||||
if (ii.getItemEffect(toUse.getItemId()).applyTo(c.getPlayer())) {
|
||||
remove(c, slot);
|
||||
} else {
|
||||
c.getPlayer().dropMessage(5, "You cannot recover from a banish state at the moment.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
remove(c, slot);
|
||||
|
||||
ii.getItemEffect(toUse.getItemId()).applyTo(c.getPlayer());
|
||||
@@ -84,7 +93,11 @@ public final class UseItemHandler extends AbstractMaplePacketHandler {
|
||||
c.announce(MaplePacketCreator.enableActions());
|
||||
}
|
||||
|
||||
private boolean isTownScroll(int itemId) {
|
||||
private static boolean isTownScroll(int itemId) {
|
||||
return itemId >= 2030000 && itemId < 2030021;
|
||||
}
|
||||
|
||||
private static boolean isAntibanishScroll(int itemId) {
|
||||
return itemId == 2030100;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,16 +796,30 @@ public class MapleStatEffect {
|
||||
if (moveTo != -1) {
|
||||
if (moveTo != applyto.getMapId()) {
|
||||
MapleMap target;
|
||||
MaplePortal pt;
|
||||
|
||||
if (moveTo == 999999999) {
|
||||
target = applyto.getMap().getReturnMap();
|
||||
if(sourceid != 2030100) {
|
||||
target = applyto.getMap().getReturnMap();
|
||||
pt = target.getRandomPlayerSpawnpoint();
|
||||
} else {
|
||||
if(!applyto.canRecoverLastBanish()) return false;
|
||||
|
||||
Pair<Integer, Integer> lastBanishInfo = applyto.getLastBanishData();
|
||||
target = applyto.getWarpMap(lastBanishInfo.getLeft());
|
||||
pt = target.getPortal(lastBanishInfo.getRight());
|
||||
}
|
||||
} else {
|
||||
target = applyto.getClient().getWorldServer().getChannel(applyto.getClient().getChannel()).getMapFactory().getMap(moveTo);
|
||||
int targetid = target.getId() / 10000000;
|
||||
if (targetid != 60 && applyto.getMapId() / 10000000 != 61 && targetid != applyto.getMapId() / 10000000 && targetid != 21 && targetid != 20 && targetid != 12 && (applyto.getMapId() / 10000000 != 10 && applyto.getMapId() / 10000000 != 12)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pt = target.getRandomPlayerSpawnpoint();
|
||||
}
|
||||
applyto.changeMap(target, target.getRandomPlayerSpawnpoint());
|
||||
|
||||
applyto.changeMap(target, pt);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class MobSkill {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public void applyEffect(MapleCharacter player, MapleMonster monster, boolean skill) {
|
||||
public void applyEffect(MapleCharacter player, MapleMonster monster, boolean skill, List<MapleCharacter> banishPlayers) {
|
||||
MapleDisease disease = null;
|
||||
Map<MonsterStatus, Integer> stats = new ArrayMap<MonsterStatus, Integer>();
|
||||
List<Integer> reflection = new LinkedList<Integer>();
|
||||
@@ -174,10 +174,10 @@ public class MobSkill {
|
||||
case 129: // Banish
|
||||
if (lt != null && rb != null && skill) {
|
||||
for (MapleCharacter chr : getPlayersInRange(monster, player)) {
|
||||
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
banishPlayers.add(chr);
|
||||
}
|
||||
} else {
|
||||
player.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
banishPlayers.add(player);
|
||||
}
|
||||
break;
|
||||
case 131: // Mist
|
||||
|
||||
@@ -54,6 +54,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
import java.lang.ref.WeakReference;
|
||||
import net.server.Server;
|
||||
import net.server.channel.Channel;
|
||||
import scripting.map.MapScriptManager;
|
||||
@@ -90,10 +91,12 @@ public class MapleMap {
|
||||
private Collection<SpawnPoint> monsterSpawn = Collections.synchronizedList(new LinkedList<SpawnPoint>());
|
||||
private Collection<SpawnPoint> allMonsterSpawn = Collections.synchronizedList(new LinkedList<SpawnPoint>());
|
||||
private AtomicInteger spawnedMonstersOnMap = new AtomicInteger(0);
|
||||
private AtomicInteger droppedItemCount = new AtomicInteger(0);
|
||||
private Collection<MapleCharacter> characters = new LinkedHashSet<>();
|
||||
private Map<Integer, MaplePortal> portals = new HashMap<>();
|
||||
private Map<Integer, Integer> backgroundTypes = new HashMap<>();
|
||||
private Map<String, Integer> environment = new LinkedHashMap<>();
|
||||
private LinkedList<WeakReference<MapleMapObject>> registeredDrops = new LinkedList<>();
|
||||
private List<Rectangle> areas = new ArrayList<>();
|
||||
private MapleFootholdTree footholds = null;
|
||||
private int mapid;
|
||||
@@ -123,6 +126,8 @@ public class MapleMap {
|
||||
private int fieldLimit = 0;
|
||||
private int mobCapacity = -1;
|
||||
private ScheduledFuture<?> mapMonitor = null;
|
||||
private ScheduledFuture<?> itemMonitor = null;
|
||||
private short itemMonitorTimeout;
|
||||
private Pair<Integer, String> timeMob = null;
|
||||
private short mobInterval = 5000;
|
||||
private boolean allowSummons = true; // All maps should have this true at the beginning
|
||||
@@ -556,6 +561,98 @@ public class MapleMap {
|
||||
}
|
||||
}
|
||||
|
||||
private void stopItemMonitor() {
|
||||
chrWLock.lock();
|
||||
try {
|
||||
itemMonitor.cancel(false);
|
||||
itemMonitor = null;
|
||||
} finally {
|
||||
chrWLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanItemMonitor() {
|
||||
objectWLock.lock();
|
||||
try {
|
||||
registeredDrops.removeAll(Collections.singleton(null));
|
||||
} finally {
|
||||
objectWLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void startItemMonitor() {
|
||||
chrWLock.lock();
|
||||
try {
|
||||
itemMonitor = TimerManager.getInstance().register(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getCharacters().isEmpty()) {
|
||||
if(itemMonitorTimeout == 0) {
|
||||
stopItemMonitor();
|
||||
return;
|
||||
} else {
|
||||
itemMonitorTimeout--;
|
||||
}
|
||||
} else {
|
||||
itemMonitorTimeout = 1;
|
||||
}
|
||||
|
||||
if(!registeredDrops.isEmpty()) cleanItemMonitor();
|
||||
}
|
||||
}, ServerConstants.ITEM_MONITOR_TIME, ServerConstants.ITEM_MONITOR_TIME);
|
||||
|
||||
itemMonitorTimeout = 1;
|
||||
} finally {
|
||||
chrWLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasItemMonitor() {
|
||||
chrRLock.lock();
|
||||
try {
|
||||
return itemMonitor != null;
|
||||
} finally {
|
||||
chrRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void registerItemDrop(MapleMapItem mdrop) {
|
||||
if(droppedItemCount.get() >= ServerConstants.ITEM_LIMIT_ON_MAP) {
|
||||
MapleMapObject mapobj;
|
||||
|
||||
objectWLock.lock();
|
||||
try {
|
||||
mapobj = registeredDrops.remove(0).get();
|
||||
while(mapobj == null) {
|
||||
mapobj = registeredDrops.remove(0).get();
|
||||
}
|
||||
} finally {
|
||||
objectWLock.unlock();
|
||||
}
|
||||
|
||||
makeDisappearItemFromMap(mapobj);
|
||||
}
|
||||
|
||||
if(!everlast) TimerManager.getInstance().schedule(new ExpireMapItemJob(mdrop), ServerConstants.ITEM_EXPIRE_TIME);
|
||||
|
||||
objectWLock.lock();
|
||||
try {
|
||||
registeredDrops.add(new WeakReference<>((MapleMapObject) mdrop));
|
||||
} finally {
|
||||
objectWLock.unlock();
|
||||
}
|
||||
|
||||
droppedItemCount.incrementAndGet();
|
||||
}
|
||||
|
||||
public void pickItemDrop(byte[] pickupPacket, MapleMapItem mdrop) {
|
||||
broadcastMessage(pickupPacket, mdrop.getPosition());
|
||||
|
||||
this.removeMapObject(mdrop);
|
||||
mdrop.setPickedUp(true);
|
||||
droppedItemCount.decrementAndGet();
|
||||
}
|
||||
|
||||
private void spawnDrop(final Item idrop, final Point dropPos, final MapleMonster mob, final MapleCharacter chr, final byte droptype, final short questid) {
|
||||
final MapleMapItem mdrop = new MapleMapItem(idrop, dropPos, mob, chr, droptype, false, questid);
|
||||
mdrop.setDropTime(System.currentTimeMillis());
|
||||
@@ -568,7 +665,7 @@ public class MapleMap {
|
||||
}
|
||||
}, null);
|
||||
|
||||
TimerManager.getInstance().schedule(new ExpireMapItemJob(mdrop), ServerConstants.ITEM_EXPIRE_TIME);
|
||||
registerItemDrop(mdrop);
|
||||
activateItemReactors(mdrop, chr.getClient());
|
||||
}
|
||||
|
||||
@@ -584,7 +681,7 @@ public class MapleMap {
|
||||
}
|
||||
}, null);
|
||||
|
||||
TimerManager.getInstance().schedule(new ExpireMapItemJob(mdrop), ServerConstants.ITEM_EXPIRE_TIME);
|
||||
registerItemDrop(mdrop);
|
||||
}
|
||||
|
||||
public final void disappearingItemDrop(final MapleMapObject dropper, final MapleCharacter owner, final Item item, final Point pos) {
|
||||
@@ -1569,21 +1666,19 @@ public class MapleMap {
|
||||
|
||||
public final void spawnItemDrop(final MapleMapObject dropper, final MapleCharacter owner, final Item item, Point pos, final byte dropType, final boolean playerDrop) {
|
||||
final Point droppos = calcDropPos(pos, pos);
|
||||
final MapleMapItem drop = new MapleMapItem(item, droppos, dropper, owner, dropType, playerDrop);
|
||||
drop.setDropTime(System.currentTimeMillis());
|
||||
final MapleMapItem mdrop = new MapleMapItem(item, droppos, dropper, owner, dropType, playerDrop);
|
||||
mdrop.setDropTime(System.currentTimeMillis());
|
||||
|
||||
spawnAndAddRangedMapObject(drop, new DelayedPacketCreation() {
|
||||
spawnAndAddRangedMapObject(mdrop, new DelayedPacketCreation() {
|
||||
@Override
|
||||
public void sendPackets(MapleClient c) {
|
||||
c.announce(MaplePacketCreator.dropItemFromMapObject(drop, dropper.getPosition(), droppos, (byte) 1));
|
||||
c.announce(MaplePacketCreator.dropItemFromMapObject(mdrop, dropper.getPosition(), droppos, (byte) 1));
|
||||
}
|
||||
}, null);
|
||||
broadcastMessage(MaplePacketCreator.dropItemFromMapObject(drop, dropper.getPosition(), droppos, (byte) 0));
|
||||
broadcastMessage(MaplePacketCreator.dropItemFromMapObject(mdrop, dropper.getPosition(), droppos, (byte) 0));
|
||||
|
||||
if (!everlast) {
|
||||
TimerManager.getInstance().schedule(new ExpireMapItemJob(drop), ServerConstants.ITEM_EXPIRE_TIME);
|
||||
activateItemReactors(drop, owner.getClient());
|
||||
}
|
||||
registerItemDrop(mdrop);
|
||||
activateItemReactors(mdrop, owner.getClient());
|
||||
}
|
||||
|
||||
public final void spawnItemDropList(List<Integer> list, final MapleMapObject dropper, final MapleCharacter owner, Point pos) {
|
||||
@@ -1677,8 +1772,12 @@ public class MapleMap {
|
||||
chrWLock.unlock();
|
||||
}
|
||||
chr.setMapId(mapid);
|
||||
if (onFirstUserEnter.length() != 0 && !chr.hasEntered(onFirstUserEnter, mapid) && MapScriptManager.getInstance().scriptExists(onFirstUserEnter, true)) {
|
||||
if (countPlayers() <= 1) {
|
||||
|
||||
itemMonitorTimeout = 1;
|
||||
if (getCharacters().size() <= 1) {
|
||||
if(!hasItemMonitor()) startItemMonitor();
|
||||
|
||||
if (onFirstUserEnter.length() != 0 && !chr.hasEntered(onFirstUserEnter, mapid) && MapScriptManager.getInstance().scriptExists(onFirstUserEnter, true)) {
|
||||
chr.enteredScript(onFirstUserEnter, mapid);
|
||||
MapScriptManager.getInstance().getMapScript(chr.getClient(), onFirstUserEnter, true);
|
||||
}
|
||||
@@ -2289,10 +2388,11 @@ public class MapleMap {
|
||||
public void movePlayer(MapleCharacter player, Point newPosition) {
|
||||
player.setPosition(newPosition);
|
||||
Collection<MapleMapObject> visibleObjects = player.getVisibleMapObjects();
|
||||
MapleMapObject[] visibleObjectsNow = visibleObjects.toArray(new MapleMapObject[visibleObjects.size()]);
|
||||
|
||||
objectRLock.lock();
|
||||
try {
|
||||
MapleMapObject[] visibleObjectsNow = visibleObjects.toArray(new MapleMapObject[visibleObjects.size()]);
|
||||
|
||||
for (MapleMapObject mo : visibleObjectsNow) {
|
||||
if (mo != null) {
|
||||
if (mapobjects.get(mo.getObjectId()) == mo) {
|
||||
@@ -2453,11 +2553,9 @@ public class MapleMap {
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
MapleMap.this.broadcastMessage(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 0, 0), mapitem.getPosition());
|
||||
mapitem.setPickedUp(true);
|
||||
MapleMap.this.pickItemDrop(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 0, 0), mapitem);
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
MapleMap.this.removeMapObject(mapitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +25,15 @@ import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataTool;
|
||||
@@ -46,6 +51,8 @@ public class MapleMapFactory {
|
||||
private MapleData nameData;
|
||||
private EventInstanceManager event;
|
||||
private Map<Integer, MapleMap> maps = new HashMap<>();
|
||||
private ReadLock mapsRLock;
|
||||
private WriteLock mapsWLock;
|
||||
private int channel, world;
|
||||
|
||||
public MapleMapFactory(EventInstanceManager eim, MapleDataProvider source, MapleDataProvider stringSource, int world, int channel) {
|
||||
@@ -54,14 +61,32 @@ public class MapleMapFactory {
|
||||
this.world = world;
|
||||
this.channel = channel;
|
||||
this.event = eim;
|
||||
|
||||
ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();
|
||||
this.mapsRLock = rrwl.readLock();
|
||||
this.mapsWLock = rrwl.writeLock();
|
||||
}
|
||||
|
||||
public MapleMap getMap(int mapid) {
|
||||
Integer omapid = Integer.valueOf(mapid);
|
||||
MapleMap map = maps.get(omapid);
|
||||
MapleMap map;
|
||||
|
||||
mapsRLock.lock();
|
||||
try {
|
||||
map = maps.get(omapid);
|
||||
} finally {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
|
||||
if (map == null) {
|
||||
synchronized (this) {
|
||||
map = maps.get(omapid);
|
||||
mapsRLock.lock();
|
||||
try {
|
||||
map = maps.get(omapid);
|
||||
} finally {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
|
||||
if (map != null) {
|
||||
return map;
|
||||
}
|
||||
@@ -224,14 +249,24 @@ public class MapleMapFactory {
|
||||
}
|
||||
map.setBackgroundTypes(backTypes);
|
||||
|
||||
maps.put(omapid, map);
|
||||
mapsWLock.lock();
|
||||
try {
|
||||
maps.put(omapid, map);
|
||||
} finally {
|
||||
mapsWLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public boolean isMapLoaded(int mapId) {
|
||||
return maps.containsKey(mapId);
|
||||
mapsRLock.lock();
|
||||
try {
|
||||
return maps.containsKey(mapId);
|
||||
} finally {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private AbstractLoadedMapleLife loadLife(MapleData life, String id, String type) {
|
||||
@@ -318,11 +353,25 @@ public class MapleMapFactory {
|
||||
}
|
||||
|
||||
public Map<Integer, MapleMap> getMaps() {
|
||||
return maps;
|
||||
mapsRLock.lock();
|
||||
try {
|
||||
return Collections.unmodifiableMap(maps);
|
||||
} finally {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
for(MapleMap map: maps.values()) map.setEventInstance(null);
|
||||
Collection<MapleMap> mapValues;
|
||||
|
||||
mapsRLock.lock();
|
||||
try {
|
||||
mapValues = maps.values();
|
||||
} finally {
|
||||
mapsRLock.unlock();
|
||||
}
|
||||
|
||||
for(MapleMap map: mapValues) map.setEventInstance(null);
|
||||
this.event = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public class MapleMapItem extends AbstractMapleMapObject {
|
||||
}
|
||||
|
||||
public void setDropTime(long time) {
|
||||
this.dropTime = time;
|
||||
this.dropTime = time;
|
||||
}
|
||||
|
||||
public byte getDropType() {
|
||||
|
||||
Reference in New Issue
Block a user