diff --git a/config.yaml b/config.yaml index c6d0e0d6a3..4d7ec5d6d5 100644 --- a/config.yaml +++ b/config.yaml @@ -332,7 +332,8 @@ server: ITEM_EXPIRE_CHECK: 10000 # (10 * 10000) Interval between item expiring tasks on maps, which checks and makes disappear expired items. ITEM_LIMIT_ON_MAP: 200 #Max number of items allowed on a map. MAP_VISITED_SIZE: 5 #Max length for last mapids visited by a player. This is used to recover and update drops on these maps accordingly with player actions. - MAP_DAMAGE_OVERTIME_INTERVAL: 5000 #Interval in milliseconds between map environment damage (e.g. El Nath and Aqua Road surrondings). + MAP_DAMAGE_OVERTIME_INTERVAL: 2500 #Interval in milliseconds between map environment damage (e.g. El Nath and Aqua Road surrondings). + MAP_DAMAGE_OVERTIME_COUNT: 2 #Channel Mob Disease Monitor Configuration MOB_STATUS_MONITOR_PROC: 200 #Frequency in milliseconds between each proc on the mob disease monitor schedule. diff --git a/src/main/java/client/Character.java b/src/main/java/client/Character.java index 1f8615b7af..c5cd8faf57 100644 --- a/src/main/java/client/Character.java +++ b/src/main/java/client/Character.java @@ -251,7 +251,6 @@ public class Character extends AbstractCharacterObject { private boolean loggedIn = false; private boolean useCS; //chaos scroll upon crafting item. private long npcCd; - private long lastHpDec = 0; private int newWarpMap = -1; private boolean canWarpMap = true; //only one "warp" must be used per call, and this will define the right one. private int canWarpCounter = 0; //counts how many times "inner warps" have been called. @@ -1720,10 +1719,6 @@ public class Character extends AbstractCharacterObject { Character.this.getParty().setEnemy(k); } silentPartyUpdateInternal(getParty()); // EIM script calls inside - - if (getMap().getHPDec() > 0) { - resetHpDecreaseTask(); - } } else { log.warn("Chr {} got stuck when moving to map {}", getName(), map.getId()); client.disconnect(true, false); // thanks BHB for noticing a player storage stuck case here @@ -2767,31 +2762,12 @@ public class Character extends AbstractCharacterObject { } } - private void doHurtHp() { + public void doHurtHp() { if (!(this.getInventory(InventoryType.EQUIPPED).findById(getMap().getHPDecProtect()) != null || buffMapProtection())) { addHP(-getMap().getHPDec()); - lastHpDec = Server.getInstance().getCurrentTime(); } } - private void startHpDecreaseTask(long lastHpTask) { - hpDecreaseTask = TimerManager.getInstance().register(new Runnable() { - @Override - public void run() { - doHurtHp(); - } - }, YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL, YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL - lastHpTask); - } - - public void resetHpDecreaseTask() { - if (hpDecreaseTask != null) { - hpDecreaseTask.cancel(false); - } - - long lastHpTask = Server.getInstance().getCurrentTime() - lastHpDec; - startHpDecreaseTask((lastHpTask > YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL) ? YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL : lastHpTask); - } - public void dropMessage(String message) { dropMessage(0, message); } diff --git a/src/main/java/client/Client.java b/src/main/java/client/Client.java index 5ed36fbcb7..46224343f7 100644 --- a/src/main/java/client/Client.java +++ b/src/main/java/client/Client.java @@ -940,6 +940,10 @@ public class Client extends ChannelInboundHandlerAdapter { if (MapId.isDojo(mapId)) { this.getChannelServer().freeDojoSectionIfEmpty(mapId); } + + if (player.getMap().getHPDec() > 0) { + getWorldServer().removePlayerHpDecrease(player); + } } } catch (final Throwable t) { diff --git a/src/main/java/config/ServerConfig.java b/src/main/java/config/ServerConfig.java index c3248fa364..cbd771246a 100644 --- a/src/main/java/config/ServerConfig.java +++ b/src/main/java/config/ServerConfig.java @@ -180,6 +180,7 @@ public class ServerConfig { public int ITEM_LIMIT_ON_MAP; public int MAP_VISITED_SIZE; public int MAP_DAMAGE_OVERTIME_INTERVAL; + public int MAP_DAMAGE_OVERTIME_COUNT; //Channel Mob Disease Monitor Configuration public int MOB_STATUS_MONITOR_PROC; diff --git a/src/main/java/net/server/channel/handlers/ItemMoveHandler.java b/src/main/java/net/server/channel/handlers/ItemMoveHandler.java index dcb97b90a5..23d95a40d9 100644 --- a/src/main/java/net/server/channel/handlers/ItemMoveHandler.java +++ b/src/main/java/net/server/channel/handlers/ItemMoveHandler.java @@ -55,9 +55,6 @@ public final class ItemMoveHandler extends AbstractPacketHandler { InventoryManipulator.move(c, type, src, action); } - if (c.getPlayer().getMap().getHPDec() > 0) { - c.getPlayer().resetHpDecreaseTask(); - } c.getPlayer().getAutobanManager().spam(6); } } \ No newline at end of file diff --git a/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java b/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java index 4e261c3a1b..61ccc18149 100644 --- a/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java +++ b/src/main/java/net/server/channel/handlers/PlayerLoggedinHandler.java @@ -386,10 +386,6 @@ public final class PlayerLoggedinHandler extends AbstractPacketHandler { player.commitExcludedItems(); showDueyNotification(c, player); - if (player.getMap().getHPDec() > 0) { - player.resetHpDecreaseTask(); - } - player.resetPlayerRates(); if (YamlConfig.config.server.USE_ADD_RATES_BY_LEVEL) { player.setPlayerRates(); diff --git a/src/main/java/net/server/task/CharacterHpDecreaseTask.java b/src/main/java/net/server/task/CharacterHpDecreaseTask.java new file mode 100644 index 0000000000..ed62fb9073 --- /dev/null +++ b/src/main/java/net/server/task/CharacterHpDecreaseTask.java @@ -0,0 +1,37 @@ +/* + This file is part of the HeavenMS MapleStory Server + Copyleft (L) 2016 - 2019 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 . +*/ +package net.server.task; + +import net.server.world.World; + +/** + * @author Ronan + */ +public class CharacterHpDecreaseTask extends BaseTask implements Runnable { + + @Override + public void run() { + wserv.runPlayerHpDecreaseSchedule(); + } + + public CharacterHpDecreaseTask(World world) { + super(world); + } +} diff --git a/src/main/java/net/server/world/World.java b/src/main/java/net/server/world/World.java index 5b41cdf826..f41775ee6b 100644 --- a/src/main/java/net/server/world/World.java +++ b/src/main/java/net/server/world/World.java @@ -153,6 +153,7 @@ public class World { private MonitoredReentrantLock timedMapObjectLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.WORLD_MAPOBJS, true); private final Map fishingAttempters = Collections.synchronizedMap(new WeakHashMap<>()); + private Map playerHpDec = Collections.synchronizedMap(new WeakHashMap<>()); private ScheduledFuture charactersSchedule; private ScheduledFuture marriagesSchedule; @@ -160,6 +161,7 @@ public class World { private ScheduledFuture fishingSchedule; private ScheduledFuture partySearchSchedule; private ScheduledFuture timeoutSchedule; + private ScheduledFuture hpDecSchedule; public World(int world, int flag, String eventmsg, int exprate, int droprate, int bossdroprate, int mesorate, int questrate, int travelrate, int fishingrate) { this.id = world; @@ -194,6 +196,7 @@ public class World { fishingSchedule = tman.register(new FishingTask(this), SECONDS.toMillis(10), SECONDS.toMillis(10)); partySearchSchedule = tman.register(new PartySearchTask(this), SECONDS.toMillis(10), SECONDS.toMillis(10)); timeoutSchedule = tman.register(new TimeoutTask(this), SECONDS.toMillis(10), SECONDS.toMillis(10)); + hpDecSchedule = tman.register(new CharacterHpDecreaseTask(this), YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL, YamlConfig.config.server.MAP_DAMAGE_OVERTIME_INTERVAL); if (YamlConfig.config.server.USE_FAMILY_SYSTEM) { long timeLeft = Server.getTimeLeftForNextDay(); @@ -1715,6 +1718,33 @@ public class World { r.run(); } } + + public void addPlayerHpDecrease(Character chr) { + playerHpDec.putIfAbsent(chr, 0); + } + + public void removePlayerHpDecrease(Character chr) { + playerHpDec.remove(chr); + } + + public void runPlayerHpDecreaseSchedule() { + Map m = new HashMap<>(); + m.putAll(playerHpDec); + + for (Entry e : m.entrySet()) { + Character chr = e.getKey(); + + if (!chr.isAwayFromWorld()) { + int c = e.getValue(); + c = (c + 1) % YamlConfig.config.server.MAP_DAMAGE_OVERTIME_COUNT; + playerHpDec.replace(chr, c); + + if (c == 0) { + chr.doHurtHp(); + } + } + } + } public void resetDisabledServerMessages() { srvMessagesLock.lock(); @@ -2149,6 +2179,11 @@ public class World { timeoutSchedule.cancel(false); timeoutSchedule = null; } + + if(hpDecSchedule != null) { + hpDecSchedule.cancel(false); + hpDecSchedule = null; + } players.disconnectAll(); players = null; diff --git a/src/main/java/server/maps/MapleMap.java b/src/main/java/server/maps/MapleMap.java index 747c906043..50b46fa9c0 100644 --- a/src/main/java/server/maps/MapleMap.java +++ b/src/main/java/server/maps/MapleMap.java @@ -2379,6 +2379,12 @@ public class MapleMap { chr.setMapId(mapid); chr.updateActiveEffects(); + + if (this.getHPDec() > 0) { + getWorldServer().addPlayerHpDecrease(chr); + } else { + getWorldServer().removePlayerHpDecrease(chr); + } MapScriptManager msm = MapScriptManager.getInstance(); if (chrSize == 1) {