Revamped buff system + skill cd/buff schedule rework

Completely rearranged buff system (system can smartly check for the best
statup to take effect for it's duration, or the server can be flagged to
act as usual). Refactored scheduling system for buffs expiration and
cooldowns to use one single thread per player rather than one per
instance.
This commit is contained in:
ronancpl
2017-09-22 19:09:56 -03:00
parent 1ffcf47f79
commit 9c72ce1e3a
104 changed files with 1321 additions and 583 deletions

View File

@@ -21,6 +21,8 @@
*/
package net.server;
import net.server.worker.CouponWorker;
import net.server.worker.RankingWorker;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;

View File

@@ -41,6 +41,8 @@ public final class CancelBuffHandler extends AbstractMaplePacketHandler implemen
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int sourceid = slea.readInt();
if(sourceid < 0) sourceid = -sourceid; //oh my...
switch (sourceid) {
case FPArchMage.BIG_BANG:
case ILArchMage.BIG_BANG:

View File

@@ -32,7 +32,6 @@ import tools.Pair;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleCharacter.CancelCooldownAction;
import client.MapleClient;
import client.MapleJob;
import client.MapleStat;
@@ -175,7 +174,7 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
return;
} else {
c.announce(MaplePacketCreator.skillCooldown(attack.skill, effect_.getCooldown()));
player.addCooldown(attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000, TimerManager.getInstance().schedule(new CancelCooldownAction(player, attack.skill), effect_.getCooldown() * 1000));
player.addCooldown(attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000);
}
}
}

View File

@@ -50,7 +50,9 @@ public class EnterCashShopHandler extends AbstractMaplePacketHandler {
mc.closePlayerInteractions();
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(mc.getId(), mc.getAllBuffs());
mc.cancelBuffEffects();
mc.cancelAllBuffs(true);
mc.cancelBuffExpireTask();
mc.cancelSkillCooldownTask();
mc.cancelExpirationTask();
c.announce(MaplePacketCreator.openCashShop(c, false));

View File

@@ -59,6 +59,9 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
}
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
chr.cancelAllBuffs(true);
chr.cancelBuffExpireTask();
chr.cancelSkillCooldownTask();
chr.cancelExpirationTask();
chr.saveToDB();
chr.getMap().removePlayer(c.getPlayer());

View File

@@ -27,7 +27,6 @@ import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleCharacter.CancelCooldownAction;
import client.MapleClient;
import client.Skill;
import client.SkillFactory;
@@ -76,7 +75,7 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
return;
} else {
c.announce(MaplePacketCreator.skillCooldown(attack.skill, effect_.getCooldown()));
player.addCooldown(attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000, TimerManager.getInstance().schedule(new CancelCooldownAction(player, attack.skill), effect_.getCooldown() * 1000));
player.addCooldown(attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000);
}
}
applyAttack(attack, player, effect.getAttackCount());

View File

@@ -32,6 +32,7 @@ import constants.ItemConstants;
import java.util.Arrays;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import server.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MapleMiniGame;
@@ -172,6 +173,7 @@ public final class PlayerInteractionHandler extends AbstractMaplePacketHandler {
} else {
HiredMerchant merchant = new HiredMerchant(chr, itemId, desc);
chr.setHiredMerchant(merchant);
c.getWorldServer().registerHiredMerchant(merchant);
chr.getClient().getChannelServer().addHiredMerchant(chr.getId(), merchant);
chr.announce(MaplePacketCreator.getHiredMerchant(chr, merchant, true));
}

View File

@@ -256,6 +256,8 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
c.announce(MaplePacketCreator.enableReport());
player.changeSkillLevel(SkillFactory.getSkill(10000000 * player.getJobType() + 12), (byte) (player.getLinkedLevel() / 10), 20, -1);
player.checkBerserk(player.isHidden());
player.buffExpireTask();
player.skillCooldownTask();
player.expirationTask();
if (GameConstants.hasSPTable(player.getJob()) && player.getJob().getId() != 2001) {
player.createDragon();

View File

@@ -30,7 +30,6 @@ import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleBuffStat;
import client.MapleCharacter;
import client.MapleCharacter.CancelCooldownAction;
import client.MapleClient;
import client.Skill;
import client.SkillFactory;
@@ -208,7 +207,7 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
return;
} else {
c.announce(MaplePacketCreator.skillCooldown(attack.skill, effect_.getCooldown()));
player.addCooldown(attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000, TimerManager.getInstance().schedule(new CancelCooldownAction(player, attack.skill), effect_.getCooldown() * 1000));
player.addCooldown(attack.skill, System.currentTimeMillis(), effect_.getCooldown() * 1000);
}
}
}

View File

@@ -32,7 +32,6 @@ import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleCharacter;
import client.MapleCharacter.CancelCooldownAction;
import client.autoban.AutobanFactory;
import client.MapleClient;
import client.MapleStat;
@@ -84,8 +83,7 @@ public final class SpecialMoveHandler extends AbstractMaplePacketHandler {
return;
} else if (skillid != Corsair.BATTLE_SHIP) {
c.announce(MaplePacketCreator.skillCooldown(skillid, effect.getCooldown()));
ScheduledFuture<?> timer = TimerManager.getInstance().schedule(new CancelCooldownAction(c.getPlayer(), skillid), effect.getCooldown() * 1000);
chr.addCooldown(skillid, System.currentTimeMillis(), effect.getCooldown() * 1000, timer);
chr.addCooldown(skillid, System.currentTimeMillis(), effect.getCooldown() * 1000);
}
}
if (skillid == Hero.MONSTER_MAGNET || skillid == Paladin.MONSTER_MAGNET || skillid == DarkKnight.MONSTER_MAGNET) { // Monster Magnet

View File

@@ -0,0 +1,39 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
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.worker;
import net.server.world.World;
/**
* @author Ronan
*/
public class BaseWorker implements Runnable {
protected World wserv;
@Override
public void run() {}
public BaseWorker(World world) {
wserv = world;
}
}

View File

@@ -20,17 +20,17 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server;
package net.server.worker;
import net.server.world.World;
import client.MapleCharacter;
import constants.ServerConstants;
import net.server.PlayerStorage;
/**
* @author Ronan
*/
public class CharacterAutosaverWorker implements Runnable {
private World wserv;
public class CharacterAutosaverWorker extends BaseWorker implements Runnable {
@Override
public void run() {
@@ -45,6 +45,6 @@ public class CharacterAutosaverWorker implements Runnable {
}
public CharacterAutosaverWorker(World world) {
wserv = world;
super(world);
}
}

View File

@@ -20,9 +20,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server;
package net.server.worker;
import java.sql.SQLException;
import net.server.Server;
import tools.FilePrinter;
/**

View File

@@ -0,0 +1,40 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
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.worker;
import net.server.world.World;
/**
* @author Ronan
*/
public class HiredMerchantWorker extends BaseWorker implements Runnable {
@Override
public void run() {
wserv.runHiredMerchantSchedule();
}
public HiredMerchantWorker(World world) {
super(world);
}
}

View File

@@ -20,15 +20,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server;
package net.server.worker;
import net.server.world.World;
/**
* @author Ronan
*/
public class MountTirednessWorker implements Runnable {
private World wserv;
public class MountTirednessWorker extends BaseWorker implements Runnable {
@Override
public void run() {
@@ -36,6 +35,6 @@ public class MountTirednessWorker implements Runnable {
}
public MountTirednessWorker(World world) {
wserv = world;
super(world);
}
}

View File

@@ -20,15 +20,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server;
package net.server.worker;
import net.server.world.World;
/**
* @author Ronan
*/
public class PetFullnessWorker implements Runnable {
private World wserv;
public class PetFullnessWorker extends BaseWorker implements Runnable {
@Override
public void run() {
@@ -36,6 +35,6 @@ public class PetFullnessWorker implements Runnable {
}
public PetFullnessWorker(World world) {
wserv = world;
super(world);
}
}

View File

@@ -19,7 +19,7 @@
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;
package net.server.worker;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -28,6 +28,7 @@ import java.sql.SQLException;
import client.MapleJob;
import tools.DatabaseConnection;
import constants.ServerConstants;
import net.server.Server;
/**
* @author Matze

View File

@@ -45,9 +45,10 @@ import java.util.HashSet;
import java.util.concurrent.ScheduledFuture;
import server.TimerManager;
import net.server.CharacterAutosaverWorker;
import net.server.MountTirednessWorker;
import net.server.PetFullnessWorker;
import server.maps.HiredMerchant;
import net.server.worker.CharacterAutosaverWorker;
import net.server.worker.MountTirednessWorker;
import net.server.worker.PetFullnessWorker;
import net.server.PlayerStorage;
import net.server.Server;
import net.server.channel.Channel;
@@ -84,6 +85,10 @@ public class World {
private ScheduledFuture<?> mountsSchedule;
private long mountUpdate;
private Map<HiredMerchant, Byte> activeMerchants = new LinkedHashMap<>();
private ScheduledFuture<?> MerchantsSchedule;
private long merchantUpdate;
private ScheduledFuture<?> charactersSchedule;
public World(int world, int flag, String eventmsg, int exprate, int droprate, int mesorate, int bossdroprate) {
@@ -773,6 +778,48 @@ public class World {
}
}
}
public void registerHiredMerchant(HiredMerchant hm) {
synchronized(activeMerchants) {
byte initProc;
if(System.currentTimeMillis() - merchantUpdate > 5 * 60 * 1000) initProc = 1;
else initProc = 0;
activeMerchants.put(hm, initProc);
}
}
public void unregisterHiredMerchant(HiredMerchant hm) {
synchronized(activeMerchants) {
activeMerchants.remove(hm);
}
}
public void runHiredMerchantSchedule() {
Map<HiredMerchant, Byte> deployedMerchants;
synchronized(activeMerchants) {
merchantUpdate = System.currentTimeMillis();
deployedMerchants = Collections.unmodifiableMap(activeMerchants);
}
for(Map.Entry<HiredMerchant, Byte> dm: deployedMerchants.entrySet()) {
byte timeOn = dm.getValue();
if(timeOn <= 144) { // 1440 minutes == 24hrs
synchronized(activeMerchants) {
activeMerchants.put(dm.getKey(), (byte)(timeOn + 1));
}
} else {
HiredMerchant hm = dm.getKey();
hm.forceClose();
this.getChannel(hm.getChannel()).removeHiredMerchant(hm.getOwnerId());
synchronized(activeMerchants) {
activeMerchants.remove(dm.getKey());
}
}
}
}
public void setServerMessage(String msg) {
for (Channel ch : channels) {