Fixed chair exploit & beholder issue + Mini-dungeon revamp
Fixed an (quite amusing) exploit with map chairs stacking "extra healing" schedules on certain conditions. Fixed mini-dungeon not disposing players properly in some cases. Refactored the mini-dungeon structure. Fixed an issue on CASH inventory merging same items when trying to swap them. Fixed Beholder crash issue when trying to enter Cash Shop.
This commit is contained in:
@@ -355,15 +355,18 @@ public class MapleInventoryManipulator {
|
||||
|
||||
public static void move(MapleClient c, MapleInventoryType type, short src, short dst) {
|
||||
if (src < 0 || dst < 0) {
|
||||
System.out.println("src " + src + " dst " + dst);
|
||||
return;
|
||||
}
|
||||
if(dst > c.getPlayer().getInventory(type).getSlotLimit()) {
|
||||
System.out.println("slim " + c.getPlayer().getInventory(type).getSlotLimit() + " dst " + dst);
|
||||
return;
|
||||
}
|
||||
if(dst > c.getPlayer().getInventory(type).getSlotLimit()) {
|
||||
return;
|
||||
}
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
Item source = c.getPlayer().getInventory(type).getItem(src);
|
||||
Item initialTarget = c.getPlayer().getInventory(type).getItem(dst);
|
||||
if (source == null) {
|
||||
System.out.println("null");
|
||||
return;
|
||||
}
|
||||
short olddstQ = -1;
|
||||
@@ -374,7 +377,7 @@ public class MapleInventoryManipulator {
|
||||
short slotMax = ii.getSlotMax(c, source.getItemId());
|
||||
c.getPlayer().getInventory(type).move(src, dst, slotMax);
|
||||
final List<ModifyInventory> mods = new ArrayList<>();
|
||||
if (!type.equals(MapleInventoryType.EQUIP) && initialTarget != null && initialTarget.getItemId() == source.getItemId() && !ItemConstants.isRechargable(source.getItemId())) {
|
||||
if (!(type.equals(MapleInventoryType.EQUIP) || type.equals(MapleInventoryType.CASH)) && initialTarget != null && initialTarget.getItemId() == source.getItemId() && !ItemConstants.isRechargable(source.getItemId())) {
|
||||
if ((olddstQ + oldsrcQ) > slotMax) {
|
||||
mods.add(new ModifyInventory(1, source));
|
||||
mods.add(new ModifyInventory(1, initialTarget));
|
||||
|
||||
@@ -202,14 +202,6 @@ public class MapleStatEffect {
|
||||
ret.speed = (short) MapleDataTool.getInt("speed", source, 0);
|
||||
ret.jump = (short) MapleDataTool.getInt("jump", source, 0);
|
||||
|
||||
if((sourceid == Beginner.NIMBLE_FEET || sourceid == Noblesse.NIMBLE_FEET || sourceid == Evan.NIMBLE_FEET || sourceid == Legend.AGILE_BODY) && ServerConstants.USE_ULTRA_NIMBLE_FEET == true) {
|
||||
ret.jump = (short)(ret.speed * 4);
|
||||
ret.speed *= 15;
|
||||
}
|
||||
|
||||
ret.berserk = MapleDataTool.getInt("berserk", source, 0);
|
||||
ret.booster = MapleDataTool.getInt("booster", source, 0);
|
||||
|
||||
ret.mapProtection = mapProtection(sourceid);
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.MAP_PROTECTION, Integer.valueOf(ret.mapProtection));
|
||||
|
||||
@@ -222,11 +214,16 @@ public class MapleStatEffect {
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.AVOID, Integer.valueOf(ret.avoid));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.SPEED, Integer.valueOf(ret.speed));
|
||||
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(!skill) {
|
||||
if(isDojoBuff(sourceid) || sourceid == 2022337) {
|
||||
if(isPyramidBuff(sourceid)) {
|
||||
ret.berserk = MapleDataTool.getInt("berserk", source, 0);
|
||||
ret.booster = MapleDataTool.getInt("booster", source, 0);
|
||||
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.BERSERK, Integer.valueOf(ret.berserk));
|
||||
addBuffStatPairToListIfNotZero(statups, MapleBuffStat.BOOSTER, Integer.valueOf(ret.booster));
|
||||
|
||||
} else if(isDojoBuff(sourceid) || sourceid == 2022337) {
|
||||
ret.mhpR = (byte) MapleDataTool.getInt("mhpR", source, 0);
|
||||
ret.mhpRRate = (short) (MapleDataTool.getInt("mhpRRate", source, 0) * 100);
|
||||
ret.mmpR = (byte) MapleDataTool.getInt("mmpR", source, 0);
|
||||
@@ -268,6 +265,11 @@ public class MapleStatEffect {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((sourceid == Beginner.NIMBLE_FEET || sourceid == Noblesse.NIMBLE_FEET || sourceid == Evan.NIMBLE_FEET || sourceid == Legend.AGILE_BODY) && ServerConstants.USE_ULTRA_NIMBLE_FEET == true) {
|
||||
ret.jump = (short)(ret.speed * 4);
|
||||
ret.speed *= 15;
|
||||
}
|
||||
}
|
||||
}
|
||||
MapleData ltd = source.getChildByPath("lt");
|
||||
@@ -1328,11 +1330,15 @@ public class MapleStatEffect {
|
||||
return sourceid >= 2022359 && sourceid <= 2022421;
|
||||
}
|
||||
|
||||
public static boolean isPyramidBuff(int sourceid) {
|
||||
return sourceid >= 2022585 && sourceid <= 2022617;
|
||||
}
|
||||
|
||||
public static boolean isRateCoupon(int sourceid) {
|
||||
int itemType = sourceid / 1000;
|
||||
return itemType == 5211 || itemType == 5360;
|
||||
}
|
||||
|
||||
|
||||
private boolean isDs() {
|
||||
return skill && (sourceid == Rogue.DARK_SIGHT || sourceid == WindArcher.WIND_WALK || sourceid == NightWalker.DARK_SIGHT);
|
||||
}
|
||||
|
||||
@@ -1979,19 +1979,11 @@ public class MapleMap {
|
||||
if (chr.getEventInstance() != null) {
|
||||
chr.getEventInstance().movePlayer(chr);
|
||||
}
|
||||
} else if (MapleMiniDungeon.isDungeonMap(mapid)) {
|
||||
final MapleMiniDungeon dungeon = MapleMiniDungeon.getDungeon(mapid);
|
||||
chr.getClient().announce(MaplePacketCreator.getClock(30 * 60));
|
||||
TimerManager.getInstance().schedule(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (MapleMiniDungeon.isDungeonMap(chr.getMapId())) {
|
||||
chr.changeMap(dungeon.getBase());
|
||||
}
|
||||
}
|
||||
}, 30 * 60 * 1000);
|
||||
} else if (MapleMiniDungeonInfo.isDungeonMap(mapid)) {
|
||||
MapleMiniDungeon mmd = chr.getClient().getChannelServer().getMiniDungeon(mapid);
|
||||
if(mmd != null) mmd.registerPlayer(chr);
|
||||
}
|
||||
|
||||
MaplePet[] pets = chr.getPets();
|
||||
for (int i = 0; i < pets.length; i++) {
|
||||
if (pets[i] != null) {
|
||||
@@ -2152,6 +2144,16 @@ public class MapleMap {
|
||||
} finally {
|
||||
chrWLock.unlock();
|
||||
}
|
||||
|
||||
if (MapleMiniDungeonInfo.isDungeonMap(mapid)) {
|
||||
MapleMiniDungeon mmd = chr.getClient().getChannelServer().getMiniDungeon(mapid);
|
||||
if(mmd != null) {
|
||||
if(!mmd.unregisterPlayer(chr)) {
|
||||
chr.getClient().getChannelServer().removeMiniDungeon(mapid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
removeMapObject(chr.getObjectId());
|
||||
if (!chr.isHidden()) {
|
||||
broadcastMessage(MaplePacketCreator.removePlayerFromMap(chr.getId()));
|
||||
|
||||
@@ -1,86 +1,102 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package server.maps;
|
||||
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
import server.TimerManager;
|
||||
import client.MapleCharacter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import tools.MaplePacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
* @author Ronan
|
||||
*/
|
||||
|
||||
public enum MapleMiniDungeon {
|
||||
|
||||
//http://bbb.hidden-street.net/search_finder/mini%20dungeon
|
||||
|
||||
CAVE_OF_MUSHROOMS(105050100, 105050101, 30),
|
||||
GOLEM_CASTLE_RUINS(105040304, 105040320, 34),
|
||||
HILL_OF_SANDSTORMS(260020600, 260020630, 30),
|
||||
HENESYS_PIG_FARM(100020000, 100020100, 30),
|
||||
DRAKES_BLUE_CAVE(105090311, 105090320, 30),
|
||||
DRUMMER_BUNNYS_LAIR(221023400, 221023401, 30),
|
||||
THE_ROUND_TABLE_OF_KENTARUS(240020500, 240020512, 30),
|
||||
THE_RESTORING_MEMORY(240040511, 240040800, 19),
|
||||
NEWT_SECURED_ZONE(240040520, 240040900, 19),
|
||||
PILLAGE_OF_TREASURE_ISLAND(251010402, 251010410, 30),
|
||||
LONGEST_RIDE_ON_BYEBYE_STATION(551030000, 551030001, 19);
|
||||
|
||||
private int baseId;
|
||||
private int dungeonId;
|
||||
private int dungeons;
|
||||
|
||||
private MapleMiniDungeon(int baseId, int dungeonId, int dungeons) {
|
||||
this.baseId = baseId;
|
||||
this.dungeonId = dungeonId;
|
||||
this.dungeons = dungeons;
|
||||
}
|
||||
|
||||
public int getBase() {
|
||||
return baseId;
|
||||
}
|
||||
|
||||
public int getDungeonId() {
|
||||
return dungeonId;
|
||||
}
|
||||
|
||||
public int getDungeons() {
|
||||
return dungeons;
|
||||
}
|
||||
|
||||
public static boolean isDungeonMap(int map){
|
||||
for (MapleMiniDungeon dungeon : MapleMiniDungeon.values()){
|
||||
if (map >= dungeon.getDungeonId() && map <= dungeon.getDungeonId() + dungeon.getDungeons()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static MapleMiniDungeon getDungeon(int map){
|
||||
for (MapleMiniDungeon dungeon : MapleMiniDungeon.values()){
|
||||
if (map >= dungeon.getDungeonId() && map <= dungeon.getDungeonId() + dungeon.getDungeons()){
|
||||
return dungeon;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public class MapleMiniDungeon {
|
||||
List<MapleCharacter> players = new ArrayList<>();
|
||||
ScheduledFuture<?> timeoutTask = null;
|
||||
Lock lock = new ReentrantLock();
|
||||
|
||||
int baseMap;
|
||||
long expireTime;
|
||||
|
||||
public MapleMiniDungeon(int base, int durationMin) {
|
||||
baseMap = base;
|
||||
expireTime = durationMin * 60 * 1000;
|
||||
|
||||
timeoutTask = TimerManager.getInstance().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
lock.lock();
|
||||
try {
|
||||
List<MapleCharacter> lchr = new ArrayList<>(players);
|
||||
|
||||
for(MapleCharacter chr : lchr) {
|
||||
chr.changeMap(baseMap);
|
||||
}
|
||||
|
||||
dispose();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}, expireTime);
|
||||
|
||||
expireTime += System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public boolean registerPlayer(MapleCharacter chr) {
|
||||
int time = (int)((expireTime - System.currentTimeMillis()) / 1000);
|
||||
if(time > 0) chr.getClient().announce(MaplePacketCreator.getClock(time));
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
if(timeoutTask == null) return false;
|
||||
|
||||
players.add(chr);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean unregisterPlayer(MapleCharacter chr) {
|
||||
chr.getClient().announce(MaplePacketCreator.removeClock());
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
players.remove(chr);
|
||||
|
||||
if(players.isEmpty()) {
|
||||
dispose();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
lock.lock();
|
||||
try {
|
||||
players.clear();
|
||||
|
||||
if(timeoutTask != null) {
|
||||
timeoutTask.cancel(false);
|
||||
timeoutTask = null;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
86
src/server/maps/MapleMiniDungeonInfo.java
Normal file
86
src/server/maps/MapleMiniDungeonInfo.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package server.maps;
|
||||
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author SharpAceX(Alan)
|
||||
*/
|
||||
|
||||
public enum MapleMiniDungeonInfo {
|
||||
|
||||
//http://bbb.hidden-street.net/search_finder/mini%20dungeon
|
||||
|
||||
CAVE_OF_MUSHROOMS(105050100, 105050101, 30),
|
||||
GOLEM_CASTLE_RUINS(105040304, 105040320, 34),
|
||||
HILL_OF_SANDSTORMS(260020600, 260020630, 30),
|
||||
HENESYS_PIG_FARM(100020000, 100020100, 30),
|
||||
DRAKES_BLUE_CAVE(105090311, 105090320, 30),
|
||||
DRUMMER_BUNNYS_LAIR(221023400, 221023401, 30),
|
||||
THE_ROUND_TABLE_OF_KENTARUS(240020500, 240020512, 30),
|
||||
THE_RESTORING_MEMORY(240040511, 240040800, 19),
|
||||
NEWT_SECURED_ZONE(240040520, 240040900, 19),
|
||||
PILLAGE_OF_TREASURE_ISLAND(251010402, 251010410, 30),
|
||||
LONGEST_RIDE_ON_BYEBYE_STATION(551030000, 551030001, 19);
|
||||
|
||||
private int baseId;
|
||||
private int dungeonId;
|
||||
private int dungeons;
|
||||
|
||||
private MapleMiniDungeonInfo(int baseId, int dungeonId, int dungeons) {
|
||||
this.baseId = baseId;
|
||||
this.dungeonId = dungeonId;
|
||||
this.dungeons = dungeons;
|
||||
}
|
||||
|
||||
public int getBase() {
|
||||
return baseId;
|
||||
}
|
||||
|
||||
public int getDungeonId() {
|
||||
return dungeonId;
|
||||
}
|
||||
|
||||
public int getDungeons() {
|
||||
return dungeons;
|
||||
}
|
||||
|
||||
public static boolean isDungeonMap(int map){
|
||||
for (MapleMiniDungeonInfo dungeon : MapleMiniDungeonInfo.values()){
|
||||
if (map >= dungeon.getDungeonId() && map <= dungeon.getDungeonId() + dungeon.getDungeons()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static MapleMiniDungeonInfo getDungeon(int map){
|
||||
for (MapleMiniDungeonInfo dungeon : MapleMiniDungeonInfo.values()){
|
||||
if (map >= dungeon.getDungeonId() && map <= dungeon.getDungeonId() + dungeon.getDungeons()){
|
||||
return dungeon;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user