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:
@@ -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