Coupon buff fix + concurrency fixes

Fixed coupon buff icon not showing properly. Fixed some cases involving
coupons and buff removal not dealing properly with concurrent access.
This commit is contained in:
ronancpl
2017-06-19 17:44:01 -03:00
parent 42fe74955d
commit 7f6d420cf1
58 changed files with 345 additions and 220 deletions

View File

@@ -1,4 +1,4 @@
#Sun, 18 Jun 2017 02:53:19 -0300
#Mon, 19 Jun 2017 14:48:35 -0300
C\:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2=

BIN
dist/MapleSolaxia.jar vendored

Binary file not shown.

View File

@@ -320,4 +320,13 @@ Corre
15 - 17 Junho 2017,
Correção de bug na função de atribuição de EXP, que não permitia receber valores negativos de EXP.
Implementação da GPQ.
Implementação da GPQ.
18 Junho 2017,
Correção de problema de concorrência referente às alterações nos rates do server.
Consertado bugs referentes ao comando "level", não reatribuindo rates apropriadamente.
19 Junho 2017,
Consertado cupons não aparecendo apropriadamente na região de buffs.
Consertado alguns problemas de concorrência com cupons.
Consertado alguns problemas de concorrência com character buffs.

View File

@@ -12,15 +12,18 @@
</editor-bookmarks>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/event/GuildQuest.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040009.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/ChangeMapHandler.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040006.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/reactor/2006001.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/reactor/9208009.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/TimerManager.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/channel/handlers/PlayerLoggedinHandler.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/command/Commands.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleStatEffect.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/Server.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/net/server/CouponWorker.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleBuffStat.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/constants/ServerConstants.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/MapleCharacter.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/scripts/npc/9040001.js</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/server/MapleItemInformationProvider.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/client/inventory/MapleInventory.java</file>
<file>file:/C:/Nexon/MapleSolaxia/MapleSolaxiaV2/src/tools/MaplePacketCreator.java</file>
</group>
</open-files>
</project-private>

View File

@@ -62,8 +62,11 @@ function action(mode, type, selection) {
cm.dispose();
}
} else if (status == 3) {
if (cm.haveItem(4031801))
if (cm.haveItem(4031801)) {
cm.gainItem(4031801, -1);
} else {
cm.gainMeso(-150);
}
cm.warp(104000000);
cm.dispose();
}

View File

@@ -25,7 +25,7 @@ function start() {
function action(mode, type, selection) {
if(mode == 1) {
cm.warp(990001100);
cm.warp(101030104);
}
cm.dispose();
}

View File

@@ -22,42 +22,48 @@
package client;
public enum MapleBuffStat {
//SLOW(0x1),
MORPH(0x2),
RECOVERY(0x4),
MAPLE_WARRIOR(0x8),
STANCE(0x10),
SHARP_EYES(0x20),
MANA_REFLECTION(0x40),
//ALWAYS_RIGHT(0X80),
//SLOW(0x1L),
MORPH(0x2L),
RECOVERY(0x4L),
MAPLE_WARRIOR(0x8L),
STANCE(0x10L),
SHARP_EYES(0x20L),
MANA_REFLECTION(0x40L),
//ALWAYS_RIGHT(0X80L),
//------ bgn EDITED SLOT (was unused before) --------
MAP_PROTECTION(0x100000000000000L),
//------ end EDITED SLOT ----------------------------
SHADOW_CLAW(0x100),
INFINITY(0x200),
HOLY_SHIELD(0x400),
HAMSTRING(0x800),
BLIND(0x1000),
CONCENTRATE(0x2000),
//4000
ECHO_OF_HERO(0x8000),
//10000
GHOST_MORPH(0x20000),
AURA(0x40000),
CONFUSE(0x80000),
//100000
//200000
//400000
//800000
//1000000
//2000000
//4000000
BERSERK_FURY(0x8000000),
DIVINE_BODY(0x10000000),
SHADOW_CLAW(0x100L),
INFINITY(0x200L),
HOLY_SHIELD(0x400L),
HAMSTRING(0x800L),
BLIND(0x1000L),
CONCENTRATE(0x2000L),
//4000L
ECHO_OF_HERO(0x8000L),
//10000L
GHOST_MORPH(0x20000L),
AURA(0x40000L),
CONFUSE(0x80000L),
// ---- COUPON feature (was unused anyway) ----
COUPON_EXP1(0x100000L),
COUPON_EXP2(0x200000L),
COUPON_EXP3(0x400000L),
COUPON_EXP4(0x800000L),
COUPON_DRP1(0x1000000L),
COUPON_DRP2(0x2000000L),
COUPON_DRP3(0x4000000L),
// ---- end COUPON feature ----
BERSERK_FURY(0x8000000L),
DIVINE_BODY(0x10000000L),
SPARK(0x20000000L),
//40000000
//40000000L
FINALATTACK(0x80000000L),
BATTLESHIP(0xA00000040L), // weird one
WATK(0x100000000L),

View File

@@ -46,6 +46,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
//import java.util.TimeZone;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
@@ -257,6 +259,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
private ScheduledFuture<?> expiretask;
private ScheduledFuture<?> recoveryTask;
private List<ScheduledFuture<?>> timers = new ArrayList<>();
private Lock couponLock = new ReentrantLock();
private NumberFormat nf = new DecimalFormat("#,###,###,###");
private ArrayList<Integer> excluded = new ArrayList<>();
private MonsterBook monsterbook;
@@ -700,9 +703,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
public void cancelBuffStats(MapleBuffStat stat) {
public synchronized void cancelBuffStats(MapleBuffStat stat) {
List<MapleBuffStat> buffStatList = Arrays.asList(stat);
deregisterBuffStats(buffStatList);
dropBuffStats(deregisterBuffStats(buffStatList));
cancelPlayerBuffs(buffStatList);
}
@@ -789,7 +792,15 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
cancelEffect(MapleItemInformationProvider.getInstance().getItemEffect(itemId), false, -1);
}
public void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
public synchronized void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime) {
cancelEffect(effect, overwrite, startTime, true);
}
private void cancelEffect(MapleStatEffect effect, boolean overwrite, long startTime, boolean firstCancel) {
dropBuffStats(cancelEffectInternal(effect, overwrite, startTime));
}
private List<MapleBuffStatValueHolder> cancelEffectInternal(MapleStatEffect effect, boolean overwrite, long startTime) {
List<MapleBuffStat> buffstats;
if (!overwrite) {
buffstats = getBuffStats(effect, startTime);
@@ -800,7 +811,7 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
buffstats.add(statup.getLeft());
}
}
deregisterBuffStats(buffstats);
List<MapleBuffStatValueHolder> toCancel = deregisterBuffStats(buffstats);
if (effect.isMagicDoor()) {
if (!getDoors().isEmpty()) {
MapleDoor door = getDoors().iterator().next();
@@ -842,6 +853,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
if (!overwrite) {
cancelPlayerBuffs(buffstats);
}
return toCancel;
}
public void cancelEffectFromBuffStat(MapleBuffStat stat) {
@@ -1745,60 +1758,63 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
private void deregisterBuffStats(List<MapleBuffStat> stats) {
synchronized (stats) {
List<MapleBuffStatValueHolder> effectsToCancel = new ArrayList<>(stats.size());
for (MapleBuffStat stat : stats) {
MapleBuffStatValueHolder mbsvh = effects.get(stat);
if (mbsvh != null) {
effects.remove(stat);
boolean addMbsvh = true;
for (MapleBuffStatValueHolder contained : effectsToCancel) {
if (mbsvh.startTime == contained.startTime && contained.effect == mbsvh.effect) {
addMbsvh = false;
}
}
if (addMbsvh) {
effectsToCancel.add(mbsvh);
}
if (stat == MapleBuffStat.RECOVERY) {
if (recoveryTask != null) {
recoveryTask.cancel(false);
recoveryTask = null;
}
} else if (stat == MapleBuffStat.SUMMON || stat == MapleBuffStat.PUPPET) {
int summonId = mbsvh.effect.getSourceId();
MapleSummon summon = summons.get(summonId);
if (summon != null) {
getMap().broadcastMessage(MaplePacketCreator.removeSummon(summon, true), summon.getPosition());
getMap().removeMapObject(summon);
removeVisibleMapObject(summon);
summons.remove(summonId);
}
if (summon.getSkill() == DarkKnight.BEHOLDER) {
if (beholderHealingSchedule != null) {
beholderHealingSchedule.cancel(false);
beholderHealingSchedule = null;
}
if (beholderBuffSchedule != null) {
beholderBuffSchedule.cancel(false);
beholderBuffSchedule = null;
}
}
} else if (stat == MapleBuffStat.DRAGONBLOOD) {
dragonBloodSchedule.cancel(false);
dragonBloodSchedule = null;
private void dropBuffStats(List<MapleBuffStatValueHolder> effectsToCancel) {
for (MapleBuffStatValueHolder cancelEffectCancelTasks : effectsToCancel) {
if (cancelEffectCancelTasks.schedule != null) {
cancelEffectCancelTasks.schedule.cancel(false);
this.cancelEffect(cancelEffectCancelTasks.effect, false, -1, false);
}
}
}
private List<MapleBuffStatValueHolder> deregisterBuffStats(List<MapleBuffStat> stats) {
List<MapleBuffStatValueHolder> effectsToCancel = new ArrayList<>(stats.size());
for (MapleBuffStat stat : stats) {
MapleBuffStatValueHolder mbsvh = effects.get(stat);
if (mbsvh != null) {
effects.remove(stat);
boolean addMbsvh = true;
for (MapleBuffStatValueHolder contained : effectsToCancel) {
if (mbsvh.startTime == contained.startTime && contained.effect == mbsvh.effect) {
addMbsvh = false;
}
}
}
for (MapleBuffStatValueHolder cancelEffectCancelTasks : effectsToCancel) {
if (cancelEffectCancelTasks.schedule != null) {
cancelEffectCancelTasks.schedule.cancel(false);
this.cancelEffect(cancelEffectCancelTasks.effect, false, -1);
if (addMbsvh) {
effectsToCancel.add(mbsvh);
}
if (stat == MapleBuffStat.RECOVERY) {
if (recoveryTask != null) {
recoveryTask.cancel(false);
recoveryTask = null;
}
} else if (stat == MapleBuffStat.SUMMON || stat == MapleBuffStat.PUPPET) {
int summonId = mbsvh.effect.getSourceId();
MapleSummon summon = summons.get(summonId);
if (summon != null) {
getMap().broadcastMessage(MaplePacketCreator.removeSummon(summon, true), summon.getPosition());
getMap().removeMapObject(summon);
removeVisibleMapObject(summon);
summons.remove(summonId);
}
if (summon.getSkill() == DarkKnight.BEHOLDER) {
if (beholderHealingSchedule != null) {
beholderHealingSchedule.cancel(false);
beholderHealingSchedule = null;
}
if (beholderBuffSchedule != null) {
beholderBuffSchedule.cancel(false);
beholderBuffSchedule = null;
}
}
} else if (stat == MapleBuffStat.DRAGONBLOOD) {
dragonBloodSchedule.cancel(false);
dragonBloodSchedule = null;
}
}
}
return effectsToCancel;
}
public void disableDoor() {
@@ -2015,6 +2031,9 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
expiretask = TimerManager.getInstance().register(new Runnable() {
@Override
public void run() {
MapleItemInformationProvider miip = MapleItemInformationProvider.getInstance();
boolean deletedCoupon = false;
long expiration, currenttime = System.currentTimeMillis();
Set<Skill> keys = getSkills().keySet();
for (Iterator<Skill> i = keys.iterator(); i.hasNext();) {
@@ -2038,12 +2057,19 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
} else if (expiration != -1 && expiration < currenttime) {
client.announce(MaplePacketCreator.itemExpired(item.getItemId()));
toberemove.add(item);
if(miip.isRateCoupon(item.getItemId())) {
deletedCoupon = true;
}
}
}
for (Item item : toberemove) {
MapleInventoryManipulator.removeFromSlot(client, inv.getType(), item.getPosition(), item.getQuantity(), true);
}
toberemove.clear();
if(deletedCoupon) {
updateCouponRates();
}
}
}
}, 60000);
@@ -2378,10 +2404,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return new ArrayList<>(doors);
}
public int getDropRate() {
return dropRate;
}
public int getEnergyBar() {
return energybar;
}
@@ -2405,6 +2427,38 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
public int getExpRate() {
return expRate;
}
public int getCouponExpRate() {
return expCoupon;
}
public int getRawExpRate() {
return expRate / (expCoupon * client.getWorldServer().getExpRate());
}
public int getDropRate() {
return dropRate;
}
public int getCouponDropRate() {
return dropCoupon;
}
public int getRawDropRate() {
return dropRate / (dropCoupon * client.getWorldServer().getDropRate());
}
public int getMesoRate() {
return mesoRate;
}
public int getCouponMesoRate() {
return mesoCoupon;
}
public int getRawMesoRate() {
return mesoRate / (mesoCoupon * client.getWorldServer().getMesoRate());
}
public int getFace() {
return face;
@@ -2675,10 +2729,6 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
return merchantmeso;
}
public int getMesoRate() {
return mesoRate;
}
public int getMesosTraded() {
return mesosTraded;
}
@@ -3511,12 +3561,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
for (byte i = 1; i < 5; i++) {
gainSlots(i, 4, true);
}
}
this.yellowMessage("We see you reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
this.yellowMessage("You reached level " + level + ". Congratulations! As a token of your success, your inventory has been expanded a little bit.");
}
}
if (level % 20 == 0 && ServerConstants.USE_ADD_RATES_BY_LEVEL == true) { //For the drop & meso rate
revertPlayerRates();
revertLastPlayerRates();
setPlayerRates();
this.yellowMessage("You managed to get level " + level + "! Getting experience and items seems a little easier now, huh?");
}
@@ -3626,24 +3676,22 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}
}
public void setPlayerRates() {
public void setPlayerRates() {
this.expRate *= GameConstants.getPlayerBonusExpRate(this.level / 20);
this.mesoRate *= GameConstants.getPlayerBonusMesoRate(this.level / 20);
this.dropRate *= GameConstants.getPlayerBonusDropRate(this.level / 20);
}
public void revertPlayerRates() {
public void revertLastPlayerRates() {
this.expRate /= GameConstants.getPlayerBonusExpRate((this.level - 1) / 20);
this.mesoRate /= GameConstants.getPlayerBonusMesoRate((this.level - 1) / 20);
this.dropRate /= GameConstants.getPlayerBonusDropRate((this.level - 1) / 20);
}
public void revertWorldRates() {
World worldz = Server.getInstance().getWorld(world);
this.expRate /= worldz.getExpRate();
this.mesoRate /= worldz.getMesoRate();
this.dropRate /= worldz.getDropRate();
public void revertPlayerRates() {
this.expRate /= GameConstants.getPlayerBonusExpRate(this.level / 20);
this.mesoRate /= GameConstants.getPlayerBonusMesoRate(this.level / 20);
this.dropRate /= GameConstants.getPlayerBonusDropRate(this.level / 20);
}
public void setWorldRates() {
@@ -3653,13 +3701,30 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
this.dropRate *= worldz.getDropRate();
}
public void revertCouponRates() {
public void revertWorldRates() {
World worldz = Server.getInstance().getWorld(world);
this.expRate /= worldz.getExpRate();
this.mesoRate /= worldz.getMesoRate();
this.dropRate /= worldz.getDropRate();
}
private void setCouponRates() {
setActiveCoupons();
activateCouponsEffects();
}
private void revertCouponRates() {
revertCouponsEffects();
}
public void setCouponRates() {
setActiveCoupons();
activateCouponsEffects();
public void updateCouponRates() {
try {
couponLock.lock();
revertCouponRates();
setCouponRates();
} finally {
couponLock.unlock();
}
}
public void resetPlayerRates() {
@@ -4508,6 +4573,8 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
}, buffInterval, buffInterval);
}
} else if (effect.isRecovery()) {
int healInterval = (ServerConstants.USE_ULTRA_RECOVERY) ? 2500 : 5000;
final byte heal = (byte) effect.getX();
recoveryTask = TimerManager.getInstance().register(new Runnable() {
@Override
@@ -4516,12 +4583,12 @@ public class MapleCharacter extends AbstractAnimatedMapleMapObject {
client.announce(MaplePacketCreator.showOwnRecovery(heal));
getMap().broadcastMessage(MapleCharacter.this, MaplePacketCreator.showRecovery(id, heal), false);
}
}, 5000, 5000);
}, healInterval, healInterval);
}
//is it possible to maintain a list of statup effects of the same type concurrently? Pair<MapleBuffStat, Itemid>
for (Pair<MapleBuffStat, Integer> statup : effect.getStatups()) {
effects.put(statup.getLeft(), new MapleBuffStatValueHolder(effect, starttime, schedule, statup.getRight().intValue()));
effects.put(statup.getLeft(), new MapleBuffStatValueHolder(effect, starttime, schedule, statup.getRight()));
}
recalcLocalStats();
}

View File

@@ -522,19 +522,22 @@ public class Commands {
player.yellowMessage("DROP RATE");
player.message(">>Base DROP Rate: " + c.getWorldServer().getDropRate() + "x");
player.message(">>Your DROP Rate: " + player.getDropRate() / c.getWorldServer().getDropRate() + "x");
player.message(">>Your DROP Rate: " + player.getRawDropRate() + "x");
if(player.getCouponDropRate() != 1) player.message(">>Your Coupon DROP Rate: " + player.getCouponDropRate() + "x");
player.message(">>------------------------------------------------");
player.message(">>Total DROP Rate: " + player.getDropRate() + "x");
player.yellowMessage("MESO RATE");
player.message(">>Base MESO Rate: " + c.getWorldServer().getMesoRate() + "x");
player.message(">>Your MESO Rate: " + player.getMesoRate() / c.getWorldServer().getMesoRate() + "x");
player.message(">>Your MESO Rate: " + player.getRawMesoRate() + "x");
if(player.getCouponMesoRate() != 1) player.message(">>Your Coupon MESO Rate: " + player.getCouponMesoRate() + "x");
player.message(">>------------------------------------------------");
player.message(">>Total MESO Rate: " + player.getMesoRate() + "x");
player.yellowMessage("EXP RATE");
player.message(">>Base EXP Rate: " + c.getWorldServer().getExpRate() + "x");
player.message(">>Your EXP Rate: " + player.getExpRate() / c.getWorldServer().getExpRate() + "x");
player.message(">>Your EXP Rate: " + player.getRawExpRate() + "x");
if(player.getCouponExpRate() != 1) player.message(">>Your Coupon EXP Rate: " + player.getCouponExpRate() + "x");
player.message(">>------------------------------------------------");
player.message(">>Total EXP Rate: " + player.getExpRate() + "x");
/*if(c.getWorldServer().getExpRate() > ServerConstants.EXP_RATE) {
@@ -1386,8 +1389,12 @@ public class Commands {
return true;
}
player.setLevel(Integer.parseInt(sub[1]) - 1);
player.loseExp(player.getExp(), false, false);
player.loseExp(player.getExp(), false, false);
player.revertPlayerRates();
player.setLevel(Math.min(Integer.parseInt(sub[1]), player.getMaxLevel()) - 1);
player.setPlayerRates();
player.levelUp(false);
} else if (sub[0].equals("levelpro")) {
if (sub.length < 2){
@@ -1402,7 +1409,9 @@ public class Commands {
final String[] s = {"setall", String.valueOf(Short.MAX_VALUE)};
executeGMCommand(c, s, heading);
player.loseExp(player.getExp(), false, false);
player.revertPlayerRates();
player.setLevel(255);
player.setPlayerRates();
player.setFame(13337);
player.setMaxHp(30000);
player.setMaxMp(30000);
@@ -1410,8 +1419,6 @@ public class Commands {
player.updateSingleStat(MapleStat.FAME, 13337);
player.updateSingleStat(MapleStat.MAXHP, 30000);
player.updateSingleStat(MapleStat.MAXMP, 30000);
player.revertPlayerRates();
player.setPlayerRates();
player.yellowMessage("Stats maxed out.");
} else if (sub[0].equals("maxskills")) {
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {

View File

@@ -199,8 +199,7 @@ public class MapleInventory implements Iterable<Item> {
inventory.put(slot, item);
if(MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) {
owner.revertCouponRates();
owner.setCouponRates();
owner.updateCouponRates();
}
}
@@ -208,8 +207,7 @@ public class MapleInventory implements Iterable<Item> {
Item item = inventory.remove(slot);
if(item != null && MapleItemInformationProvider.getInstance().isRateCoupon(item.getItemId())) {
owner.revertCouponRates();
owner.setCouponRates();
owner.updateCouponRates();
}
}

View File

@@ -39,7 +39,7 @@ public class ServerConstants {
public static final boolean USE_DEBUG_SHOW_INFO_EQPEXP = false; //Prints on the cmd all equip exp gain info.
public static final boolean USE_MTS = false;
public static final boolean USE_FAMILY_SYSTEM = false;
public static final boolean USE_PERMISSIVE_BUFFS = true; //WARNING: Allows players that does not have increased certain buff-type skills to use it's effect. Used mainly on buff-cast commands, however making this active may generate a source for possible client-edited exploits.
public static final boolean USE_PERMISSIVE_BUFFS = false; //WARNING: Allows players that does not have increased certain buff-type skills to use it's effect. Used mainly on buff-cast commands, however making this active may generate a source for possible client-edited exploits.
public static final boolean USE_DUEY = true;
public static final boolean USE_ITEM_SORT = true;
public static final boolean USE_ITEM_SORT_BY_NAME = false; //Item sorting based on name rather than id.

View File

@@ -19,21 +19,11 @@
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;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import constants.ServerConstants;
import tools.DatabaseConnection;
import net.server.world.World;
import client.MapleCharacter;
import tools.FilePrinter;
/**
* @author Ronan
@@ -46,7 +36,7 @@ public class CouponWorker implements Runnable {
Server.getInstance().updateActiveCoupons();
Server.getInstance().commitActiveCoupons();
} catch(SQLException sqle) {
sqle.printStackTrace();
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, "Unexpected SQL error: " + sqle.getMessage() + "\n\n");
}
}
}

View File

@@ -167,8 +167,7 @@ public class Server implements Runnable {
for(MapleCharacter chr: world.getPlayerStorage().getAllCharacters()) {
if(!chr.isLoggedin()) continue;
chr.revertCouponRates();
chr.setCouponRates();
chr.updateCouponRates();
}
}
}

View File

@@ -32,21 +32,21 @@ import client.MapleClient;
* @author Matze
*/
public final class MesoDropHandler extends AbstractMaplePacketHandler {//FIX
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter player = c.getPlayer();
if (!player.isAlive()) {
c.announce(MaplePacketCreator.enableActions());
return;
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter player = c.getPlayer();
if (!player.isAlive()) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if (!player.canDropMeso()){
player.announce(MaplePacketCreator.serverNotice(5, "Fast meso drop has been patched, cut that out. ;)"));
return;
}
slea.skip(4);
int meso = slea.readInt();
if (meso <= player.getMeso() && meso > 9 && meso < 50001) {
player.gainMeso(-meso, false, true, false);
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2);
}
}
if (!player.canDropMeso()){
player.announce(MaplePacketCreator.serverNotice(5, "Fast meso drop has been patched, cut that out. ;)"));
return;
}
slea.skip(4);
int meso = slea.readInt();
if (meso <= player.getMeso() && meso > 9 && meso < 50001) {
player.gainMeso(-meso, false, true, false);
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2);
}
}
}

View File

@@ -269,11 +269,10 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
if (player.getMap().getHPDec() > 0) player.resetHpDecreaseTask();
player.dispelBuffCoupons();
player.resetPlayerRates();
if(ServerConstants.USE_ADD_RATES_BY_LEVEL == true) player.setPlayerRates();
player.setWorldRates();
player.setCouponRates();
player.updateCouponRates();
}
}

View File

@@ -32,9 +32,10 @@ import constants.ServerConstants;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.Set;
@@ -114,12 +115,15 @@ public class World {
}
public void setExpRate(int exp) {
//System.out.println("Setting server EXP Rate to " + exp * ServerConstants.EXP_RATE + "x.");
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
List<MapleCharacter> list = new LinkedList<>(getPlayerStorage().getAllCharacters());
for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.revertWorldRates();
}
this.exprate = exp;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.setWorldRates();
}
}
@@ -129,11 +133,15 @@ public class World {
}
public void setDropRate(int drop) {
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
List<MapleCharacter> list = new LinkedList<>(getPlayerStorage().getAllCharacters());
for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.revertWorldRates();
}
this.droprate = drop;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.setWorldRates();
}
}
@@ -143,11 +151,15 @@ public class World {
}
public void setMesoRate(int meso) {
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
List<MapleCharacter> list = new LinkedList<>(getPlayerStorage().getAllCharacters());
for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.revertWorldRates();
}
this.mesorate = meso;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
for(MapleCharacter chr : list) {
if(!chr.isLoggedin()) continue;
chr.setWorldRates();
}
}
@@ -157,13 +169,7 @@ public class World {
}
public void setBossDropRate(int bossdrop) {
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
chr.revertWorldRates();
}
this.bossdroprate = bossdrop;
for(MapleCharacter chr : getPlayerStorage().getAllCharacters()) {
chr.setWorldRates();
}
}
public PlayerStorage getPlayerStorage() {

View File

@@ -223,6 +223,40 @@ public class MapleStatEffect {
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.JUMP, Integer.valueOf(ret.jump));
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.PYRAMID_PQ, Integer.valueOf(ret.berserk));
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.BOOSTER, Integer.valueOf(ret.booster));
if(MapleItemInformationProvider.getInstance().isRateCoupon(sourceid)) {
switch(MapleDataTool.getInt("expR", source, 0)) {
case 1:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP1, 1);
break;
case 2:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP2, 1);
break;
case 3:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP3, 1);
break;
case 4:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_EXP4, 1);
break;
}
switch(MapleDataTool.getInt("drpR", source, 0)) {
case 1:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP1, 1);
break;
case 2:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP2, 1);
break;
case 3:
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.COUPON_DRP3, 1);
break;
}
}
}
MapleData ltd = source.getChildByPath("lt");
if (ltd != null) {
@@ -928,7 +962,7 @@ public class MapleStatEffect {
}
private void applyBuffEffect(MapleCharacter applyfrom, MapleCharacter applyto, boolean primary) {
if (!isMonsterRiding()) {
if (!isMonsterRiding() && !isCouponBuff()) {
applyto.cancelEffect(this, true, -1);
}
@@ -1253,6 +1287,10 @@ public class MapleStatEffect {
return skill && sourceid == ChiefBandit.CHAKRA;
}
private boolean isCouponBuff() {
return MapleItemInformationProvider.getInstance().isRateCoupon(sourceid);
}
public boolean isMonsterRiding() {
return skill && (sourceid % 10000000 == 1004 || sourceid == Corsair.BATTLE_SHIP || sourceid == Beginner.SPACESHIP || sourceid == Noblesse.SPACESHIP
|| sourceid == Beginner.YETI_MOUNT1 || sourceid == Beginner.YETI_MOUNT2 || sourceid == Beginner.WITCH_BROOMSTICK || sourceid == Beginner.BALROG_MOUNT

View File

@@ -22,8 +22,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211004">
@@ -46,8 +46,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211005">
@@ -70,8 +70,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211006">
@@ -94,8 +94,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211007">
@@ -118,8 +118,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211008">
@@ -142,8 +142,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211009">
@@ -163,8 +163,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211010">
@@ -184,8 +184,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211011">
@@ -205,8 +205,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211012">
@@ -226,8 +226,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211013">
@@ -247,8 +247,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211014">
@@ -273,8 +273,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211015">
@@ -299,8 +299,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211016">
@@ -325,8 +325,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211017">
@@ -351,8 +351,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211018">
@@ -377,8 +377,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211037">
@@ -401,8 +401,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211038">
@@ -422,8 +422,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211039">
@@ -448,8 +448,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211040">
@@ -472,8 +472,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211041">
@@ -493,8 +493,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211042">
@@ -519,8 +519,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211043">
@@ -543,8 +543,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211044">
@@ -564,8 +564,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05211045">
@@ -590,8 +590,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05211046">
@@ -616,8 +616,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir>
</imgdir>
<imgdir name="05211048">
@@ -642,8 +642,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir>
</imgdir>
<imgdir name="05211049">
@@ -668,8 +668,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir>
</imgdir>
<imgdir name="05211052">
@@ -695,8 +695,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="3"/>
</imgdir>
</imgdir>
<imgdir name="05211060">
@@ -722,8 +722,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="expR" value="4"/>
</imgdir>
</imgdir>
</imgdir>

View File

@@ -22,8 +22,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="1"/>
</imgdir>
</imgdir>
<imgdir name="05360001">
@@ -48,8 +48,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360002">
@@ -74,8 +74,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360003">
@@ -100,8 +100,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360004">
@@ -126,8 +126,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360005">
@@ -152,8 +152,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360006">
@@ -178,8 +178,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360007">
@@ -204,8 +204,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360008">
@@ -230,8 +230,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="2"/>
</imgdir>
</imgdir>
<imgdir name="05360042">
@@ -256,8 +256,8 @@
</imgdir>
</imgdir>
<imgdir name="spec">
<int name="pad" value="5"/>
<int name="time" value="2100000"/>
<int name="drpR" value="3"/>
</imgdir>
</imgdir>
</imgdir>