Reformat and clean up "net" package
This commit is contained in:
@@ -29,7 +29,7 @@ public abstract class AbstractPacketHandler implements PacketHandler {
|
||||
public boolean validateState(Client c) {
|
||||
return c.isLoggedIn();
|
||||
}
|
||||
|
||||
|
||||
protected static long currentServerTime() {
|
||||
return Server.getInstance().getCurrentTime();
|
||||
}
|
||||
|
||||
@@ -60,10 +60,7 @@ public final class PacketProcessor {
|
||||
return null;
|
||||
}
|
||||
PacketHandler handler = handlers[packetId];
|
||||
if (handler != null) {
|
||||
return handler;
|
||||
}
|
||||
return null;
|
||||
return handler;
|
||||
}
|
||||
|
||||
public void registerHandler(RecvOpcode code, PacketHandler handler) {
|
||||
|
||||
@@ -36,15 +36,15 @@ import java.security.NoSuchAlgorithmException;
|
||||
public class MapleAESOFB {
|
||||
private static final Logger log = LoggerFactory.getLogger(MapleAESOFB.class);
|
||||
private final static SecretKeySpec skey = new SecretKeySpec(
|
||||
new byte[]{
|
||||
0x13, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00,
|
||||
(byte) 0xB4, 0x00, 0x00, 0x00,
|
||||
0x1B, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00,
|
||||
0x33, 0x00, 0x00, 0x00,
|
||||
0x52, 0x00, 0x00, 0x00}, "AES");
|
||||
new byte[]{
|
||||
0x13, 0x00, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00,
|
||||
(byte) 0xB4, 0x00, 0x00, 0x00,
|
||||
0x1B, 0x00, 0x00, 0x00,
|
||||
0x0F, 0x00, 0x00, 0x00,
|
||||
0x33, 0x00, 0x00, 0x00,
|
||||
0x52, 0x00, 0x00, 0x00}, "AES");
|
||||
|
||||
private static final byte[] funnyBytes = new byte[]{
|
||||
(byte) 0xEC, (byte) 0x3F, (byte) 0x77, (byte) 0xA4, (byte) 0x45, (byte) 0xD0, (byte) 0x71, (byte) 0xBF,
|
||||
|
||||
@@ -23,7 +23,7 @@ package net.opcodes;
|
||||
|
||||
public enum RecvOpcode {
|
||||
CUSTOM_PACKET(0x3713),//13 37 lol
|
||||
|
||||
|
||||
LOGIN_PASSWORD(0x01),
|
||||
GUEST_LOGIN(0x02),
|
||||
SERVERLIST_REREQUEST(0x04),
|
||||
@@ -203,10 +203,10 @@ public enum RecvOpcode {
|
||||
MTS_OPERATION(0xFD),
|
||||
USE_MAPLELIFE(0x100),
|
||||
USE_HAMMER(0x104);
|
||||
|
||||
|
||||
private int code = -2;
|
||||
|
||||
private RecvOpcode(int code) {
|
||||
RecvOpcode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@ public enum SendOpcode {
|
||||
CONFIRM_EULA_RESULT(0x05),
|
||||
CHECK_PINCODE(0x06),
|
||||
UPDATE_PINCODE(0x07),
|
||||
|
||||
|
||||
VIEW_ALL_CHAR(0x08),
|
||||
SELECT_CHARACTER_BY_VAC(0x09),
|
||||
|
||||
|
||||
SERVERLIST(0x0A),
|
||||
CHARLIST(0x0B),
|
||||
SERVER_IP(0x0C),
|
||||
@@ -51,7 +51,7 @@ public enum SendOpcode {
|
||||
LAST_CONNECTED_WORLD(0x1A),
|
||||
RECOMMENDED_WORLD_MESSAGE(0x1B),
|
||||
CHECK_SPW_RESULT(0x1C),
|
||||
|
||||
|
||||
/*CWvsContext::OnPacket*/
|
||||
INVENTORY_OPERATION(0x1D),
|
||||
INVENTORY_GROW(0x1E),
|
||||
@@ -91,16 +91,16 @@ public enum SendOpcode {
|
||||
INCUBATOR_RESULT(0x45),
|
||||
SHOP_SCANNER_RESULT(0x46),
|
||||
SHOP_LINK_RESULT(0x47),
|
||||
|
||||
|
||||
MARRIAGE_REQUEST(0x48),
|
||||
MARRIAGE_RESULT(0x49),
|
||||
WEDDING_GIFT_RESULT(0x4A),
|
||||
NOTIFY_MARRIED_PARTNER_MAP_TRANSFER(0x4B),
|
||||
|
||||
|
||||
CASH_PET_FOOD_RESULT(0x4C),
|
||||
SET_WEEK_EVENT_MESSAGE(0x4D),
|
||||
SET_POTION_DISCOUNT_RATE(0x4E),
|
||||
|
||||
|
||||
BRIDLE_MOB_CATCH_FAIL(0x4F),
|
||||
IMITATED_NPC_RESULT(0x50),
|
||||
IMITATED_NPC_DATA(0x51),
|
||||
@@ -116,7 +116,7 @@ public enum SendOpcode {
|
||||
PARTY_VALUE(0x5B),
|
||||
FIELD_SET_VARIABLE(0x5C),
|
||||
BONUS_EXP_CHANGED(0x5D),//pendant of spirit etc (guess, not sure about the opcode in v83)
|
||||
|
||||
|
||||
FAMILY_CHART_RESULT(0x5E),
|
||||
FAMILY_INFO_RESULT(0x5F),
|
||||
FAMILY_RESULT(0x60),
|
||||
@@ -128,7 +128,7 @@ public enum SendOpcode {
|
||||
FAMILY_NOTIFY_LOGIN_OR_LOGOUT(0x66), //? is logged in. LOLWUT
|
||||
FAMILY_SET_PRIVILEGE(0x67),
|
||||
FAMILY_SUMMON_REQUEST(0x68),
|
||||
|
||||
|
||||
NOTIFY_LEVELUP(0x69),
|
||||
NOTIFY_MARRIAGE(0x6A),
|
||||
NOTIFY_JOB_CHANGE(0x6B),
|
||||
@@ -149,12 +149,12 @@ public enum SendOpcode {
|
||||
SCRIPT_PROGRESS_MESSAGE(0x7A),
|
||||
DATA_CRC_CHECK_FAILED(0x7B),
|
||||
MACRO_SYS_DATA_INIT(0x7C),
|
||||
|
||||
|
||||
/*CStage::OnPacket*/
|
||||
SET_FIELD(0x7D),
|
||||
SET_ITC(0x7E),
|
||||
SET_CASH_SHOP(0x7F),
|
||||
|
||||
|
||||
/*CField::OnPacket*/
|
||||
SET_BACK_EFFECT(0x80),
|
||||
SET_MAP_OBJECT_VISIBLE(0x81),//CMapLoadable::OnSetMapObjectVisible O_O
|
||||
@@ -166,7 +166,7 @@ public enum SendOpcode {
|
||||
WHISPER(0x87),
|
||||
SPOUSE_CHAT(0x88),
|
||||
SUMMON_ITEM_INAVAILABLE(0x89), //You can't use it in this map
|
||||
|
||||
|
||||
FIELD_EFFECT(0x8A),
|
||||
FIELD_OBSTACLE_ONOFF(0x8B),
|
||||
FIELD_OBSTACLE_ONOFF_LIST(0x8C),
|
||||
@@ -197,7 +197,7 @@ public enum SendOpcode {
|
||||
UPDATE_CHAR_BOX(0xA5),
|
||||
SHOW_CONSUME_EFFECT(0xA6),
|
||||
SHOW_SCROLL_EFFECT(0xA7),
|
||||
|
||||
|
||||
SPAWN_PET(0xA8),
|
||||
MOVE_PET(0xAA),
|
||||
PET_CHAT(0xAB),
|
||||
@@ -299,7 +299,7 @@ public enum SendOpcode {
|
||||
MONSTER_CARNIVAL_MESSAGE(0x125),
|
||||
MONSTER_CARNIVAL_DIED(0x126),
|
||||
MONSTER_CARNIVAL_LEAVE(0x127),
|
||||
|
||||
|
||||
ARIANT_ARENA_USER_SCORE(0x129),
|
||||
SHEEP_RANCH_INFO(0x12B),
|
||||
SHEEP_RANCH_CLOTHES(0x12C),
|
||||
@@ -317,18 +317,18 @@ public enum SendOpcode {
|
||||
RPS_GAME(0x138),
|
||||
MESSENGER(0x139),
|
||||
PLAYER_INTERACTION(0x13A),
|
||||
|
||||
|
||||
TOURNAMENT(0x13B),
|
||||
TOURNAMENT_MATCH_TABLE(0x13C),
|
||||
TOURNAMENT_SET_PRIZE(0x13D),
|
||||
TOURNAMENT_UEW(0x13E),
|
||||
TOURNAMENT_CHARACTERS(0x13F),//they never coded this :|
|
||||
|
||||
|
||||
WEDDING_PROGRESS(0x140),//byte step, int groomid, int brideid
|
||||
WEDDING_CEREMONY_END(0x141),
|
||||
|
||||
|
||||
PARCEL(0x142),
|
||||
|
||||
|
||||
CHARGE_PARAM_RESULT(0x143),
|
||||
QUERY_CASH_RESULT(0x144),
|
||||
CASHSHOP_OPERATION(0x145),
|
||||
@@ -341,7 +341,7 @@ public enum SendOpcode {
|
||||
CASHSHOP_GACHAPON_STAMP_RESULT(0x14C),
|
||||
CASHSHOP_CASH_ITEM_GACHAPON_RESULT(0x14D),
|
||||
CASHSHOP_CASH_GACHAPON_OPEN_RESULT(0x14E),
|
||||
|
||||
|
||||
KEYMAP(0x14F),
|
||||
AUTO_HP_POT(0x150),
|
||||
AUTO_MP_POT(0x151),
|
||||
@@ -356,7 +356,7 @@ public enum SendOpcode {
|
||||
VEGA_SCROLL(0x166);
|
||||
private int code = -2;
|
||||
|
||||
private SendOpcode(int code) {
|
||||
SendOpcode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,15 +33,14 @@ import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Danny//changed to map :3
|
||||
* @author Ronan//debuffs to storage as well
|
||||
*/
|
||||
public class PlayerBuffStorage {
|
||||
private int id = (int) (Math.random() * 100);
|
||||
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.BUFF_STORAGE, true);
|
||||
private Map<Integer, List<PlayerBuffValueHolder>> buffs = new HashMap<>();
|
||||
private Map<Integer, Map<Disease, Pair<Long, MobSkill>>> diseases = new HashMap<>();
|
||||
private final int id = (int) (Math.random() * 100);
|
||||
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.BUFF_STORAGE, true);
|
||||
private final Map<Integer, List<PlayerBuffValueHolder>> buffs = new HashMap<>();
|
||||
private final Map<Integer, Map<Disease, Pair<Long, MobSkill>>> diseases = new HashMap<>();
|
||||
|
||||
public void addBuffsToStorage(int chrid, List<PlayerBuffValueHolder> toStore) {
|
||||
lock.lock();
|
||||
@@ -60,7 +59,7 @@ public class PlayerBuffStorage {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addDiseasesToStorage(int chrid, Map<Disease, Pair<Long, MobSkill>> toStore) {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -99,9 +98,6 @@ public class PlayerBuffStorage {
|
||||
return false;
|
||||
}
|
||||
final PlayerBuffStorage other = (PlayerBuffStorage) obj;
|
||||
if (id != other.id) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return id == other.id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ package net.server;
|
||||
import server.StatEffect;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Danny
|
||||
*/
|
||||
public class PlayerBuffValueHolder {
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
package net.server;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Danny
|
||||
*/
|
||||
public class PlayerCoolDownValueHolder {
|
||||
|
||||
@@ -29,8 +29,8 @@ public class PlayerDiseaseValueHolder {//Thanks Celino
|
||||
public Disease disease;
|
||||
|
||||
public PlayerDiseaseValueHolder(final Disease disease, final long startTime, final long length) {
|
||||
this.disease = disease;
|
||||
this.startTime = startTime;
|
||||
this.length = length;
|
||||
this.disease = disease;
|
||||
this.startTime = startTime;
|
||||
this.length = length;
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,8 @@ public class PlayerStorage {
|
||||
private final MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.PLAYER_STORAGE, true);
|
||||
private final Map<Integer, Character> storage = new LinkedHashMap<>();
|
||||
private final Map<String, Character> nameStorage = new LinkedHashMap<>();
|
||||
private MonitoredReadLock rlock = MonitoredReadLockFactory.createLock(locks);
|
||||
private MonitoredWriteLock wlock = MonitoredWriteLockFactory.createLock(locks);
|
||||
private final MonitoredReadLock rlock = MonitoredReadLockFactory.createLock(locks);
|
||||
private final MonitoredWriteLock wlock = MonitoredWriteLockFactory.createLock(locks);
|
||||
|
||||
public void addPlayer(Character chr) {
|
||||
wlock.lock();
|
||||
@@ -45,16 +45,18 @@ public class PlayerStorage {
|
||||
storage.put(chr.getId(), chr);
|
||||
nameStorage.put(chr.getName().toLowerCase(), chr);
|
||||
} finally {
|
||||
wlock.unlock();
|
||||
}
|
||||
wlock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Character removePlayer(int chr) {
|
||||
wlock.lock();
|
||||
try {
|
||||
Character mc = storage.remove(chr);
|
||||
if(mc != null) nameStorage.remove(mc.getName().toLowerCase());
|
||||
|
||||
if (mc != null) {
|
||||
nameStorage.remove(mc.getName().toLowerCase());
|
||||
}
|
||||
|
||||
return mc;
|
||||
} finally {
|
||||
wlock.unlock();
|
||||
@@ -62,7 +64,7 @@ public class PlayerStorage {
|
||||
}
|
||||
|
||||
public Character getCharacterByName(String name) {
|
||||
rlock.lock();
|
||||
rlock.lock();
|
||||
try {
|
||||
return nameStorage.get(name.toLowerCase());
|
||||
} finally {
|
||||
@@ -71,7 +73,7 @@ public class PlayerStorage {
|
||||
}
|
||||
|
||||
public Character getCharacterById(int id) {
|
||||
rlock.lock();
|
||||
rlock.lock();
|
||||
try {
|
||||
return storage.get(id);
|
||||
} finally {
|
||||
@@ -90,28 +92,28 @@ public class PlayerStorage {
|
||||
|
||||
public final void disconnectAll() {
|
||||
List<Character> chrList;
|
||||
rlock.lock();
|
||||
try {
|
||||
rlock.lock();
|
||||
try {
|
||||
chrList = new ArrayList<>(storage.values());
|
||||
} finally {
|
||||
rlock.unlock();
|
||||
}
|
||||
|
||||
for(Character mc : chrList) {
|
||||
} finally {
|
||||
rlock.unlock();
|
||||
}
|
||||
|
||||
for (Character mc : chrList) {
|
||||
Client client = mc.getClient();
|
||||
if(client != null) {
|
||||
if (client != null) {
|
||||
client.forceDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wlock.lock();
|
||||
try {
|
||||
try {
|
||||
storage.clear();
|
||||
} finally {
|
||||
wlock.unlock();
|
||||
}
|
||||
} finally {
|
||||
wlock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getSize() {
|
||||
rlock.lock();
|
||||
try {
|
||||
|
||||
@@ -96,14 +96,14 @@ public class Server {
|
||||
private static final List<Integer> activeCoupons = new LinkedList<>();
|
||||
|
||||
private LoginServer loginServer;
|
||||
private List<Map<Integer, String>> channels = new LinkedList<>();
|
||||
private List<World> worlds = new ArrayList<>();
|
||||
private final List<Map<Integer, String>> channels = new LinkedList<>();
|
||||
private final List<World> worlds = new ArrayList<>();
|
||||
private final Properties subnetInfo = new Properties();
|
||||
private final Map<Integer, Set<Integer>> accountChars = new HashMap<>();
|
||||
private final Map<Integer, Short> accountCharacterCount = new HashMap<>();
|
||||
private final Map<Integer, Integer> worldChars = new HashMap<>();
|
||||
private final Map<String, Integer> transitioningChars = new HashMap<>();
|
||||
private List<Pair<Integer, String>> worldRecommendedList = new LinkedList<>();
|
||||
private final List<Pair<Integer, String>> worldRecommendedList = new LinkedList<>();
|
||||
private final Map<Integer, Guild> guilds = new HashMap<>(100);
|
||||
private final Map<Client, Long> inLoginState = new HashMap<>(100);
|
||||
|
||||
@@ -1613,7 +1613,7 @@ public class Server {
|
||||
String reason = Character.checkWorldTransferEligibility(con, characterId, oldWorld, newWorld); //check if character is still eligible
|
||||
if (reason != null) {
|
||||
removedTransfers.add(nameChangeId);
|
||||
FilePrinter.print(FilePrinter.WORLD_TRANSFER, "World transfer cancelled : Character ID " + characterId + " at " + Calendar.getInstance().getTime().toString() + ", Reason : " + reason);
|
||||
FilePrinter.print(FilePrinter.WORLD_TRANSFER, "World transfer cancelled : Character ID " + characterId + " at " + Calendar.getInstance().getTime() + ", Reason : " + reason);
|
||||
try (PreparedStatement delPs = con.prepareStatement("DELETE FROM worldtransfers WHERE id = ?")) {
|
||||
delPs.setInt(1, nameChangeId);
|
||||
delPs.executeUpdate();
|
||||
|
||||
@@ -20,28 +20,27 @@
|
||||
package net.server.audit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Ronan
|
||||
*/
|
||||
public class LockCollector {
|
||||
|
||||
|
||||
private static final LockCollector instance = new LockCollector();
|
||||
|
||||
|
||||
public static LockCollector getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Map<Runnable, Integer> disposableLocks = new HashMap<>(200);
|
||||
|
||||
private final Map<Runnable, Integer> disposableLocks = new HashMap<>(200);
|
||||
private final Lock lock = new ReentrantLock(true);
|
||||
|
||||
|
||||
public void registerDisposeAction(Runnable r) {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -50,15 +49,15 @@ public class LockCollector {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void runLockCollector() {
|
||||
List<Runnable> toDispose = new ArrayList<>();
|
||||
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
for(Entry<Runnable, Integer> e : disposableLocks.entrySet()) {
|
||||
for (Entry<Runnable, Integer> e : disposableLocks.entrySet()) {
|
||||
Integer eVal = e.getValue();
|
||||
if(eVal > 5) { // updates each 2min
|
||||
if (eVal > 5) { // updates each 2min
|
||||
toDispose.add(e.getKey());
|
||||
} else {
|
||||
disposableLocks.put(e.getKey(), ++eVal);
|
||||
@@ -67,8 +66,8 @@ public class LockCollector {
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
for(Runnable r : toDispose) {
|
||||
|
||||
for (Runnable r : toDispose) {
|
||||
r.run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,121 +33,120 @@ import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*
|
||||
* <p>
|
||||
* This tool has the main purpose of auditing deadlocks throughout the server and must be used only for debugging. The flag is USE_THREAD_TRACKER.
|
||||
*/
|
||||
public class ThreadTracker {
|
||||
private static ThreadTracker instance = null;
|
||||
|
||||
|
||||
public static ThreadTracker getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ThreadTracker();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
private final Lock ttLock = new ReentrantLock(true);
|
||||
|
||||
|
||||
private final Map<Long, List<MonitoredLockType>> threadTracker = new HashMap<>();
|
||||
private final Map<Long, Integer> threadUpdate = new HashMap<>();
|
||||
private final Map<Long, Thread> threads = new HashMap<>();
|
||||
|
||||
|
||||
private final Map<Long, AtomicInteger> lockCount = new HashMap<>();
|
||||
private final Map<Long, MonitoredLockType> lockIds = new HashMap<>();
|
||||
private final Map<Long, Long> lockThreads = new HashMap<>();
|
||||
private final Map<Long, Integer> lockUpdate = new HashMap<>();
|
||||
|
||||
|
||||
private final Map<MonitoredLockType, Map<Long, Integer>> locks = new HashMap<>();
|
||||
ScheduledFuture<?> threadTrackerSchedule;
|
||||
|
||||
|
||||
private String printThreadTrackerState(String dateFormat) {
|
||||
|
||||
|
||||
Map<MonitoredLockType, List<Integer>> lockValues = new HashMap<>();
|
||||
Set<Long> executingThreads = new HashSet<>();
|
||||
|
||||
for(Map.Entry<Long, AtomicInteger> lc : lockCount.entrySet()) {
|
||||
if(lc.getValue().get() != 0) {
|
||||
|
||||
for (Map.Entry<Long, AtomicInteger> lc : lockCount.entrySet()) {
|
||||
if (lc.getValue().get() != 0) {
|
||||
executingThreads.add(lockThreads.get(lc.getKey()));
|
||||
|
||||
|
||||
MonitoredLockType lockId = lockIds.get(lc.getKey());
|
||||
List<Integer> list = lockValues.get(lockId);
|
||||
|
||||
if(list == null) {
|
||||
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
lockValues.put(lockId, list);
|
||||
}
|
||||
|
||||
|
||||
list.add(lc.getValue().get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
String s = "----------------------------\r\n" + dateFormat + "\r\n ";
|
||||
s += "Lock-thread usage count:";
|
||||
for(Map.Entry<MonitoredLockType, List<Integer>> lock : lockValues.entrySet()) {
|
||||
for (Map.Entry<MonitoredLockType, List<Integer>> lock : lockValues.entrySet()) {
|
||||
s += ("\r\n " + lock.getKey().name() + ": ");
|
||||
|
||||
for(Integer i : lock.getValue()) {
|
||||
|
||||
for (Integer i : lock.getValue()) {
|
||||
s += (i + " ");
|
||||
}
|
||||
}
|
||||
s += "\r\n\r\nThread opened lock path:";
|
||||
|
||||
for(Long tid : executingThreads) {
|
||||
|
||||
for (Long tid : executingThreads) {
|
||||
s += "\r\n";
|
||||
for(MonitoredLockType lockid : threadTracker.get(tid)) {
|
||||
for (MonitoredLockType lockid : threadTracker.get(tid)) {
|
||||
s += (lockid.name() + " ");
|
||||
}
|
||||
s += "|";
|
||||
}
|
||||
|
||||
|
||||
s += "\r\n\r\n";
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
private static String printThreadLog(List<MonitoredLockType> stillLockedPath, String dateFormat) {
|
||||
String s = "----------------------------\r\n" + dateFormat + "\r\n ";
|
||||
for(MonitoredLockType lock : stillLockedPath) {
|
||||
for (MonitoredLockType lock : stillLockedPath) {
|
||||
s += (lock.name() + " ");
|
||||
}
|
||||
s += "\r\n\r\n";
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
private static String printThreadStack(StackTraceElement[] list, String dateFormat) {
|
||||
String s = "----------------------------\r\n" + dateFormat + "\r\n";
|
||||
for (StackTraceElement stackTraceElement : list) {
|
||||
s += (" " + stackTraceElement.toString() + "\r\n");
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
public void accessThreadTracker(boolean update, boolean lock, MonitoredLockType lockId, long lockOid) {
|
||||
ttLock.lock();
|
||||
try {
|
||||
if(update) {
|
||||
if(!lock) { // update tracker
|
||||
if (update) {
|
||||
if (!lock) { // update tracker
|
||||
List<Long> toRemove = new ArrayList<>();
|
||||
|
||||
for(Long l : threadUpdate.keySet()) {
|
||||
for (Long l : threadUpdate.keySet()) {
|
||||
int next = threadUpdate.get(l) + 1;
|
||||
if(next == 4) {
|
||||
if (next == 4) {
|
||||
List<MonitoredLockType> tt = threadTracker.get(l);
|
||||
|
||||
if(tt.isEmpty()) {
|
||||
if (tt.isEmpty()) {
|
||||
toRemove.add(l);
|
||||
} else {
|
||||
StackTraceElement[] ste = threads.get(l).getStackTrace();
|
||||
if(ste.length > 0) {
|
||||
if (ste.length > 0) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
String df = dateFormat.format(new Date());
|
||||
|
||||
|
||||
FilePrinter.print(FilePrinter.DEADLOCK_LOCKS, printThreadLog(tt, df));
|
||||
FilePrinter.print(FilePrinter.DEADLOCK_STACK, printThreadStack(ste, df));
|
||||
}
|
||||
@@ -157,29 +156,29 @@ public class ThreadTracker {
|
||||
threadUpdate.put(l, next);
|
||||
}
|
||||
|
||||
for(Long l : toRemove) {
|
||||
for (Long l : toRemove) {
|
||||
threadTracker.remove(l);
|
||||
threadUpdate.remove(l);
|
||||
threads.remove(l);
|
||||
|
||||
for(Map<Long, Integer> threadLock : locks.values()) {
|
||||
for (Map<Long, Integer> threadLock : locks.values()) {
|
||||
threadLock.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
toRemove.clear();
|
||||
|
||||
for(Entry<Long, Integer> it : lockUpdate.entrySet()) {
|
||||
for (Entry<Long, Integer> it : lockUpdate.entrySet()) {
|
||||
int val = it.getValue() + 1;
|
||||
|
||||
if(val < 60) {
|
||||
if (val < 60) {
|
||||
lockUpdate.put(it.getKey(), val);
|
||||
} else {
|
||||
toRemove.add(it.getKey()); // free the structure after 60 silent updates
|
||||
}
|
||||
}
|
||||
|
||||
for(Long l : toRemove) {
|
||||
for (Long l : toRemove) {
|
||||
lockCount.remove(l);
|
||||
lockIds.remove(l);
|
||||
lockThreads.remove(l);
|
||||
@@ -195,9 +194,9 @@ public class ThreadTracker {
|
||||
} else {
|
||||
long tid = Thread.currentThread().getId();
|
||||
|
||||
if(lock) {
|
||||
if (lock) {
|
||||
AtomicInteger c = lockCount.get(lockOid);
|
||||
if(c == null) {
|
||||
if (c == null) {
|
||||
c = new AtomicInteger(0);
|
||||
lockCount.put(lockOid, c);
|
||||
lockIds.put(lockOid, lockId);
|
||||
@@ -207,40 +206,39 @@ public class ThreadTracker {
|
||||
c.incrementAndGet();
|
||||
|
||||
List<MonitoredLockType> list = threadTracker.get(tid);
|
||||
if(list == null) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>(5);
|
||||
threadTracker.put(tid, list);
|
||||
threadUpdate.put(tid, 0);
|
||||
threads.put(tid, Thread.currentThread());
|
||||
} else if(list.isEmpty()) {
|
||||
} else if (list.isEmpty()) {
|
||||
threadUpdate.put(tid, 0);
|
||||
}
|
||||
list.add(lockId);
|
||||
|
||||
Map<Long, Integer> threadLock = locks.get(lockId);
|
||||
if(threadLock == null) {
|
||||
if (threadLock == null) {
|
||||
threadLock = new HashMap<>(5);
|
||||
locks.put(lockId, threadLock);
|
||||
}
|
||||
|
||||
Integer lc = threadLock.get(tid);
|
||||
if(lc != null) {
|
||||
if (lc != null) {
|
||||
threadLock.put(tid, lc + 1);
|
||||
} else {
|
||||
threadLock.put(tid, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
AtomicInteger c = lockCount.get(lockOid);
|
||||
if (c != null) { // thanks BHB for detecting an NPE here
|
||||
c.decrementAndGet();
|
||||
}
|
||||
|
||||
|
||||
lockUpdate.put(lockOid, 0);
|
||||
|
||||
List<MonitoredLockType> list = threadTracker.get(tid);
|
||||
for(int i = list.size() - 1; i >= 0; i--) {
|
||||
if(lockId.equals(list.get(i))) {
|
||||
for (int i = list.size() - 1; i >= 0; i--) {
|
||||
if (lockId.equals(list.get(i))) {
|
||||
list.remove(i);
|
||||
break;
|
||||
}
|
||||
@@ -254,25 +252,25 @@ public class ThreadTracker {
|
||||
ttLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String printLockStatus(MonitoredLockType lockId) {
|
||||
String s = "";
|
||||
|
||||
for(Long threadid : locks.get(lockId).keySet()) {
|
||||
for(MonitoredLockType lockid : threadTracker.get(threadid)) {
|
||||
|
||||
for (Long threadid : locks.get(lockId).keySet()) {
|
||||
for (MonitoredLockType lockid : threadTracker.get(threadid)) {
|
||||
s += (" " + lockid.name());
|
||||
}
|
||||
|
||||
|
||||
s += " |\r\n";
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
public void registerThreadTrackerTask() {
|
||||
threadTrackerSchedule = TimerManager.getInstance().register(() -> accessThreadTracker(true, false, MonitoredLockType.UNDEFINED, -1), 10000, 10000);
|
||||
}
|
||||
|
||||
|
||||
public void cancelThreadTrackerTask() {
|
||||
threadTrackerSchedule.cancel(false);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
package net.server.audit.locks;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
|
||||
|
||||
@@ -20,17 +20,16 @@
|
||||
package net.server.audit.locks;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public interface MonitoredReadLock {
|
||||
|
||||
|
||||
void lock();
|
||||
|
||||
|
||||
void unlock();
|
||||
|
||||
|
||||
boolean tryLock();
|
||||
|
||||
|
||||
MonitoredReadLock dispose();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,17 +20,16 @@
|
||||
package net.server.audit.locks;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public interface MonitoredReentrantLock {
|
||||
|
||||
|
||||
void lock();
|
||||
|
||||
|
||||
void unlock();
|
||||
|
||||
|
||||
boolean tryLock();
|
||||
|
||||
|
||||
MonitoredReentrantLock dispose();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,27 +22,26 @@ package net.server.audit.locks;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class MonitoredReentrantReadWriteLock extends ReentrantReadWriteLock {
|
||||
public final MonitoredLockType id;
|
||||
|
||||
|
||||
public MonitoredReentrantReadWriteLock(MonitoredLockType id) {
|
||||
super();
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
public MonitoredReentrantReadWriteLock(MonitoredLockType id, boolean fair) {
|
||||
super(fair);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReadLock readLock() {
|
||||
return super.readLock();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WriteLock writeLock() {
|
||||
return super.writeLock();
|
||||
|
||||
@@ -20,17 +20,16 @@
|
||||
package net.server.audit.locks;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public interface MonitoredWriteLock {
|
||||
|
||||
|
||||
void lock();
|
||||
|
||||
|
||||
void unlock();
|
||||
|
||||
|
||||
boolean tryLock();
|
||||
|
||||
|
||||
MonitoredWriteLock dispose();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class TrackerReadLock extends ReentrantReadWriteLock.ReadLock implements MonitoredReadLock {
|
||||
@@ -47,17 +46,17 @@ public class TrackerReadLock extends ReentrantReadWriteLock.ReadLock implements
|
||||
private final int hashcode;
|
||||
private final Lock state = new ReentrantLock(true);
|
||||
private final AtomicInteger reentrantCount = new AtomicInteger(0);
|
||||
|
||||
|
||||
public TrackerReadLock(MonitoredReentrantReadWriteLock lock) {
|
||||
super(lock);
|
||||
this.id = lock.id;
|
||||
hashcode = this.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (deadlockedState != null) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
@@ -68,24 +67,24 @@ public class TrackerReadLock extends ReentrantReadWriteLock.ReadLock implements
|
||||
|
||||
registerLocking();
|
||||
}
|
||||
|
||||
|
||||
super.lock();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unlock() {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
unregisterLocking();
|
||||
}
|
||||
|
||||
|
||||
super.unlock();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
if(super.tryLock()) {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
if (super.tryLock()) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (deadlockedState != null) {
|
||||
//FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState));
|
||||
ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode);
|
||||
deadlockedState = null;
|
||||
@@ -98,13 +97,13 @@ public class TrackerReadLock extends ReentrantReadWriteLock.ReadLock implements
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerLocking() {
|
||||
state.lock();
|
||||
try {
|
||||
ThreadTracker.getInstance().accessThreadTracker(false, true, id, hashcode);
|
||||
|
||||
if(reentrantCount.incrementAndGet() == 1) {
|
||||
|
||||
if (reentrantCount.incrementAndGet() == 1) {
|
||||
final Thread t = Thread.currentThread();
|
||||
timeoutSchedule = TimerManager.getInstance().schedule(() -> issueDeadlock(t), YamlConfig.config.server.LOCK_MONITOR_TIME);
|
||||
}
|
||||
@@ -112,51 +111,51 @@ public class TrackerReadLock extends ReentrantReadWriteLock.ReadLock implements
|
||||
state.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void unregisterLocking() {
|
||||
state.lock();
|
||||
try {
|
||||
if(reentrantCount.decrementAndGet() == 0) {
|
||||
if(timeoutSchedule != null) {
|
||||
if (reentrantCount.decrementAndGet() == 0) {
|
||||
if (timeoutSchedule != null) {
|
||||
timeoutSchedule.cancel(false);
|
||||
timeoutSchedule = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ThreadTracker.getInstance().accessThreadTracker(false, false, id, hashcode);
|
||||
} finally {
|
||||
state.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void issueDeadlock(Thread t) {
|
||||
deadlockedState = t.getStackTrace();
|
||||
//super.unlock();
|
||||
}
|
||||
|
||||
|
||||
private static String printStackTrace(StackTraceElement[] list) {
|
||||
String s = "";
|
||||
for (StackTraceElement stackTraceElement : list) {
|
||||
s += (" " + stackTraceElement.toString() + "\r\n");
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MonitoredReadLock dispose() {
|
||||
state.lock();
|
||||
try {
|
||||
if(timeoutSchedule != null) {
|
||||
if (timeoutSchedule != null) {
|
||||
timeoutSchedule.cancel(false);
|
||||
timeoutSchedule = null;
|
||||
}
|
||||
|
||||
|
||||
reentrantCount.set(Integer.MAX_VALUE);
|
||||
} finally {
|
||||
state.unlock();
|
||||
}
|
||||
|
||||
|
||||
//unlock();
|
||||
return new EmptyReadLock(id);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class TrackerReentrantLock extends ReentrantLock implements MonitoredReentrantLock {
|
||||
@@ -45,23 +44,23 @@ public class TrackerReentrantLock extends ReentrantLock implements MonitoredReen
|
||||
private final int hashcode;
|
||||
private final Lock state = new ReentrantLock(true);
|
||||
private final AtomicInteger reentrantCount = new AtomicInteger(0);
|
||||
|
||||
|
||||
public TrackerReentrantLock(MonitoredLockType id) {
|
||||
super();
|
||||
this.id = id;
|
||||
hashcode = this.hashCode();
|
||||
}
|
||||
|
||||
|
||||
public TrackerReentrantLock(MonitoredLockType id, boolean fair) {
|
||||
super(fair);
|
||||
this.id = id;
|
||||
hashcode = this.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (deadlockedState != null) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
@@ -72,24 +71,24 @@ public class TrackerReentrantLock extends ReentrantLock implements MonitoredReen
|
||||
|
||||
registerLocking();
|
||||
}
|
||||
|
||||
|
||||
super.lock();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unlock() {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
unregisterLocking();
|
||||
}
|
||||
|
||||
|
||||
super.unlock();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
if(super.tryLock()) {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
if (super.tryLock()) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (deadlockedState != null) {
|
||||
//FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState));
|
||||
ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode);
|
||||
deadlockedState = null;
|
||||
@@ -102,13 +101,13 @@ public class TrackerReentrantLock extends ReentrantLock implements MonitoredReen
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerLocking() {
|
||||
state.lock();
|
||||
try {
|
||||
ThreadTracker.getInstance().accessThreadTracker(false, true, id, hashcode);
|
||||
|
||||
if(reentrantCount.incrementAndGet() == 1) {
|
||||
|
||||
if (reentrantCount.incrementAndGet() == 1) {
|
||||
final Thread t = Thread.currentThread();
|
||||
timeoutSchedule = TimerManager.getInstance().schedule(() -> issueDeadlock(t), YamlConfig.config.server.LOCK_MONITOR_TIME);
|
||||
}
|
||||
@@ -116,51 +115,51 @@ public class TrackerReentrantLock extends ReentrantLock implements MonitoredReen
|
||||
state.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void unregisterLocking() {
|
||||
state.lock();
|
||||
try {
|
||||
if(reentrantCount.decrementAndGet() == 0) {
|
||||
if(timeoutSchedule != null) {
|
||||
if (reentrantCount.decrementAndGet() == 0) {
|
||||
if (timeoutSchedule != null) {
|
||||
timeoutSchedule.cancel(false);
|
||||
timeoutSchedule = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ThreadTracker.getInstance().accessThreadTracker(false, false, id, hashcode);
|
||||
} finally {
|
||||
state.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void issueDeadlock(Thread t) {
|
||||
deadlockedState = t.getStackTrace();
|
||||
//super.unlock();
|
||||
}
|
||||
|
||||
|
||||
private static String printStackTrace(StackTraceElement[] list) {
|
||||
String s = "";
|
||||
for (StackTraceElement stackTraceElement : list) {
|
||||
s += (" " + stackTraceElement.toString() + "\r\n");
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MonitoredReentrantLock dispose() {
|
||||
state.lock();
|
||||
try {
|
||||
if(timeoutSchedule != null) {
|
||||
if (timeoutSchedule != null) {
|
||||
timeoutSchedule.cancel(false);
|
||||
timeoutSchedule = null;
|
||||
}
|
||||
|
||||
|
||||
reentrantCount.set(Integer.MAX_VALUE);
|
||||
} finally {
|
||||
state.unlock();
|
||||
}
|
||||
|
||||
|
||||
//unlock();
|
||||
return new EmptyReentrantLock(id);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class TrackerWriteLock extends ReentrantReadWriteLock.WriteLock implements MonitoredWriteLock {
|
||||
@@ -53,11 +52,11 @@ public class TrackerWriteLock extends ReentrantReadWriteLock.WriteLock implement
|
||||
this.id = lock.id;
|
||||
hashcode = this.hashCode();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (deadlockedState != null) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
|
||||
@@ -68,24 +67,24 @@ public class TrackerWriteLock extends ReentrantReadWriteLock.WriteLock implement
|
||||
|
||||
registerLocking();
|
||||
}
|
||||
|
||||
|
||||
super.lock();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unlock() {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
unregisterLocking();
|
||||
}
|
||||
|
||||
|
||||
super.unlock();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
if(super.tryLock()) {
|
||||
if(YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if(deadlockedState != null) {
|
||||
if (super.tryLock()) {
|
||||
if (YamlConfig.config.server.USE_THREAD_TRACKER) {
|
||||
if (deadlockedState != null) {
|
||||
//FilePrinter.printError(FilePrinter.DEADLOCK_ERROR, "Deadlock occurred when trying to use the '" + id.name() + "' lock resources:\r\n" + printStackTrace(deadlockedState));
|
||||
ThreadTracker.getInstance().accessThreadTracker(true, true, id, hashcode);
|
||||
deadlockedState = null;
|
||||
@@ -98,13 +97,13 @@ public class TrackerWriteLock extends ReentrantReadWriteLock.WriteLock implement
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void registerLocking() {
|
||||
state.lock();
|
||||
try {
|
||||
ThreadTracker.getInstance().accessThreadTracker(false, true, id, hashcode);
|
||||
|
||||
if(reentrantCount.incrementAndGet() == 1) {
|
||||
|
||||
if (reentrantCount.incrementAndGet() == 1) {
|
||||
final Thread t = Thread.currentThread();
|
||||
timeoutSchedule = TimerManager.getInstance().schedule(() -> issueDeadlock(t), YamlConfig.config.server.LOCK_MONITOR_TIME);
|
||||
}
|
||||
@@ -112,51 +111,51 @@ public class TrackerWriteLock extends ReentrantReadWriteLock.WriteLock implement
|
||||
state.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void unregisterLocking() {
|
||||
state.lock();
|
||||
try {
|
||||
if(reentrantCount.decrementAndGet() == 0) {
|
||||
if(timeoutSchedule != null) {
|
||||
if (reentrantCount.decrementAndGet() == 0) {
|
||||
if (timeoutSchedule != null) {
|
||||
timeoutSchedule.cancel(false);
|
||||
timeoutSchedule = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ThreadTracker.getInstance().accessThreadTracker(false, false, id, hashcode);
|
||||
} finally {
|
||||
state.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void issueDeadlock(Thread t) {
|
||||
deadlockedState = t.getStackTrace();
|
||||
//super.unlock();
|
||||
}
|
||||
|
||||
|
||||
private static String printStackTrace(StackTraceElement[] list) {
|
||||
String s = "";
|
||||
for (StackTraceElement stackTraceElement : list) {
|
||||
s += (" " + stackTraceElement.toString() + "\r\n");
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MonitoredWriteLock dispose() {
|
||||
state.lock();
|
||||
try {
|
||||
if(timeoutSchedule != null) {
|
||||
if (timeoutSchedule != null) {
|
||||
timeoutSchedule.cancel(false);
|
||||
timeoutSchedule = null;
|
||||
}
|
||||
|
||||
|
||||
reentrantCount.set(Integer.MAX_VALUE);
|
||||
} finally {
|
||||
state.unlock();
|
||||
}
|
||||
|
||||
|
||||
//unlock();
|
||||
return new EmptyWriteLock(id);
|
||||
}
|
||||
|
||||
@@ -6,19 +6,19 @@ import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public abstract class AbstractEmptyLock {
|
||||
|
||||
|
||||
protected static String printThreadStack(StackTraceElement[] list) {
|
||||
DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); // DRY-code opportunity performed by jtumidanski
|
||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
||||
String df = dateFormat.format(new Date());
|
||||
|
||||
|
||||
String s = "\r\n" + df + "\r\n";
|
||||
for (StackTraceElement stackTraceElement : list) {
|
||||
s += (" " + stackTraceElement.toString() + "\r\n");
|
||||
}
|
||||
s += "----------------------------\r\n\r\n";
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -24,30 +24,29 @@ import net.server.audit.locks.MonitoredReadLock;
|
||||
import tools.FilePrinter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class EmptyReadLock extends AbstractEmptyLock implements MonitoredReadLock {
|
||||
private final MonitoredLockType id;
|
||||
|
||||
|
||||
public EmptyReadLock(MonitoredLockType type) {
|
||||
this.id = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
FilePrinter.printError(FilePrinter.DISPOSED_LOCKS, "Captured locking tentative on disposed lock " + id + ":" + printThreadStack(Thread.currentThread().getStackTrace()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unlock() {}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
FilePrinter.printError(FilePrinter.DISPOSED_LOCKS, "Captured try-locking tentative on disposed lock " + id + ":" + printThreadStack(Thread.currentThread().getStackTrace()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MonitoredReadLock dispose() {
|
||||
return this;
|
||||
|
||||
@@ -24,30 +24,29 @@ import net.server.audit.locks.MonitoredReentrantLock;
|
||||
import tools.FilePrinter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class EmptyReentrantLock extends AbstractEmptyLock implements MonitoredReentrantLock {
|
||||
private final MonitoredLockType id;
|
||||
|
||||
|
||||
public EmptyReentrantLock(MonitoredLockType type) {
|
||||
this.id = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
FilePrinter.printError(FilePrinter.DISPOSED_LOCKS, "Captured locking tentative on disposed lock " + id + ":" + printThreadStack(Thread.currentThread().getStackTrace()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unlock() {}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
FilePrinter.printError(FilePrinter.DISPOSED_LOCKS, "Captured try-locking tentative on disposed lock " + id + ":" + printThreadStack(Thread.currentThread().getStackTrace()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MonitoredReentrantLock dispose() {
|
||||
return this;
|
||||
|
||||
@@ -24,30 +24,29 @@ import net.server.audit.locks.MonitoredWriteLock;
|
||||
import tools.FilePrinter;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class EmptyWriteLock extends AbstractEmptyLock implements MonitoredWriteLock {
|
||||
private final MonitoredLockType id;
|
||||
|
||||
|
||||
public EmptyWriteLock(MonitoredLockType type) {
|
||||
this.id = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void lock() {
|
||||
FilePrinter.printError(FilePrinter.DISPOSED_LOCKS, "Captured locking tentative on disposed lock " + id + ":" + printThreadStack(Thread.currentThread().getStackTrace()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void unlock() {}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean tryLock() {
|
||||
FilePrinter.printError(FilePrinter.DISPOSED_LOCKS, "Captured try-locking tentative on disposed lock " + id + ":" + printThreadStack(Thread.currentThread().getStackTrace()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MonitoredWriteLock dispose() {
|
||||
return this;
|
||||
|
||||
@@ -23,7 +23,6 @@ import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||
import net.server.audit.locks.active.TrackerReadLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class MonitoredReadLockFactory {
|
||||
|
||||
@@ -23,14 +23,13 @@ import net.server.audit.locks.MonitoredLockType;
|
||||
import net.server.audit.locks.active.TrackerReentrantLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class MonitoredReentrantLockFactory {
|
||||
public static TrackerReentrantLock createLock(MonitoredLockType id) {
|
||||
return new TrackerReentrantLock(id);
|
||||
}
|
||||
|
||||
|
||||
public static TrackerReentrantLock createLock(MonitoredLockType id, boolean fair) {
|
||||
return new TrackerReentrantLock(id, fair);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import net.server.audit.locks.MonitoredReentrantReadWriteLock;
|
||||
import net.server.audit.locks.active.TrackerWriteLock;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class MonitoredWriteLockFactory {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,6 @@
|
||||
package net.server.channel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Frz
|
||||
*/
|
||||
public class CharacterIdChannelPair {
|
||||
|
||||
@@ -57,16 +57,18 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
public boolean ranged, magic;
|
||||
public int speed = 4;
|
||||
public Point position = new Point();
|
||||
|
||||
|
||||
public StatEffect getAttackEffect(Character chr, Skill theSkill) {
|
||||
Skill mySkill = theSkill;
|
||||
if (mySkill == null) {
|
||||
mySkill = SkillFactory.getSkill(skill);
|
||||
}
|
||||
|
||||
|
||||
int skillLevel = chr.getSkillLevel(mySkill);
|
||||
if(skillLevel == 0 && GameConstants.isPqSkillMap(chr.getMapId()) && GameConstants.isPqSkill(mySkill.getId())) skillLevel = 1;
|
||||
|
||||
if (skillLevel == 0 && GameConstants.isPqSkillMap(chr.getMapId()) && GameConstants.isPqSkill(mySkill.getId())) {
|
||||
skillLevel = 1;
|
||||
}
|
||||
|
||||
if (skillLevel == 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -85,7 +87,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
if (map.isOwnershipRestricted(player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Skill theSkill = null;
|
||||
StatEffect attackEffect = null;
|
||||
final int job = player.getJob().getId();
|
||||
@@ -108,20 +110,20 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
int mobCount = attackEffect.getMobCount();
|
||||
if (attack.skill != Cleric.HEAL) {
|
||||
if (player.isAlive()) {
|
||||
if(attack.skill == Aran.BODY_PRESSURE || attack.skill == Marauder.ENERGY_CHARGE || attack.skill == ThunderBreaker.ENERGY_CHARGE) { // thanks IxianMace for noticing Energy Charge skills refreshing on touch
|
||||
if (attack.skill == Aran.BODY_PRESSURE || attack.skill == Marauder.ENERGY_CHARGE || attack.skill == ThunderBreaker.ENERGY_CHARGE) { // thanks IxianMace for noticing Energy Charge skills refreshing on touch
|
||||
// prevent touch dmg skills refreshing
|
||||
} else if(attack.skill == DawnWarrior.FINAL_ATTACK || attack.skill == WindArcher.FINAL_ATTACK) {
|
||||
} else if (attack.skill == DawnWarrior.FINAL_ATTACK || attack.skill == WindArcher.FINAL_ATTACK) {
|
||||
// prevent cygnus FA refreshing
|
||||
mobCount = 15;
|
||||
} else if(attack.skill == NightWalker.POISON_BOMB) {// Poison Bomb
|
||||
} else if (attack.skill == NightWalker.POISON_BOMB) {// Poison Bomb
|
||||
attackEffect.applyTo(player, new Point(attack.position.x, attack.position.y));
|
||||
} else {
|
||||
attackEffect.applyTo(player);
|
||||
|
||||
|
||||
if (attack.skill == Page.FINAL_ATTACK_BW || attack.skill == Page.FINAL_ATTACK_SWORD || attack.skill == Fighter.FINAL_ATTACK_SWORD
|
||||
|| attack.skill == Fighter.FINAL_ATTACK_AXE || attack.skill == Spearman.FINAL_ATTACK_SPEAR || attack.skill == Spearman.FINAL_ATTACK_POLEARM
|
||||
|| attack.skill == Hunter.FINAL_ATTACK || attack.skill == Crossbowman.FINAL_ATTACK) {
|
||||
|
||||
|
||||
mobCount = 15;//:(
|
||||
} else if (attack.skill == Aran.HIDDEN_FULL_DOUBLE || attack.skill == Aran.HIDDEN_FULL_TRIPLE || attack.skill == Aran.HIDDEN_OVER_DOUBLE || attack.skill == Aran.HIDDEN_OVER_TRIPLE) {
|
||||
mobCount = 12;
|
||||
@@ -131,7 +133,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
player.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (attack.numAttacked > mobCount) {
|
||||
AutobanFactory.MOB_COUNT.autoban(player, "Skill: " + attack.skill + "; Count: " + attack.numAttacked + " Max: " + attackEffect.getMobCount());
|
||||
return;
|
||||
@@ -145,7 +147,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
/*if (attackCount != attack.numDamage && attack.skill != ChiefBandit.MESO_EXPLOSION && attack.skill != NightWalker.VAMPIRE && attack.skill != WindArcher.WIND_SHOT && attack.skill != Aran.COMBO_SMASH && attack.skill != Aran.COMBO_FENRIR && attack.skill != Aran.COMBO_TEMPEST && attack.skill != NightLord.NINJA_AMBUSH && attack.skill != Shadower.NINJA_AMBUSH) {
|
||||
return;
|
||||
}*/
|
||||
|
||||
|
||||
int totDamage = 0;
|
||||
|
||||
if (attack.skill == ChiefBandit.MESO_EXPLOSION) {
|
||||
@@ -154,30 +156,30 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
MapObject mapobject = map.getMapObject(oned);
|
||||
if (mapobject != null && mapobject.getType() == MapObjectType.ITEM) {
|
||||
final MapItem mapitem = (MapItem) mapobject;
|
||||
if (mapitem.getMeso() == 0) { //Maybe it is possible some how?
|
||||
if (mapitem.getMeso() == 0) { //Maybe it is possible some how?
|
||||
return;
|
||||
}
|
||||
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
TimerManager.getInstance().schedule(() -> {
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
map.pickItemDrop(PacketCreator.removeItemFromMap(mapitem.getObjectId(), 4, 0), mapitem);
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
TimerManager.getInstance().schedule(() -> {
|
||||
mapitem.lockItem();
|
||||
try {
|
||||
if (mapitem.isPickedUp()) {
|
||||
return;
|
||||
}
|
||||
}, delay);
|
||||
delay += 100;
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
}
|
||||
map.pickItemDrop(PacketCreator.removeItemFromMap(mapitem.getObjectId(), 4, 0), mapitem);
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
}
|
||||
}, delay);
|
||||
delay += 100;
|
||||
} finally {
|
||||
mapitem.unlockItem();
|
||||
}
|
||||
} else if (mapobject != null && mapobject.getType() != MapObjectType.MONSTER) {
|
||||
return;
|
||||
}
|
||||
@@ -185,42 +187,42 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
for (Integer oned : attack.allDamage.keySet()) {
|
||||
final Monster monster = map.getMonsterByOid(oned);
|
||||
if (monster != null) {
|
||||
if (monster != null) {
|
||||
double distance = player.getPosition().distanceSq(monster.getPosition());
|
||||
double distanceToDetect = 200000.0;
|
||||
|
||||
if(attack.ranged)
|
||||
|
||||
if (attack.ranged) {
|
||||
distanceToDetect += 400000;
|
||||
|
||||
if(attack.magic)
|
||||
}
|
||||
|
||||
if (attack.magic) {
|
||||
distanceToDetect += 200000;
|
||||
|
||||
if(player.getJob().isA(Job.ARAN1))
|
||||
}
|
||||
|
||||
if (player.getJob().isA(Job.ARAN1)) {
|
||||
distanceToDetect += 200000; // Arans have extra range over normal warriors.
|
||||
|
||||
if(attack.skill == Aran.COMBO_SMASH || attack.skill == Aran.BODY_PRESSURE)
|
||||
}
|
||||
|
||||
if (attack.skill == Aran.COMBO_SMASH || attack.skill == Aran.BODY_PRESSURE) {
|
||||
distanceToDetect += 40000;
|
||||
|
||||
else if(attack.skill == Bishop.GENESIS || attack.skill == ILArchMage.BLIZZARD || attack.skill == FPArchMage.METEOR_SHOWER)
|
||||
} else if (attack.skill == Bishop.GENESIS || attack.skill == ILArchMage.BLIZZARD || attack.skill == FPArchMage.METEOR_SHOWER) {
|
||||
distanceToDetect += 275000;
|
||||
|
||||
else if(attack.skill == Hero.BRANDISH || attack.skill == DragonKnight.SPEAR_CRUSHER || attack.skill == DragonKnight.POLE_ARM_CRUSHER)
|
||||
} else if (attack.skill == Hero.BRANDISH || attack.skill == DragonKnight.SPEAR_CRUSHER || attack.skill == DragonKnight.POLE_ARM_CRUSHER) {
|
||||
distanceToDetect += 40000;
|
||||
|
||||
else if(attack.skill == DragonKnight.DRAGON_ROAR || attack.skill == SuperGM.SUPER_DRAGON_ROAR)
|
||||
} else if (attack.skill == DragonKnight.DRAGON_ROAR || attack.skill == SuperGM.SUPER_DRAGON_ROAR) {
|
||||
distanceToDetect += 250000;
|
||||
|
||||
else if(attack.skill == Shadower.BOOMERANG_STEP)
|
||||
} else if (attack.skill == Shadower.BOOMERANG_STEP) {
|
||||
distanceToDetect += 60000;
|
||||
|
||||
}
|
||||
|
||||
if (distance > distanceToDetect) {
|
||||
AutobanFactory.DISTANCE_HACK.alert(player, "Distance Sq to monster: " + distance + " SID: " + attack.skill + " MID: " + monster.getId());
|
||||
monster.refreshMobPosition();
|
||||
}
|
||||
|
||||
|
||||
int totDamageToOneMonster = 0;
|
||||
List<Integer> onedList = attack.allDamage.get(oned);
|
||||
|
||||
|
||||
if (attack.magic) { // thanks BHB, Alex (CanIGetaPR) for noticing no immunity status check here
|
||||
if (monster.isBuffed(MonsterStatus.MAGIC_IMMUNITY)) {
|
||||
Collections.fill(onedList, 1);
|
||||
@@ -230,7 +232,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
Collections.fill(onedList, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (GameConstants.isDojoBoss(monster.getId())) {
|
||||
if (attack.skill == 1009 || attack.skill == 10001009 || attack.skill == 20001009) {
|
||||
int dmgLimit = (int) Math.ceil(0.3 * monster.getMaxHp());
|
||||
@@ -238,13 +240,15 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
for (Integer i : onedList) {
|
||||
_onedList.add(i < dmgLimit ? i : dmgLimit);
|
||||
}
|
||||
|
||||
|
||||
onedList = _onedList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Integer eachd : onedList) {
|
||||
if(eachd < 0) eachd += Integer.MAX_VALUE;
|
||||
if (eachd < 0) {
|
||||
eachd += Integer.MAX_VALUE;
|
||||
}
|
||||
totDamageToOneMonster += eachd;
|
||||
}
|
||||
totDamage += totDamageToOneMonster;
|
||||
@@ -252,18 +256,19 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
if (player.getBuffedValue(BuffStat.PICKPOCKET) != null && (attack.skill == 0 || attack.skill == Rogue.DOUBLE_STAB || attack.skill == Bandit.SAVAGE_BLOW || attack.skill == ChiefBandit.ASSAULTER || attack.skill == ChiefBandit.BAND_OF_THIEVES || attack.skill == Shadower.ASSASSINATE || attack.skill == Shadower.TAUNT || attack.skill == Shadower.BOOMERANG_STEP)) {
|
||||
Skill pickpocket = SkillFactory.getSkill(ChiefBandit.PICKPOCKET);
|
||||
int picklv = (player.isGM()) ? pickpocket.getMaxLevel() : player.getSkillLevel(pickpocket);
|
||||
if(picklv > 0) {
|
||||
if (picklv > 0) {
|
||||
int delay = 0;
|
||||
final int maxmeso = player.getBuffedValue(BuffStat.PICKPOCKET);
|
||||
for (Integer eachd : onedList) {
|
||||
for (Integer eachd : onedList) {
|
||||
eachd += Integer.MAX_VALUE;
|
||||
|
||||
if (pickpocket.getEffect(picklv).makeChanceResult()) {
|
||||
final int eachdf;
|
||||
if(eachd < 0)
|
||||
eachdf = eachd + Integer.MAX_VALUE;
|
||||
else
|
||||
eachdf = eachd;
|
||||
if (eachd < 0) {
|
||||
eachdf = eachd + Integer.MAX_VALUE;
|
||||
} else {
|
||||
eachdf = eachd;
|
||||
}
|
||||
|
||||
TimerManager.getInstance().schedule(() -> map.spawnMesoDrop(Math.min((int) Math.max(((double) eachdf / (double) 20000) * (double) maxmeso, 1), maxmeso), new Point((int) (monster.getPosition().getX() + Randomizer.nextInt(100) - 50), (int) (monster.getPosition().getY())), monster, player, true, (byte) 2), delay);
|
||||
delay += 100;
|
||||
@@ -277,18 +282,20 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
if (monster.getStolen().size() < 1) { // One steal per mob <3
|
||||
if (steal.getEffect(player.getSkillLevel(steal)).makeChanceResult()) {
|
||||
monster.addStolen(0);
|
||||
|
||||
|
||||
MonsterInformationProvider mi = MonsterInformationProvider.getInstance();
|
||||
List<Integer> dropPool = mi.retrieveDropPool(monster.getId());
|
||||
if(!dropPool.isEmpty()) {
|
||||
if (!dropPool.isEmpty()) {
|
||||
int rndPool = (int) Math.floor(Math.random() * dropPool.get(dropPool.size() - 1));
|
||||
|
||||
|
||||
int i = 0;
|
||||
while(rndPool >= dropPool.get(i)) i++;
|
||||
|
||||
while (rndPool >= dropPool.get(i)) {
|
||||
i++;
|
||||
}
|
||||
|
||||
List<MonsterDropEntry> toSteal = new ArrayList<>();
|
||||
toSteal.add(mi.retrieveDrop(monster.getId()).get(i));
|
||||
|
||||
|
||||
map.dropItemsFromMonster(toSteal, player, monster);
|
||||
monster.addStolen(toSteal.get(0).itemId);
|
||||
}
|
||||
@@ -311,15 +318,15 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (player.isAran()) {
|
||||
if (player.getBuffedValue(BuffStat.WK_CHARGE) != null) {
|
||||
if (player.getBuffedValue(BuffStat.WK_CHARGE) != null) {
|
||||
Skill snowCharge = SkillFactory.getSkill(Aran.SNOW_CHARGE);
|
||||
if (totDamageToOneMonster > 0) {
|
||||
MonsterStatusEffect monsterStatusEffect = new MonsterStatusEffect(Collections.singletonMap(MonsterStatus.SPEED, snowCharge.getEffect(player.getSkillLevel(snowCharge)).getX()), snowCharge, null, false);
|
||||
monster.applyStatus(player, monsterStatusEffect, false, snowCharge.getEffect(player.getSkillLevel(snowCharge)).getY() * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player.getBuffedValue(BuffStat.HAMSTRING) != null) {
|
||||
Skill hamstring = SkillFactory.getSkill(Bowmaster.HAMSTRING);
|
||||
@@ -348,14 +355,14 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
if (player.isBuffFrom(BuffStat.WK_CHARGE, chargeSkill)) {
|
||||
if (totDamageToOneMonster > 0) {
|
||||
if (charge == WhiteKnight.BW_ICE_CHARGE || charge == WhiteKnight.SWORD_ICE_CHARGE) {
|
||||
monster.setTempEffectiveness(Element.ICE, ElementalEffectiveness.WEAK, chargeSkill.getEffect(player.getSkillLevel(chargeSkill)).getY() * 1000);
|
||||
monster.setTempEffectiveness(Element.ICE, ElementalEffectiveness.WEAK, chargeSkill.getEffect(player.getSkillLevel(chargeSkill)).getY() * 1000);
|
||||
break;
|
||||
}
|
||||
if (charge == WhiteKnight.BW_FIRE_CHARGE || charge == WhiteKnight.SWORD_FIRE_CHARGE) {
|
||||
monster.setTempEffectiveness(Element.FIRE, ElementalEffectiveness.WEAK, chargeSkill.getEffect(player.getSkillLevel(chargeSkill)).getY() * 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (job == 122) {
|
||||
@@ -389,15 +396,15 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (job >= 311 && job <= 322) {
|
||||
if (!monster.isBoss()) {
|
||||
} else if (job >= 311 && job <= 322) {
|
||||
if (!monster.isBoss()) {
|
||||
Skill mortalBlow;
|
||||
if (job == 311 || job == 312) {
|
||||
mortalBlow = SkillFactory.getSkill(Ranger.MORTAL_BLOW);
|
||||
} else {
|
||||
mortalBlow = SkillFactory.getSkill(Sniper.MORTAL_BLOW);
|
||||
}
|
||||
|
||||
|
||||
int skillLevel = player.getSkillLevel(mortalBlow);
|
||||
if (skillLevel > 0) {
|
||||
StatEffect mortal = mortalBlow.getEffect(skillLevel);
|
||||
@@ -407,24 +414,24 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (attack.skill != 0) {
|
||||
if (attackEffect.getFixDamage() != -1) {
|
||||
if (totDamageToOneMonster != attackEffect.getFixDamage() && totDamageToOneMonster != 0) {
|
||||
AutobanFactory.FIX_DAMAGE.autoban(player, totDamageToOneMonster + " damage");
|
||||
}
|
||||
|
||||
|
||||
int threeSnailsId = player.getJobType() * 10000000 + 1000;
|
||||
if(attack.skill == threeSnailsId) {
|
||||
if(YamlConfig.config.server.USE_ULTRA_THREE_SNAILS) {
|
||||
if (attack.skill == threeSnailsId) {
|
||||
if (YamlConfig.config.server.USE_ULTRA_THREE_SNAILS) {
|
||||
int skillLv = player.getSkillLevel(threeSnailsId);
|
||||
|
||||
if(skillLv > 0) {
|
||||
if (skillLv > 0) {
|
||||
AbstractPlayerInteraction api = player.getAbstractPlayerInteraction();
|
||||
|
||||
int shellId;
|
||||
switch(skillLv) {
|
||||
switch (skillLv) {
|
||||
case 1:
|
||||
shellId = 4000019;
|
||||
break;
|
||||
@@ -437,7 +444,7 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
shellId = 4000016;
|
||||
}
|
||||
|
||||
if(api.haveItem(shellId, 1)) {
|
||||
if (api.haveItem(shellId, 1)) {
|
||||
api.gainItem(shellId, (short) -1, false);
|
||||
totDamageToOneMonster *= player.getLevel();
|
||||
} else {
|
||||
@@ -452,36 +459,36 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
if (totDamageToOneMonster > 0 && attackEffect != null) {
|
||||
Map<MonsterStatus, Integer> attackEffectStati = attackEffect.getMonsterStati();
|
||||
if(!attackEffectStati.isEmpty()) {
|
||||
if (!attackEffectStati.isEmpty()) {
|
||||
if (attackEffect.makeChanceResult()) {
|
||||
monster.applyStatus(player, new MonsterStatusEffect(attackEffectStati, theSkill, null, false), attackEffect.isPoison(), attackEffect.getDuration());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (attack.skill == Paladin.HEAVENS_HAMMER) {
|
||||
if(!monster.isBoss()) {
|
||||
if (!monster.isBoss()) {
|
||||
damageMonsterWithSkill(player, map, monster, monster.getHp() - 1, attack.skill, 1777);
|
||||
} else {
|
||||
int HHDmg = (player.calculateMaxBaseDamage(player.getTotalWatk()) * (SkillFactory.getSkill(Paladin.HEAVENS_HAMMER).getEffect(player.getSkillLevel(SkillFactory.getSkill(Paladin.HEAVENS_HAMMER))).getDamage() / 100));
|
||||
damageMonsterWithSkill(player, map, monster, (int) (Math.floor(Math.random() * (HHDmg / 5) + HHDmg * .8)), attack.skill, 1777);
|
||||
}
|
||||
} else if (attack.skill == Aran.COMBO_TEMPEST) {
|
||||
if(!monster.isBoss()) {
|
||||
if (!monster.isBoss()) {
|
||||
damageMonsterWithSkill(player, map, monster, monster.getHp(), attack.skill, 0);
|
||||
} else {
|
||||
int TmpDmg = (player.calculateMaxBaseDamage(player.getTotalWatk()) * (SkillFactory.getSkill(Aran.COMBO_TEMPEST).getEffect(player.getSkillLevel(SkillFactory.getSkill(Aran.COMBO_TEMPEST))).getDamage() / 100));
|
||||
damageMonsterWithSkill(player, map, monster, (int) (Math.floor(Math.random() * (TmpDmg / 5) + TmpDmg * .8)), attack.skill, 0);
|
||||
}
|
||||
} else {
|
||||
if(attack.skill == Aran.BODY_PRESSURE) {
|
||||
if (attack.skill == Aran.BODY_PRESSURE) {
|
||||
map.broadcastMessage(PacketCreator.damageMonster(monster.getObjectId(), totDamageToOneMonster));
|
||||
}
|
||||
|
||||
|
||||
map.damageMonster(player, monster, totDamageToOneMonster);
|
||||
}
|
||||
if (monster.isBuffed(MonsterStatus.WEAPON_REFLECT) && !attack.magic) {
|
||||
List<Pair<Integer, Integer>> mobSkills = monster.getSkills();
|
||||
|
||||
|
||||
for (Pair<Integer, Integer> ms : mobSkills) {
|
||||
if (ms.left == 145) {
|
||||
MobSkill toUse = MobSkillFactory.getMobSkill(ms.left, ms.right);
|
||||
@@ -489,10 +496,10 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
map.broadcastMessage(player, PacketCreator.damagePlayer(0, monster.getId(), player.getId(), toUse.getX(), 0, 0, false, 0, true, monster.getObjectId(), 0, 0), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (monster.isBuffed(MonsterStatus.MAGIC_REFLECT) && attack.magic) {
|
||||
List<Pair<Integer, Integer>> mobSkills = monster.getSkills();
|
||||
|
||||
|
||||
for (Pair<Integer, Integer> ms : mobSkills) {
|
||||
if (ms.left == 145) {
|
||||
MobSkill toUse = MobSkillFactory.getMobSkill(ms.left, ms.right);
|
||||
@@ -510,11 +517,14 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
|
||||
private static void damageMonsterWithSkill(final Character attacker, final MapleMap map, final Monster monster, final int damage, int skillid, int fixedTime) {
|
||||
int animationTime;
|
||||
|
||||
if(fixedTime == 0) animationTime = SkillFactory.getSkill(skillid).getAnimationTime();
|
||||
else animationTime = fixedTime;
|
||||
|
||||
if(animationTime > 0) { // be sure to only use LIMITED ATTACKS with animation time here
|
||||
|
||||
if (fixedTime == 0) {
|
||||
animationTime = SkillFactory.getSkill(skillid).getAnimationTime();
|
||||
} else {
|
||||
animationTime = fixedTime;
|
||||
}
|
||||
|
||||
if (animationTime > 0) { // be sure to only use LIMITED ATTACKS with animation time here
|
||||
TimerManager.getInstance().schedule(() -> {
|
||||
map.broadcastMessage(PacketCreator.damageMonster(monster.getObjectId(), damage), monster.getPosition());
|
||||
map.damageMonster(attacker, monster, damage);
|
||||
@@ -524,9 +534,9 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
map.damageMonster(attacker, monster, damage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected AttackInfo parseDamage(InPacket p, Character chr, boolean ranged, boolean magic) {
|
||||
//2C 00 00 01 91 A1 12 00 A5 57 62 FC E2 75 99 10 00 47 80 01 04 01 C6 CC 02 DD FF 5F 00
|
||||
//2C 00 00 01 91 A1 12 00 A5 57 62 FC E2 75 99 10 00 47 80 01 04 01 C6 CC 02 DD FF 5F 00
|
||||
AttackInfo ret = new AttackInfo();
|
||||
p.readByte();
|
||||
ret.numAttackedAndDamage = p.readByte();
|
||||
@@ -536,18 +546,20 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
ret.skill = p.readInt();
|
||||
ret.ranged = ranged;
|
||||
ret.magic = magic;
|
||||
|
||||
|
||||
if (ret.skill > 0) {
|
||||
ret.skilllevel = chr.getSkillLevel(ret.skill);
|
||||
if(ret.skilllevel == 0 && GameConstants.isPqSkillMap(chr.getMapId()) && GameConstants.isPqSkill(ret.skill)) ret.skilllevel = 1;
|
||||
if (ret.skilllevel == 0 && GameConstants.isPqSkillMap(chr.getMapId()) && GameConstants.isPqSkill(ret.skill)) {
|
||||
ret.skilllevel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ret.skill == Evan.ICE_BREATH || ret.skill == Evan.FIRE_BREATH || ret.skill == FPArchMage.BIG_BANG || ret.skill == ILArchMage.BIG_BANG || ret.skill == Bishop.BIG_BANG || ret.skill == Gunslinger.GRENADE || ret.skill == Brawler.CORKSCREW_BLOW || ret.skill == ThunderBreaker.CORKSCREW_BLOW || ret.skill == NightWalker.POISON_BOMB) {
|
||||
ret.charge = p.readInt();
|
||||
} else {
|
||||
ret.charge = 0;
|
||||
}
|
||||
|
||||
|
||||
p.skip(8);
|
||||
ret.display = p.readByte();
|
||||
ret.direction = p.readByte();
|
||||
@@ -602,56 +614,60 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
ret.speed = p.readByte();
|
||||
p.skip(4);
|
||||
}
|
||||
|
||||
|
||||
// Find the base damage to base futher calculations on.
|
||||
// Several skills have their own formula in this section.
|
||||
long calcDmgMax;
|
||||
|
||||
if(magic && ret.skill != 0) { // thanks onechord for noticing a few false positives stemming from maxdmg as 0
|
||||
|
||||
if (magic && ret.skill != 0) { // thanks onechord for noticing a few false positives stemming from maxdmg as 0
|
||||
calcDmgMax = (long) (Math.ceil((chr.getTotalMagic() * Math.ceil(chr.getTotalMagic() / 1000.0) + chr.getTotalMagic()) / 30.0) + Math.ceil(chr.getTotalInt() / 200.0));
|
||||
} else if(ret.skill == 4001344 || ret.skill == NightWalker.LUCKY_SEVEN || ret.skill == NightLord.TRIPLE_THROW) {
|
||||
} else if (ret.skill == 4001344 || ret.skill == NightWalker.LUCKY_SEVEN || ret.skill == NightLord.TRIPLE_THROW) {
|
||||
calcDmgMax = (long) ((chr.getTotalLuk() * 5) * Math.ceil(chr.getTotalWatk() / 100.0));
|
||||
} else if(ret.skill == DragonKnight.DRAGON_ROAR) {
|
||||
} else if (ret.skill == DragonKnight.DRAGON_ROAR) {
|
||||
calcDmgMax = (long) ((chr.getTotalStr() * 4 + chr.getTotalDex()) * Math.ceil(chr.getTotalWatk() / 100.0));
|
||||
} else if(ret.skill == NightLord.VENOMOUS_STAR || ret.skill == Shadower.VENOMOUS_STAB) {
|
||||
} else if (ret.skill == NightLord.VENOMOUS_STAR || ret.skill == Shadower.VENOMOUS_STAB) {
|
||||
calcDmgMax = (long) (Math.ceil((18.5 * (chr.getTotalStr() + chr.getTotalLuk()) + chr.getTotalDex() * 2) / 100.0) * chr.calculateMaxBaseDamage(chr.getTotalWatk()));
|
||||
} else {
|
||||
calcDmgMax = chr.calculateMaxBaseDamage(chr.getTotalWatk());
|
||||
}
|
||||
|
||||
if(ret.skill != 0) {
|
||||
if (ret.skill != 0) {
|
||||
Skill skill = SkillFactory.getSkill(ret.skill);
|
||||
StatEffect effect = skill.getEffect(ret.skilllevel);
|
||||
|
||||
if (magic) {
|
||||
// Since the skill is magic based, use the magic formula
|
||||
if(chr.getJob() == Job.IL_ARCHMAGE || chr.getJob() == Job.IL_MAGE) {
|
||||
if (chr.getJob() == Job.IL_ARCHMAGE || chr.getJob() == Job.IL_MAGE) {
|
||||
int skillLvl = chr.getSkillLevel(ILMage.ELEMENT_AMPLIFICATION);
|
||||
if(skillLvl > 0)
|
||||
if (skillLvl > 0) {
|
||||
calcDmgMax = calcDmgMax * SkillFactory.getSkill(ILMage.ELEMENT_AMPLIFICATION).getEffect(skillLvl).getY() / 100;
|
||||
} else if(chr.getJob() == Job.FP_ARCHMAGE || chr.getJob() == Job.FP_MAGE) {
|
||||
}
|
||||
} else if (chr.getJob() == Job.FP_ARCHMAGE || chr.getJob() == Job.FP_MAGE) {
|
||||
int skillLvl = chr.getSkillLevel(FPMage.ELEMENT_AMPLIFICATION);
|
||||
if(skillLvl > 0)
|
||||
if (skillLvl > 0) {
|
||||
calcDmgMax = calcDmgMax * SkillFactory.getSkill(FPMage.ELEMENT_AMPLIFICATION).getEffect(skillLvl).getY() / 100;
|
||||
} else if(chr.getJob() == Job.BLAZEWIZARD3 || chr.getJob() == Job.BLAZEWIZARD4) {
|
||||
}
|
||||
} else if (chr.getJob() == Job.BLAZEWIZARD3 || chr.getJob() == Job.BLAZEWIZARD4) {
|
||||
int skillLvl = chr.getSkillLevel(BlazeWizard.ELEMENT_AMPLIFICATION);
|
||||
if(skillLvl > 0)
|
||||
if (skillLvl > 0) {
|
||||
calcDmgMax = calcDmgMax * SkillFactory.getSkill(BlazeWizard.ELEMENT_AMPLIFICATION).getEffect(skillLvl).getY() / 100;
|
||||
} else if(chr.getJob() == Job.EVAN7 || chr.getJob() == Job.EVAN8 || chr.getJob() == Job.EVAN9 || chr.getJob() == Job.EVAN10) {
|
||||
}
|
||||
} else if (chr.getJob() == Job.EVAN7 || chr.getJob() == Job.EVAN8 || chr.getJob() == Job.EVAN9 || chr.getJob() == Job.EVAN10) {
|
||||
int skillLvl = chr.getSkillLevel(Evan.MAGIC_AMPLIFICATION);
|
||||
if(skillLvl > 0)
|
||||
if (skillLvl > 0) {
|
||||
calcDmgMax = calcDmgMax * SkillFactory.getSkill(Evan.MAGIC_AMPLIFICATION).getEffect(skillLvl).getY() / 100;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
calcDmgMax *= effect.getMatk();
|
||||
if(ret.skill == Cleric.HEAL) {
|
||||
if (ret.skill == Cleric.HEAL) {
|
||||
// This formula is still a bit wonky, but it is fairly accurate.
|
||||
calcDmgMax = (int) Math.round((chr.getTotalInt() * 4.8 + chr.getTotalLuk() * 4) * chr.getTotalMagic() / 1000);
|
||||
calcDmgMax = calcDmgMax * effect.getHp() / 100;
|
||||
|
||||
calcDmgMax = calcDmgMax * effect.getHp() / 100;
|
||||
|
||||
ret.speed = 7;
|
||||
}
|
||||
} else if(ret.skill == Hermit.SHADOW_MESO) {
|
||||
} else if (ret.skill == Hermit.SHADOW_MESO) {
|
||||
// Shadow Meso also has its own formula
|
||||
calcDmgMax = effect.getMoneyCon() * 10;
|
||||
calcDmgMax = (int) Math.floor(calcDmgMax * 1.5);
|
||||
@@ -662,108 +678,106 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
}
|
||||
|
||||
Integer comboBuff = chr.getBuffedValue(BuffStat.COMBO);
|
||||
if(comboBuff != null && comboBuff > 0) {
|
||||
if (comboBuff != null && comboBuff > 0) {
|
||||
int oid = chr.isCygnus() ? DawnWarrior.COMBO : Crusader.COMBO;
|
||||
int advcomboid = chr.isCygnus() ? DawnWarrior.ADVANCED_COMBO : Hero.ADVANCED_COMBO;
|
||||
|
||||
if(comboBuff > 6) {
|
||||
|
||||
if (comboBuff > 6) {
|
||||
// Advanced Combo
|
||||
StatEffect ceffect = SkillFactory.getSkill(advcomboid).getEffect(chr.getSkillLevel(advcomboid));
|
||||
calcDmgMax = (long) Math.floor(calcDmgMax * (ceffect.getDamage() + 50) / 100 + 0.20 + (comboBuff - 5) * 0.04);
|
||||
} else {
|
||||
// Normal Combo
|
||||
int skillLv = chr.getSkillLevel(oid);
|
||||
if(skillLv <= 0 || chr.isGM()) skillLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
|
||||
if(skillLv > 0) {
|
||||
if (skillLv <= 0 || chr.isGM()) {
|
||||
skillLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
}
|
||||
|
||||
if (skillLv > 0) {
|
||||
StatEffect ceffect = SkillFactory.getSkill(oid).getEffect(skillLv);
|
||||
calcDmgMax = (long) Math.floor(calcDmgMax * (ceffect.getDamage() + 50) / 100 + Math.floor((comboBuff - 1) * (skillLv / 6)) / 100);
|
||||
}
|
||||
}
|
||||
|
||||
if(GameConstants.isFinisherSkill(ret.skill)) {
|
||||
|
||||
if (GameConstants.isFinisherSkill(ret.skill)) {
|
||||
// Finisher skills do more damage based on how many orbs the player has.
|
||||
int orbs = comboBuff - 1;
|
||||
if(orbs == 2)
|
||||
if (orbs == 2) {
|
||||
calcDmgMax *= 1.2;
|
||||
else if(orbs == 3)
|
||||
} else if (orbs == 3) {
|
||||
calcDmgMax *= 1.54;
|
||||
else if(orbs == 4)
|
||||
} else if (orbs == 4) {
|
||||
calcDmgMax *= 2;
|
||||
else if(orbs >= 5)
|
||||
} else if (orbs >= 5) {
|
||||
calcDmgMax *= 2.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(chr.getEnergyBar() == 15000) {
|
||||
|
||||
if (chr.getEnergyBar() == 15000) {
|
||||
int energycharge = chr.isCygnus() ? ThunderBreaker.ENERGY_CHARGE : Marauder.ENERGY_CHARGE;
|
||||
StatEffect ceffect = SkillFactory.getSkill(energycharge).getEffect(chr.getSkillLevel(energycharge));
|
||||
calcDmgMax *= (100 + ceffect.getDamage()) / 100;
|
||||
}
|
||||
|
||||
|
||||
int bonusDmgBuff = 100;
|
||||
for (PlayerBuffValueHolder pbvh : chr.getAllBuffs()) {
|
||||
int bonusDmg = pbvh.effect.getDamage() - 100;
|
||||
bonusDmgBuff += bonusDmg;
|
||||
}
|
||||
|
||||
|
||||
if (bonusDmgBuff != 100) {
|
||||
float dmgBuff = bonusDmgBuff / 100.0f;
|
||||
calcDmgMax = (long) Math.ceil(calcDmgMax * dmgBuff);
|
||||
}
|
||||
|
||||
if(chr.getMapId() >= 914000000 && chr.getMapId() <= 914000500) {
|
||||
|
||||
if (chr.getMapId() >= 914000000 && chr.getMapId() <= 914000500) {
|
||||
calcDmgMax += 80000; // Aran Tutorial.
|
||||
}
|
||||
|
||||
boolean canCrit = false;
|
||||
if(chr.getJob().isA((Job.BOWMAN)) || chr.getJob().isA(Job.THIEF) || chr.getJob().isA(Job.NIGHTWALKER1) || chr.getJob().isA(Job.WINDARCHER1) || chr.getJob() == Job.ARAN3 || chr.getJob() == Job.ARAN4 || chr.getJob() == Job.MARAUDER || chr.getJob() == Job.BUCCANEER) {
|
||||
canCrit = true;
|
||||
}
|
||||
|
||||
if(chr.getBuffEffect(BuffStat.SHARP_EYES) != null) {
|
||||
boolean canCrit = chr.getJob().isA((Job.BOWMAN)) || chr.getJob().isA(Job.THIEF) || chr.getJob().isA(Job.NIGHTWALKER1) || chr.getJob().isA(Job.WINDARCHER1) || chr.getJob() == Job.ARAN3 || chr.getJob() == Job.ARAN4 || chr.getJob() == Job.MARAUDER || chr.getJob() == Job.BUCCANEER;
|
||||
|
||||
if (chr.getBuffEffect(BuffStat.SHARP_EYES) != null) {
|
||||
// Any class that has sharp eyes can crit. Also, since it stacks with normal crit go ahead
|
||||
// and calc it in.
|
||||
|
||||
canCrit = true;
|
||||
calcDmgMax *= 1.4;
|
||||
}
|
||||
|
||||
boolean shadowPartner = false;
|
||||
if(chr.getBuffEffect(BuffStat.SHADOWPARTNER) != null) {
|
||||
shadowPartner = true;
|
||||
}
|
||||
|
||||
if(ret.skill != 0) {
|
||||
|
||||
boolean shadowPartner = chr.getBuffEffect(BuffStat.SHADOWPARTNER) != null;
|
||||
|
||||
if (ret.skill != 0) {
|
||||
int fixed = ret.getAttackEffect(chr, SkillFactory.getSkill(ret.skill)).getFixDamage();
|
||||
if(fixed > 0)
|
||||
if (fixed > 0) {
|
||||
calcDmgMax = fixed;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ret.numAttacked; i++) {
|
||||
int oid = p.readInt();
|
||||
p.skip(14);
|
||||
List<Integer> allDamageNumbers = new ArrayList<>();
|
||||
Monster monster = chr.getMap().getMonsterByOid(oid);
|
||||
|
||||
if(chr.getBuffEffect(BuffStat.WK_CHARGE) != null) {
|
||||
|
||||
if (chr.getBuffEffect(BuffStat.WK_CHARGE) != null) {
|
||||
// Charge, so now we need to check elemental effectiveness
|
||||
int sourceID = chr.getBuffSource(BuffStat.WK_CHARGE);
|
||||
int level = chr.getBuffedValue(BuffStat.WK_CHARGE);
|
||||
if(monster != null) {
|
||||
if(sourceID == WhiteKnight.BW_FIRE_CHARGE || sourceID == WhiteKnight.SWORD_FIRE_CHARGE) {
|
||||
if(monster.getStats().getEffectiveness(Element.FIRE) == ElementalEffectiveness.WEAK) {
|
||||
if (monster != null) {
|
||||
if (sourceID == WhiteKnight.BW_FIRE_CHARGE || sourceID == WhiteKnight.SWORD_FIRE_CHARGE) {
|
||||
if (monster.getStats().getEffectiveness(Element.FIRE) == ElementalEffectiveness.WEAK) {
|
||||
calcDmgMax *= 1.05 + level * 0.015;
|
||||
}
|
||||
} else if(sourceID == WhiteKnight.BW_ICE_CHARGE || sourceID == WhiteKnight.SWORD_ICE_CHARGE) {
|
||||
if(monster.getStats().getEffectiveness(Element.ICE) == ElementalEffectiveness.WEAK) {
|
||||
} else if (sourceID == WhiteKnight.BW_ICE_CHARGE || sourceID == WhiteKnight.SWORD_ICE_CHARGE) {
|
||||
if (monster.getStats().getEffectiveness(Element.ICE) == ElementalEffectiveness.WEAK) {
|
||||
calcDmgMax *= 1.05 + level * 0.015;
|
||||
}
|
||||
} else if(sourceID == WhiteKnight.BW_LIT_CHARGE || sourceID == WhiteKnight.SWORD_LIT_CHARGE) {
|
||||
if(monster.getStats().getEffectiveness(Element.LIGHTING) == ElementalEffectiveness.WEAK) {
|
||||
} else if (sourceID == WhiteKnight.BW_LIT_CHARGE || sourceID == WhiteKnight.SWORD_LIT_CHARGE) {
|
||||
if (monster.getStats().getEffectiveness(Element.LIGHTING) == ElementalEffectiveness.WEAK) {
|
||||
calcDmgMax *= 1.05 + level * 0.015;
|
||||
}
|
||||
} else if(sourceID == Paladin.BW_HOLY_CHARGE || sourceID == Paladin.SWORD_HOLY_CHARGE) {
|
||||
if(monster.getStats().getEffectiveness(Element.HOLY) == ElementalEffectiveness.WEAK) {
|
||||
} else if (sourceID == Paladin.BW_HOLY_CHARGE || sourceID == Paladin.SWORD_HOLY_CHARGE) {
|
||||
if (monster.getStats().getEffectiveness(Element.HOLY) == ElementalEffectiveness.WEAK) {
|
||||
calcDmgMax *= 1.2 + level * 0.015;
|
||||
}
|
||||
}
|
||||
@@ -773,92 +787,95 @@ public abstract class AbstractDealDamageHandler extends AbstractPacketHandler {
|
||||
calcDmgMax *= 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret.skill != 0) {
|
||||
Skill skill = SkillFactory.getSkill(ret.skill);
|
||||
if(skill.getElement() != Element.NEUTRAL && chr.getBuffedValue(BuffStat.ELEMENTAL_RESET) == null) {
|
||||
// The skill has an element effect, so we need to factor that in.
|
||||
if(monster != null) {
|
||||
ElementalEffectiveness eff = monster.getElementalEffectiveness(skill.getElement());
|
||||
if(eff == ElementalEffectiveness.WEAK) {
|
||||
calcDmgMax *= 1.5;
|
||||
} else if(eff == ElementalEffectiveness.STRONG) {
|
||||
//calcDmgMax *= 0.5;
|
||||
}
|
||||
} else {
|
||||
// Since we already know the skill has an elemental attribute, but we dont know if the monster is weak or not, lets
|
||||
// take the safe approach and just assume they are weak.
|
||||
|
||||
if (ret.skill != 0) {
|
||||
Skill skill = SkillFactory.getSkill(ret.skill);
|
||||
if (skill.getElement() != Element.NEUTRAL && chr.getBuffedValue(BuffStat.ELEMENTAL_RESET) == null) {
|
||||
// The skill has an element effect, so we need to factor that in.
|
||||
if (monster != null) {
|
||||
ElementalEffectiveness eff = monster.getElementalEffectiveness(skill.getElement());
|
||||
if (eff == ElementalEffectiveness.WEAK) {
|
||||
calcDmgMax *= 1.5;
|
||||
} else if (eff == ElementalEffectiveness.STRONG) {
|
||||
//calcDmgMax *= 0.5;
|
||||
}
|
||||
} else {
|
||||
// Since we already know the skill has an elemental attribute, but we dont know if the monster is weak or not, lets
|
||||
// take the safe approach and just assume they are weak.
|
||||
calcDmgMax *= 1.5;
|
||||
}
|
||||
}
|
||||
if (ret.skill == FPWizard.POISON_BREATH || ret.skill == FPMage.POISON_MIST || ret.skill == FPArchMage.FIRE_DEMON || ret.skill == ILArchMage.ICE_DEMON) {
|
||||
if (monster != null) {
|
||||
// Turns out poison is completely server side, so I don't know why I added this. >.<
|
||||
//calcDmgMax = monster.getHp() / (70 - chr.getSkillLevel(skill));
|
||||
}
|
||||
} else if (ret.skill == Hermit.SHADOW_WEB) {
|
||||
if (monster != null) {
|
||||
calcDmgMax = monster.getHp() / (50 - chr.getSkillLevel(skill));
|
||||
}
|
||||
} else if (ret.skill == Hermit.SHADOW_MESO) {
|
||||
if (monster != null) {
|
||||
monster.debuffMob(Hermit.SHADOW_MESO);
|
||||
}
|
||||
} else if (ret.skill == Aran.BODY_PRESSURE) {
|
||||
if (monster != null) {
|
||||
int bodyPressureDmg = (int) Math.ceil(monster.getMaxHp() * SkillFactory.getSkill(Aran.BODY_PRESSURE).getEffect(ret.skilllevel).getDamage() / 100.0);
|
||||
if (bodyPressureDmg > calcDmgMax) {
|
||||
calcDmgMax = bodyPressureDmg;
|
||||
}
|
||||
}
|
||||
if(ret.skill == FPWizard.POISON_BREATH || ret.skill == FPMage.POISON_MIST || ret.skill == FPArchMage.FIRE_DEMON || ret.skill == ILArchMage.ICE_DEMON) {
|
||||
if(monster != null) {
|
||||
// Turns out poison is completely server side, so I don't know why I added this. >.<
|
||||
//calcDmgMax = monster.getHp() / (70 - chr.getSkillLevel(skill));
|
||||
}
|
||||
} else if(ret.skill == Hermit.SHADOW_WEB) {
|
||||
if(monster != null) {
|
||||
calcDmgMax = monster.getHp() / (50 - chr.getSkillLevel(skill));
|
||||
}
|
||||
} else if(ret.skill == Hermit.SHADOW_MESO) {
|
||||
if(monster != null) {
|
||||
monster.debuffMob(Hermit.SHADOW_MESO);
|
||||
}
|
||||
} else if (ret.skill == Aran.BODY_PRESSURE) {
|
||||
if (monster != null) {
|
||||
int bodyPressureDmg = (int) Math.ceil(monster.getMaxHp() * SkillFactory.getSkill(Aran.BODY_PRESSURE).getEffect(ret.skilllevel).getDamage() / 100.0);
|
||||
if (bodyPressureDmg > calcDmgMax) {
|
||||
calcDmgMax = bodyPressureDmg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int j = 0; j < ret.numDamage; j++) {
|
||||
int damage = p.readInt();
|
||||
long hitDmgMax = calcDmgMax;
|
||||
if(ret.skill == Buccaneer.BARRAGE || ret.skill == ThunderBreaker.BARRAGE) {
|
||||
if(j > 3)
|
||||
hitDmgMax *= Math.pow(2, (j - 3));
|
||||
int damage = p.readInt();
|
||||
long hitDmgMax = calcDmgMax;
|
||||
if (ret.skill == Buccaneer.BARRAGE || ret.skill == ThunderBreaker.BARRAGE) {
|
||||
if (j > 3) {
|
||||
hitDmgMax *= Math.pow(2, (j - 3));
|
||||
}
|
||||
if(shadowPartner) {
|
||||
// For shadow partner, the second half of the hits only do 50% damage. So calc that
|
||||
// in for the crit effects.
|
||||
if(j >= ret.numDamage / 2) {
|
||||
hitDmgMax *= 0.5;
|
||||
}
|
||||
}
|
||||
if (shadowPartner) {
|
||||
// For shadow partner, the second half of the hits only do 50% damage. So calc that
|
||||
// in for the crit effects.
|
||||
if (j >= ret.numDamage / 2) {
|
||||
hitDmgMax *= 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret.skill == Marksman.SNIPE) {
|
||||
damage = 195000 + Randomizer.nextInt(5000);
|
||||
hitDmgMax = 200000;
|
||||
} else if (ret.skill == Beginner.BAMBOO_RAIN || ret.skill == Noblesse.BAMBOO_RAIN || ret.skill == Evan.BAMBOO_THRUST || ret.skill == Legend.BAMBOO_THRUST) {
|
||||
hitDmgMax = 82569000; // 30% of Max HP of strongest Dojo boss
|
||||
}
|
||||
if (ret.skill == Marksman.SNIPE) {
|
||||
damage = 195000 + Randomizer.nextInt(5000);
|
||||
hitDmgMax = 200000;
|
||||
} else if (ret.skill == Beginner.BAMBOO_RAIN || ret.skill == Noblesse.BAMBOO_RAIN || ret.skill == Evan.BAMBOO_THRUST || ret.skill == Legend.BAMBOO_THRUST) {
|
||||
hitDmgMax = 82569000; // 30% of Max HP of strongest Dojo boss
|
||||
}
|
||||
|
||||
long maxWithCrit = hitDmgMax;
|
||||
if(canCrit) // They can crit, so up the max.
|
||||
maxWithCrit *= 2;
|
||||
|
||||
// Warn if the damage is over 1.5x what we calculated above.
|
||||
if(damage > maxWithCrit * 1.5) {
|
||||
AutobanFactory.DAMAGE_HACK.alert(chr, "DMG: " + damage + " MaxDMG: " + maxWithCrit + " SID: " + ret.skill + " MobID: " + (monster != null ? monster.getId() : "null") + " Map: " + chr.getMap().getMapName() + " (" + chr.getMapId() + ")");
|
||||
}
|
||||
long maxWithCrit = hitDmgMax;
|
||||
if (canCrit) // They can crit, so up the max.
|
||||
{
|
||||
maxWithCrit *= 2;
|
||||
}
|
||||
|
||||
// Add a ab point if its over 5x what we calculated.
|
||||
if(damage > maxWithCrit * 5) {
|
||||
AutobanFactory.DAMAGE_HACK.addPoint(chr.getAutobanManager(), "DMG: " + damage + " MaxDMG: " + maxWithCrit + " SID: " + ret.skill + " MobID: " + (monster != null ? monster.getId() : "null") + " Map: " + chr.getMap().getMapName() + " (" + chr.getMapId() + ")");
|
||||
}
|
||||
// Warn if the damage is over 1.5x what we calculated above.
|
||||
if (damage > maxWithCrit * 1.5) {
|
||||
AutobanFactory.DAMAGE_HACK.alert(chr, "DMG: " + damage + " MaxDMG: " + maxWithCrit + " SID: " + ret.skill + " MobID: " + (monster != null ? monster.getId() : "null") + " Map: " + chr.getMap().getMapName() + " (" + chr.getMapId() + ")");
|
||||
}
|
||||
|
||||
if (ret.skill == Marksman.SNIPE || (canCrit && damage > hitDmgMax)) {
|
||||
// If the skill is a crit, inverse the damage to make it show up on clients.
|
||||
damage = -Integer.MAX_VALUE + damage - 1;
|
||||
}
|
||||
// Add a ab point if its over 5x what we calculated.
|
||||
if (damage > maxWithCrit * 5) {
|
||||
AutobanFactory.DAMAGE_HACK.addPoint(chr.getAutobanManager(), "DMG: " + damage + " MaxDMG: " + maxWithCrit + " SID: " + ret.skill + " MobID: " + (monster != null ? monster.getId() : "null") + " Map: " + chr.getMap().getMapName() + " (" + chr.getMapId() + ")");
|
||||
}
|
||||
|
||||
allDamageNumbers.add(damage);
|
||||
if (ret.skill == Marksman.SNIPE || (canCrit && damage > hitDmgMax)) {
|
||||
// If the skill is a crit, inverse the damage to make it show up on clients.
|
||||
damage = -Integer.MAX_VALUE + damage - 1;
|
||||
}
|
||||
|
||||
allDamageNumbers.add(damage);
|
||||
}
|
||||
if (ret.skill != Corsair.RAPID_FIRE || ret.skill != Aran.HIDDEN_FULL_DOUBLE || ret.skill != Aran.HIDDEN_FULL_TRIPLE || ret.skill != Aran.HIDDEN_OVER_DOUBLE || ret.skill != Aran.HIDDEN_OVER_TRIPLE) {
|
||||
p.skip(4);
|
||||
p.skip(4);
|
||||
}
|
||||
ret.allDamage.put(oid, allDamageNumbers);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,9 @@ public abstract class AbstractMovementPacketHandler extends AbstractPacketHandle
|
||||
protected List<LifeMovementFragment> parseMovement(InPacket p) throws EmptyMovementException {
|
||||
List<LifeMovementFragment> res = new ArrayList<>();
|
||||
byte numCommands = p.readByte();
|
||||
if (numCommands < 1) throw new EmptyMovementException(p);
|
||||
if (numCommands < 1) {
|
||||
throw new EmptyMovementException(p);
|
||||
}
|
||||
for (byte i = 0; i < numCommands; i++) {
|
||||
byte command = p.readByte();
|
||||
switch (command) {
|
||||
@@ -138,24 +140,26 @@ public abstract class AbstractMovementPacketHandler extends AbstractPacketHandle
|
||||
throw new EmptyMovementException(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (res.isEmpty()) {
|
||||
throw new EmptyMovementException(p);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
protected void updatePosition(InPacket p, AnimatedMapObject target, int yOffset) throws EmptyMovementException {
|
||||
|
||||
|
||||
byte numCommands = p.readByte();
|
||||
if (numCommands < 1) throw new EmptyMovementException(p);
|
||||
if (numCommands < 1) {
|
||||
throw new EmptyMovementException(p);
|
||||
}
|
||||
for (byte i = 0; i < numCommands; i++) {
|
||||
byte command = p.readByte();
|
||||
switch (command) {
|
||||
case 0: // normal move
|
||||
case 5:
|
||||
case 17: { // Float
|
||||
//Absolute movement - only this is important for the server, other movement can be passed to the client
|
||||
//Absolute movement - only this is important for the server, other movement can be passed to the client
|
||||
short xpos = p.readShort(); //is signed fine here?
|
||||
short ypos = p.readShort();
|
||||
target.setPosition(new Point(xpos, ypos + yOffset));
|
||||
@@ -175,8 +179,8 @@ public abstract class AbstractMovementPacketHandler extends AbstractPacketHandle
|
||||
case 19: // Springs on maps
|
||||
case 20: // Aran Combat Step
|
||||
case 22: {
|
||||
//Relative movement - server only cares about stance
|
||||
p.skip(4); //xpos = lea.readShort(); ypos = lea.readShort();
|
||||
//Relative movement - server only cares about stance
|
||||
p.skip(4); //xpos = lea.readShort(); ypos = lea.readShort();
|
||||
byte newstate = p.readByte();
|
||||
target.setStance(newstate);
|
||||
p.readShort(); //duration
|
||||
@@ -190,8 +194,8 @@ public abstract class AbstractMovementPacketHandler extends AbstractPacketHandle
|
||||
case 11: //chair
|
||||
{
|
||||
// case 14: {
|
||||
//Teleport movement - same as above
|
||||
p.skip(8); //xpos = lea.readShort(); ypos = lea.readShort(); xwobble = lea.readShort(); ywobble = lea.readShort();
|
||||
//Teleport movement - same as above
|
||||
p.skip(8); //xpos = lea.readShort(); ypos = lea.readShort(); xwobble = lea.readShort(); ywobble = lea.readShort();
|
||||
byte newstate = p.readByte();
|
||||
target.setStance(newstate);
|
||||
break;
|
||||
@@ -215,8 +219,8 @@ public abstract class AbstractMovementPacketHandler extends AbstractPacketHandle
|
||||
break;
|
||||
}*/
|
||||
case 15: {
|
||||
//Jump down movement - stance only
|
||||
p.skip(12); //short xpos = lea.readShort(); ypos = lea.readShort(); xwobble = lea.readShort(); ywobble = lea.readShort(); fh = lea.readShort(); ofh = lea.readShort();
|
||||
//Jump down movement - stance only
|
||||
p.skip(12); //short xpos = lea.readShort(); ypos = lea.readShort(); xwobble = lea.readShort(); ywobble = lea.readShort(); fh = lea.readShort(); ofh = lea.readShort();
|
||||
byte newstate = p.readByte();
|
||||
target.setStance(newstate);
|
||||
p.readShort(); // duration
|
||||
|
||||
@@ -41,7 +41,6 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jay Estrella
|
||||
* @author Ubaware
|
||||
*/
|
||||
@@ -49,7 +48,7 @@ public final class AcceptFamilyHandler extends AbstractPacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
if(!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
if (!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
return;
|
||||
}
|
||||
Character chr = c.getPlayer();
|
||||
@@ -58,15 +57,17 @@ public final class AcceptFamilyHandler extends AbstractPacketHandler {
|
||||
boolean accept = p.readByte() != 0;
|
||||
// String inviterName = slea.readMapleAsciiString();
|
||||
Character inviter = c.getWorldServer().getPlayerStorage().getCharacterById(inviterId);
|
||||
if(inviter != null) {
|
||||
if (inviter != null) {
|
||||
InviteResult inviteResult = InviteCoordinator.answerInvite(InviteType.FAMILY, c.getPlayer().getId(), c.getPlayer(), accept);
|
||||
if(inviteResult.result == InviteResultType.NOT_FOUND) return; //was never invited. (or expired on server only somehow?)
|
||||
if(accept) {
|
||||
if(inviter.getFamily() != null) {
|
||||
if(chr.getFamily() == null) {
|
||||
if (inviteResult.result == InviteResultType.NOT_FOUND) {
|
||||
return; //was never invited. (or expired on server only somehow?)
|
||||
}
|
||||
if (accept) {
|
||||
if (inviter.getFamily() != null) {
|
||||
if (chr.getFamily() == null) {
|
||||
FamilyEntry newEntry = new FamilyEntry(inviter.getFamily(), chr.getId(), chr.getName(), chr.getLevel(), chr.getJob());
|
||||
newEntry.setCharacter(chr);
|
||||
if(!newEntry.setSenior(inviter.getFamilyEntry(), true)) {
|
||||
if (!newEntry.setSenior(inviter.getFamilyEntry(), true)) {
|
||||
inviter.sendPacket(PacketCreator.sendFamilyMessage(1, 0));
|
||||
return;
|
||||
} else {
|
||||
@@ -77,8 +78,10 @@ public final class AcceptFamilyHandler extends AbstractPacketHandler {
|
||||
} else { //absorb target family
|
||||
FamilyEntry targetEntry = chr.getFamilyEntry();
|
||||
Family targetFamily = targetEntry.getFamily();
|
||||
if(targetFamily.getLeader() != targetEntry) return;
|
||||
if(inviter.getFamily().getTotalGenerations() + targetFamily.getTotalGenerations() <= YamlConfig.config.server.FAMILY_MAX_GENERATIONS) {
|
||||
if (targetFamily.getLeader() != targetEntry) {
|
||||
return;
|
||||
}
|
||||
if (inviter.getFamily().getTotalGenerations() + targetFamily.getTotalGenerations() <= YamlConfig.config.server.FAMILY_MAX_GENERATIONS) {
|
||||
targetEntry.join(inviter.getFamilyEntry());
|
||||
} else {
|
||||
inviter.sendPacket(PacketCreator.sendFamilyMessage(76, 0));
|
||||
@@ -87,7 +90,7 @@ public final class AcceptFamilyHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
} else { // create new family
|
||||
if(chr.getFamily() != null && inviter.getFamily() != null && chr.getFamily().getTotalGenerations() + inviter.getFamily().getTotalGenerations() >= YamlConfig.config.server.FAMILY_MAX_GENERATIONS) {
|
||||
if (chr.getFamily() != null && inviter.getFamily() != null && chr.getFamily().getTotalGenerations() + inviter.getFamily().getTotalGenerations() >= YamlConfig.config.server.FAMILY_MAX_GENERATIONS) {
|
||||
inviter.sendPacket(PacketCreator.sendFamilyMessage(76, 0));
|
||||
chr.sendPacket(PacketCreator.sendFamilyMessage(76, 0));
|
||||
return;
|
||||
@@ -96,9 +99,9 @@ public final class AcceptFamilyHandler extends AbstractPacketHandler {
|
||||
c.getWorldServer().addFamily(newFamily.getID(), newFamily);
|
||||
FamilyEntry inviterEntry = new FamilyEntry(newFamily, inviter.getId(), inviter.getName(), inviter.getLevel(), inviter.getJob());
|
||||
inviterEntry.setCharacter(inviter);
|
||||
newFamily.setLeader(inviter.getFamilyEntry());
|
||||
newFamily.setLeader(inviter.getFamilyEntry());
|
||||
newFamily.addEntry(inviterEntry);
|
||||
if(chr.getFamily() == null) { //completely new family
|
||||
if (chr.getFamily() == null) { //completely new family
|
||||
FamilyEntry newEntry = new FamilyEntry(newFamily, chr.getId(), chr.getName(), chr.getLevel(), chr.getJob());
|
||||
newEntry.setCharacter(chr);
|
||||
newEntry.setSenior(inviterEntry, true);
|
||||
@@ -107,7 +110,7 @@ public final class AcceptFamilyHandler extends AbstractPacketHandler {
|
||||
insertNewFamilyRecord(chr.getId(), newFamily.getID(), inviter.getId(), false); // char was already saved from setSenior() above
|
||||
newFamily.setMessage("", true);
|
||||
} else { //new family for inviter, absorb invitee family
|
||||
insertNewFamilyRecord(inviter.getId(), newFamily.getID(), 0 , true);
|
||||
insertNewFamilyRecord(inviter.getId(), newFamily.getID(), 0, true);
|
||||
newFamily.setMessage("", true);
|
||||
chr.getFamilyEntry().join(inviterEntry);
|
||||
}
|
||||
@@ -124,27 +127,27 @@ public final class AcceptFamilyHandler extends AbstractPacketHandler {
|
||||
}
|
||||
|
||||
private static void insertNewFamilyRecord(int characterID, int familyID, int seniorID, boolean updateChar) {
|
||||
try(Connection con = DatabaseConnection.getConnection()) {
|
||||
try(PreparedStatement ps = con.prepareStatement("INSERT INTO family_character (cid, familyid, seniorid) VALUES (?, ?, ?)")) {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("INSERT INTO family_character (cid, familyid, seniorid) VALUES (?, ?, ?)")) {
|
||||
ps.setInt(1, characterID);
|
||||
ps.setInt(2, familyID);
|
||||
ps.setInt(3, seniorID);
|
||||
ps.executeUpdate();
|
||||
} catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not save new family record for char id " + characterID + ".");
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(updateChar) {
|
||||
try(PreparedStatement ps = con.prepareStatement("UPDATE characters SET familyid = ? WHERE id = ?")) {
|
||||
if (updateChar) {
|
||||
try (PreparedStatement ps = con.prepareStatement("UPDATE characters SET familyid = ? WHERE id = ?")) {
|
||||
ps.setInt(1, familyID);
|
||||
ps.setInt(2, characterID);
|
||||
ps.executeUpdate();
|
||||
} catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not update 'characters' 'familyid' record for char id " + characterID + ".");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch(SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get connection to DB.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import tools.LogHelper;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kevintjuh93
|
||||
*/
|
||||
public class AdminChatHandler extends AbstractPacketHandler {
|
||||
|
||||
@@ -75,10 +75,10 @@ public final class AdminCommandHandler extends AbstractPacketHandler {
|
||||
c.getPlayer().setExp(p.readInt());
|
||||
break;
|
||||
case 0x03: // /ban <name>
|
||||
c.getPlayer().yellowMessage("Please use !ban <IGN> <Reason>");
|
||||
break;
|
||||
c.getPlayer().yellowMessage("Please use !ban <IGN> <Reason>");
|
||||
break;
|
||||
case 0x04: // /block <name> <duration (in days)> <HACK/BOT/AD/HARASS/CURSE/SCAM/MISCONDUCT/SELL/ICASH/TEMP/GM/IPROGRAM/MEGAPHONE>
|
||||
victim = p.readString();
|
||||
victim = p.readString();
|
||||
int type = p.readByte(); //reason
|
||||
int duration = p.readInt();
|
||||
String description = p.readString();
|
||||
@@ -176,7 +176,7 @@ public final class AdminCommandHandler extends AbstractPacketHandler {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.out.println("New GM packet encountered (MODE : " + mode + ": " + p.toString());
|
||||
System.out.println("New GM packet encountered (MODE : " + mode + ": " + p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import net.server.guild.GuildPackets;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author XoticStory, Ronan
|
||||
*/
|
||||
public final class AllianceOperationHandler extends AbstractPacketHandler {
|
||||
@@ -42,16 +41,16 @@ public final class AllianceOperationHandler extends AbstractPacketHandler {
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Alliance alliance = null;
|
||||
Character chr = c.getPlayer();
|
||||
|
||||
|
||||
if (chr.getGuild() == null) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (chr.getGuild().getAllianceId() > 0) {
|
||||
alliance = chr.getAlliance();
|
||||
}
|
||||
|
||||
|
||||
byte b = p.readByte();
|
||||
if (alliance == null) {
|
||||
if (b != 4) {
|
||||
@@ -64,13 +63,13 @@ public final class AllianceOperationHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (chr.getMGC().getAllianceRank() > 2 || !alliance.getGuilds().contains(chr.getGuildId())) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// "alliance" is only null at case 0x04
|
||||
switch (b) {
|
||||
case 0x01:
|
||||
@@ -80,61 +79,61 @@ public final class AllianceOperationHandler extends AbstractPacketHandler {
|
||||
if (chr.getGuild().getAllianceId() == 0 || chr.getGuildId() < 1 || chr.getGuildRank() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Alliance.removeGuildFromAlliance(chr.getGuild().getAllianceId(), chr.getGuildId(), chr.getWorld());
|
||||
break;
|
||||
}
|
||||
case 0x03: // Send Invite
|
||||
String guildName = p.readString();
|
||||
|
||||
|
||||
if (alliance.getGuilds().size() == alliance.getCapacity()) {
|
||||
chr.dropMessage(5, "Your alliance cannot comport any more guilds at the moment.");
|
||||
} else {
|
||||
Alliance.sendInvitation(c, guildName, alliance.getId());
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case 0x04: { // Accept Invite
|
||||
Guild guild = chr.getGuild();
|
||||
if (guild.getAllianceId() != 0 || chr.getGuildRank() != 1 || chr.getGuildId() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int allianceid = p.readInt();
|
||||
//slea.readMapleAsciiString(); //recruiter's guild name
|
||||
|
||||
|
||||
alliance = Server.getInstance().getAlliance(allianceid);
|
||||
if (alliance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!Alliance.answerInvitation(c.getPlayer().getId(), guild.getName(), alliance.getId(), true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (alliance.getGuilds().size() == alliance.getCapacity()) {
|
||||
chr.dropMessage(5, "Your alliance cannot comport any more guilds at the moment.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int guildid = chr.getGuildId();
|
||||
|
||||
Server.getInstance().addGuildtoAlliance(alliance.getId(), guildid);
|
||||
Server.getInstance().resetAllianceGuildPlayersRank(guildid);
|
||||
|
||||
|
||||
chr.getMGC().setAllianceRank(2);
|
||||
Guild g = Server.getInstance().getGuild(chr.getGuildId());
|
||||
if (g != null) {
|
||||
g.getMGC(chr.getId()).setAllianceRank(2);
|
||||
}
|
||||
|
||||
|
||||
chr.saveGuildStatus();
|
||||
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.addGuildToAlliance(alliance, guildid, c), -1, -1);
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.updateAllianceInfo(alliance, c.getWorld()), -1, -1);
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.allianceNotice(alliance.getId(), alliance.getNotice()), -1, -1);
|
||||
guild.dropMessage("Your guild has joined the [" + alliance.getName() + "] union.");
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x06: { // Expel Guild
|
||||
@@ -143,14 +142,14 @@ public final class AllianceOperationHandler extends AbstractPacketHandler {
|
||||
if (chr.getGuild().getAllianceId() == 0 || chr.getGuild().getAllianceId() != allianceid) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.removeGuildFromAlliance(alliance, guildid, c.getWorld()), -1, -1);
|
||||
Server.getInstance().removeGuildFromAlliance(alliance.getId(), guildid);
|
||||
|
||||
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.getGuildAlliances(alliance, c.getWorld()), -1, -1);
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.allianceNotice(alliance.getId(), alliance.getNotice()), -1, -1);
|
||||
Server.getInstance().guildMessage(guildid, GuildPackets.disbandAlliance(allianceid));
|
||||
|
||||
|
||||
alliance.dropMessage("[" + Server.getInstance().getGuild(guildid).getName() + "] guild has been expelled from the union.");
|
||||
break;
|
||||
}
|
||||
@@ -163,7 +162,7 @@ public final class AllianceOperationHandler extends AbstractPacketHandler {
|
||||
if (player.getAllianceRank() != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Server.getInstance().allianceMessage(alliance.getId(), sendChangeLeader(chr.getGuild().getAllianceId(), chr.getId(), slea.readInt()), -1, -1);
|
||||
changeLeaderAllianceRank(alliance, player);
|
||||
break;
|
||||
@@ -179,47 +178,49 @@ public final class AllianceOperationHandler extends AbstractPacketHandler {
|
||||
case 0x09: {
|
||||
int int1 = p.readInt();
|
||||
byte byte1 = p.readByte();
|
||||
|
||||
|
||||
//Server.getInstance().allianceMessage(alliance.getId(), sendChangeRank(chr.getGuild().getAllianceId(), chr.getId(), int1, byte1), -1, -1);
|
||||
Character player = Server.getInstance().getWorld(c.getWorld()).getPlayerStorage().getCharacterById(int1);
|
||||
changePlayerAllianceRank(alliance, player, (byte1 > 0));
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0A:
|
||||
String notice = p.readString();
|
||||
Server.getInstance().setAllianceNotice(alliance.getId(), notice);
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.allianceNotice(alliance.getId(), notice), -1, -1);
|
||||
|
||||
|
||||
alliance.dropMessage(5, "* Alliance Notice : " + notice);
|
||||
break;
|
||||
default:
|
||||
chr.dropMessage("Feature not available");
|
||||
}
|
||||
|
||||
|
||||
alliance.saveToDB();
|
||||
}
|
||||
|
||||
|
||||
private void changeLeaderAllianceRank(Alliance alliance, Character newLeader) {
|
||||
GuildCharacter lmgc = alliance.getLeader();
|
||||
Character leader = newLeader.getWorldServer().getPlayerStorage().getCharacterById(lmgc.getId());
|
||||
leader.getMGC().setAllianceRank(2);
|
||||
leader.saveGuildStatus();
|
||||
|
||||
|
||||
newLeader.getMGC().setAllianceRank(1);
|
||||
newLeader.saveGuildStatus();
|
||||
|
||||
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.getGuildAlliances(alliance, newLeader.getWorld()), -1, -1);
|
||||
alliance.dropMessage("'" + newLeader.getName() + "' has been appointed as the new head of this Alliance.");
|
||||
}
|
||||
|
||||
|
||||
private void changePlayerAllianceRank(Alliance alliance, Character chr, boolean raise) {
|
||||
int newRank = chr.getAllianceRank() + (raise ? -1 : 1);
|
||||
if(newRank < 3 || newRank > 5) return;
|
||||
|
||||
if (newRank < 3 || newRank > 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
chr.getMGC().setAllianceRank(newRank);
|
||||
chr.saveGuildStatus();
|
||||
|
||||
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.getGuildAlliances(alliance, chr.getWorld()), -1, -1);
|
||||
alliance.dropMessage("'" + chr.getName() + "' has been reassigned to '" + alliance.getRankTitle(newRank) + "' in this Alliance.");
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class AranComboHandler extends AbstractPacketHandler {
|
||||
final long currentTime = currentServerTime();
|
||||
short combo = player.getCombo();
|
||||
if ((currentTime - player.getLastCombo()) > 3000 && combo > 0) {
|
||||
combo = 0;
|
||||
combo = 0;
|
||||
}
|
||||
combo++;
|
||||
switch (combo) {
|
||||
@@ -53,7 +53,9 @@ public class AranComboHandler extends AbstractPacketHandler {
|
||||
case 80:
|
||||
case 90:
|
||||
case 100:
|
||||
if (player.getJob().getId() != 2000 && (combo / 10) > skillLevel) break;
|
||||
if (player.getJob().getId() != 2000 && (combo / 10) > skillLevel) {
|
||||
break;
|
||||
}
|
||||
SkillFactory.getSkill(Aran.COMBO_ABILITY).getEffect(combo / 10).applyComboBuff(player, combo);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -33,11 +33,13 @@ public final class AutoAggroHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character player = c.getPlayer();
|
||||
if (player.isHidden()) return; // Don't auto aggro GM's in hide...
|
||||
|
||||
if (player.isHidden()) {
|
||||
return; // Don't auto aggro GM's in hide...
|
||||
}
|
||||
|
||||
MapleMap map = player.getMap();
|
||||
int oid = p.readInt();
|
||||
|
||||
|
||||
Monster monster = map.getMonsterByOid(oid);
|
||||
if (monster != null) {
|
||||
monster.aggroAutoAggroUpdate(player);
|
||||
|
||||
@@ -27,11 +27,10 @@ import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Generic, Ronan
|
||||
*/
|
||||
public class AutoAssignHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
AssignAPProcessor.APAutoAssignAction(p, c);
|
||||
|
||||
@@ -30,7 +30,6 @@ import server.maps.Summon;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BubblesDev
|
||||
*/
|
||||
public final class BeholderHandler extends AbstractPacketHandler {//Summon Skills noobs
|
||||
|
||||
@@ -40,7 +40,7 @@ import static client.BuddyList.BuddyOperation.ADDED;
|
||||
|
||||
public class BuddylistModifyHandler extends AbstractPacketHandler {
|
||||
private static class CharacterIdNameBuddyCapacity extends CharacterNameAndId {
|
||||
private int buddyCapacity;
|
||||
private final int buddyCapacity;
|
||||
|
||||
public CharacterIdNameBuddyCapacity(int id, String name, int buddyCapacity) {
|
||||
super(id, name);
|
||||
@@ -108,7 +108,7 @@ public class BuddylistModifyHandler extends AbstractPacketHandler {
|
||||
if (charWithId != null) {
|
||||
BuddyAddResult buddyAddResult = null;
|
||||
if (channel != -1) {
|
||||
buddyAddResult = world.requestBuddyAdd(addName, c.getChannel(), player.getId(), player.getName());
|
||||
buddyAddResult = world.requestBuddyAdd(addName, c.getChannel(), player.getId(), player.getName());
|
||||
} else {
|
||||
try (Connection con = DatabaseConnection.getConnection()) {
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) as buddyCount FROM buddies WHERE characterid = ? AND pending = 0")) {
|
||||
|
||||
@@ -30,11 +30,11 @@ import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public final class CancelBuffHandler extends AbstractPacketHandler implements PacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int sourceid = p.readInt();
|
||||
|
||||
|
||||
switch (sourceid) {
|
||||
case FPArchMage.BIG_BANG:
|
||||
case ILArchMage.BIG_BANG:
|
||||
@@ -47,7 +47,7 @@ public final class CancelBuffHandler extends AbstractPacketHandler implements Pa
|
||||
case Evan.ICE_BREATH:
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), PacketCreator.skillCancel(c.getPlayer(), sourceid), false);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
c.getPlayer().cancelEffect(SkillFactory.getSkill(sourceid).getEffect(1), false, -1);
|
||||
break;
|
||||
|
||||
@@ -27,16 +27,16 @@ import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
|
||||
public final class CancelChairHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int id = p.readShort();
|
||||
Character mc = c.getPlayer();
|
||||
|
||||
|
||||
if (id >= mc.getMap().getSeats()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (c.tryacquireClient()) {
|
||||
try {
|
||||
mc.sitChair(id);
|
||||
|
||||
@@ -53,12 +53,12 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
CashShop cs = chr.getCashShop();
|
||||
|
||||
|
||||
if (!cs.isOpened()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (c.tryacquireClient()) { // thanks Thora for finding out an exploit within cash operations
|
||||
try {
|
||||
final int action = p.readByte();
|
||||
@@ -92,7 +92,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.showBoughtCashItem(item, c.getAccID()));
|
||||
} else { // Package
|
||||
cs.gainCash(useNX, cItem, chr.getWorld());
|
||||
|
||||
|
||||
List<Item> cashPackage = CashItemFactory.getPackage(cItem.getItemId());
|
||||
for (Item item : cashPackage) {
|
||||
cs.addToInventory(item);
|
||||
@@ -129,7 +129,9 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
Character receiver = c.getChannelServer().getPlayerStorage().getCharacterByName(recipient.get("name"));
|
||||
if (receiver != null) receiver.showNote();
|
||||
if (receiver != null) {
|
||||
receiver.showNote();
|
||||
}
|
||||
} else if (action == 0x05) { // Modify wish list
|
||||
cs.clearWishList();
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
@@ -262,9 +264,9 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
cs.removeFromInventory(item);
|
||||
c.sendPacket(PacketCreator.takeFromCashInventory(item));
|
||||
|
||||
if(item instanceof Equip) {
|
||||
if (item instanceof Equip) {
|
||||
Equip equip = (Equip) item;
|
||||
if(equip.getRingId() >= 0) {
|
||||
if (equip.getRingId() >= 0) {
|
||||
Ring ring = Ring.loadFromDb(equip.getRingId());
|
||||
chr.addPlayerRing(ring);
|
||||
}
|
||||
@@ -316,7 +318,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
return;
|
||||
}*/ //Gotta let them faggots marry too, hence why this is commented out <3
|
||||
|
||||
if(itemRing.toItem() instanceof Equip) {
|
||||
if (itemRing.toItem() instanceof Equip) {
|
||||
Equip eqp = (Equip) itemRing.toItem();
|
||||
Pair<Integer, Integer> rings = Ring.createRing(itemRing.getItemId(), chr, partner);
|
||||
eqp.setRingId(rings.getLeft());
|
||||
@@ -331,7 +333,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
partner.showNote();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0xC4));
|
||||
@@ -377,10 +379,10 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
String text = p.readString();
|
||||
Character partner = c.getChannelServer().getPlayerStorage().getCharacterByName(sentTo);
|
||||
if (partner == null) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0xBE));
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0xBE));
|
||||
} else {
|
||||
// Need to check to make sure its actually an equip and the right SN...
|
||||
if(itemRing.toItem() instanceof Equip) {
|
||||
if (itemRing.toItem() instanceof Equip) {
|
||||
Equip eqp = (Equip) itemRing.toItem();
|
||||
Pair<Integer, Integer> rings = Ring.createRing(itemRing.getItemId(), chr, partner);
|
||||
eqp.setRingId(rings.getLeft());
|
||||
@@ -405,59 +407,59 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
} else if (action == 0x2E) { //name change
|
||||
CashItem cItem = CashItemFactory.getItem(p.readInt());
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(4))) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0));
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
}
|
||||
if(cItem.getSN() == 50600000 && YamlConfig.config.server.ALLOW_CASHSHOP_NAME_CHANGE) {
|
||||
if (cItem.getSN() == 50600000 && YamlConfig.config.server.ALLOW_CASHSHOP_NAME_CHANGE) {
|
||||
p.readString(); //old name
|
||||
String newName = p.readString();
|
||||
if(!Character.canCreateChar(newName) || chr.getLevel() < 10) { //(longest ban duration isn't tracked currently)
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0));
|
||||
if (!Character.canCreateChar(newName) || chr.getLevel() < 10) { //(longest ban duration isn't tracked currently)
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
} else if(c.getTempBanCalendar() != null && c.getTempBanCalendar().getTimeInMillis() + (30*24*60*60*1000) > Calendar.getInstance().getTimeInMillis()) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0));
|
||||
} else if (c.getTempBanCalendar() != null && c.getTempBanCalendar().getTimeInMillis() + (30 * 24 * 60 * 60 * 1000) > Calendar.getInstance().getTimeInMillis()) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
}
|
||||
if(chr.registerNameChange(newName)) { //success
|
||||
if (chr.registerNameChange(newName)) { //success
|
||||
Item item = cItem.toItem();
|
||||
c.sendPacket(PacketCreator.showNameChangeSuccess(item, c.getAccID()));
|
||||
cs.gainCash(4, cItem, chr.getWorld());
|
||||
cs.addToInventory(item);
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0));
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
}
|
||||
}
|
||||
c.enableCSActions();
|
||||
} else if(action == 0x31) { //world transfer
|
||||
} else if (action == 0x31) { //world transfer
|
||||
CashItem cItem = CashItemFactory.getItem(p.readInt());
|
||||
if (cItem == null || !canBuy(chr, cItem, cs.getCash(4))) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0));
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
c.enableCSActions();
|
||||
return;
|
||||
}
|
||||
if(cItem.getSN() == 50600001 && YamlConfig.config.server.ALLOW_CASHSHOP_WORLD_TRANSFER) {
|
||||
if (cItem.getSN() == 50600001 && YamlConfig.config.server.ALLOW_CASHSHOP_WORLD_TRANSFER) {
|
||||
int newWorldSelection = p.readInt();
|
||||
|
||||
|
||||
int worldTransferError = chr.checkWorldTransferEligibility();
|
||||
if(worldTransferError != 0 || newWorldSelection >= Server.getInstance().getWorldsSize() || Server.getInstance().getWorldsSize() <= 1) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0));
|
||||
if (worldTransferError != 0 || newWorldSelection >= Server.getInstance().getWorldsSize() || Server.getInstance().getWorldsSize() <= 1) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
return;
|
||||
} else if(newWorldSelection == c.getWorld()) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0xDC));
|
||||
} else if (newWorldSelection == c.getWorld()) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0xDC));
|
||||
return;
|
||||
} else if(c.getAvailableCharacterWorldSlots(newWorldSelection) < 1 || Server.getInstance().getAccountWorldCharacterCount(c.getAccID(), newWorldSelection) >= 3) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0xDF));
|
||||
} else if (c.getAvailableCharacterWorldSlots(newWorldSelection) < 1 || Server.getInstance().getAccountWorldCharacterCount(c.getAccID(), newWorldSelection) >= 3) {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0xDF));
|
||||
return;
|
||||
} else if(chr.registerWorldTransfer(newWorldSelection)) {
|
||||
} else if (chr.registerWorldTransfer(newWorldSelection)) {
|
||||
Item item = cItem.toItem();
|
||||
c.sendPacket(PacketCreator.showWorldTransferSuccess(item, c.getAccID()));
|
||||
cs.gainCash(4, cItem, chr.getWorld());
|
||||
cs.addToInventory(item);
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte)0));
|
||||
c.sendPacket(PacketCreator.showCashShopMessage((byte) 0));
|
||||
}
|
||||
}
|
||||
c.enableCSActions();
|
||||
@@ -481,7 +483,7 @@ public final class CashOperationHandler extends AbstractPacketHandler {
|
||||
cal.set(year, month - 1, day);
|
||||
return c.checkBirthDate(cal);
|
||||
}
|
||||
|
||||
|
||||
private static boolean canBuy(Character chr, CashItem item, int cash) {
|
||||
if (item != null && item.isOnSale() && item.getPrice() <= cash) {
|
||||
FilePrinter.print(FilePrinter.CASHITEM_BOUGHT, chr + " bought " + ItemInformationProvider.getInstance().getName(item.getItemId()) + " (SN " + item.getSN() + ") for " + item.getPrice());
|
||||
|
||||
@@ -28,18 +28,17 @@ import tools.PacketCreator;
|
||||
import tools.Pair;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author RonanLana
|
||||
*/
|
||||
public class CashShopSurpriseHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
CashShop cs = c.getPlayer().getCashShop();
|
||||
|
||||
if(cs.isOpened()) {
|
||||
|
||||
if (cs.isOpened()) {
|
||||
Pair<Item, Item> cssResult = cs.openCashShopSurprise();
|
||||
|
||||
if(cssResult != null) {
|
||||
|
||||
if (cssResult != null) {
|
||||
Item cssItem = cssResult.getLeft(), cssBox = cssResult.getRight();
|
||||
c.sendPacket(PacketCreator.onCashGachaponOpenSuccess(c.getAccID(), cssBox.getSN(), cssBox.getQuantity(), cssItem, cssItem.getItemId(), cssItem.getQuantity(), true));
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,6 @@ import net.packet.InPacket;
|
||||
import net.server.Server;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public final class ChangeChannelHandler extends AbstractPacketHandler {
|
||||
@@ -38,14 +37,14 @@ public final class ChangeChannelHandler extends AbstractPacketHandler {
|
||||
int channel = p.readByte() + 1;
|
||||
p.readInt();
|
||||
c.getPlayer().getAutobanManager().setTimestamp(6, Server.getInstance().getCurrentTimestamp(), 3);
|
||||
if(c.getChannel() == channel) {
|
||||
AutobanFactory.GENERAL.alert(c.getPlayer(), "CCing to same channel.");
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
if (c.getChannel() == channel) {
|
||||
AutobanFactory.GENERAL.alert(c.getPlayer(), "CCing to same channel.");
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
} else if (c.getPlayer().getCashShop().isOpened() || c.getPlayer().getMiniGame() != null || c.getPlayer().getPlayerShop() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
c.changeChannel(channel);
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public final class ChangeMapHandler extends AbstractPacketHandler {
|
||||
|
||||
if (chr.isChangingMaps() || chr.isBanned()) {
|
||||
if (chr.isChangingMaps()) {
|
||||
FilePrinter.printError(FilePrinter.PORTAL_STUCK + chr.getName() + ".txt", "Player " + chr.getName() + " got stuck when changing maps. Timestamp: " + Calendar.getInstance().getTime().toString() + " Last visited mapids: " + chr.getLastVisitedMapids());
|
||||
FilePrinter.printError(FilePrinter.PORTAL_STUCK + chr.getName() + ".txt", "Player " + chr.getName() + " got stuck when changing maps. Timestamp: " + Calendar.getInstance().getTime() + " Last visited mapids: " + chr.getLastVisitedMapids());
|
||||
}
|
||||
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
|
||||
@@ -32,21 +32,21 @@ import tools.PacketCreator;
|
||||
public final class ChangeMapSpecialHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.readByte();
|
||||
String startwp = p.readString();
|
||||
p.readShort();
|
||||
Portal portal = c.getPlayer().getMap().getPortal(startwp);
|
||||
if (portal == null || c.getPlayer().portalDelay() > currentServerTime() || c.getPlayer().getBlockedPortals().contains(portal.getScriptName())) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().isChangingMaps() || c.getPlayer().isBanned()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().getTrade() != null) {
|
||||
Trade.cancelTrade(c.getPlayer(), TradeResult.UNSUCCESSFUL_ANOTHER_MAP);
|
||||
}
|
||||
portal.enterPortal(c);
|
||||
p.readByte();
|
||||
String startwp = p.readString();
|
||||
p.readShort();
|
||||
Portal portal = c.getPlayer().getMap().getPortal(startwp);
|
||||
if (portal == null || c.getPlayer().portalDelay() > currentServerTime() || c.getPlayer().getBlockedPortals().contains(portal.getScriptName())) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().isChangingMaps() || c.getPlayer().isBanned()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (c.getPlayer().getTrade() != null) {
|
||||
Trade.cancelTrade(c.getPlayer(), TradeResult.UNSUCCESSFUL_ANOTHER_MAP);
|
||||
}
|
||||
portal.enterPortal(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import server.maps.MapObject;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public final class CharInfoRequestHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.skip(4);
|
||||
@@ -38,8 +38,8 @@ public final class CharInfoRequestHandler extends AbstractPacketHandler {
|
||||
if (target != null) {
|
||||
if (target instanceof Character) {
|
||||
Character player = (Character) target;
|
||||
|
||||
if(c.getPlayer().getId() != player.getId()) {
|
||||
|
||||
if (c.getPlayer().getId() != player.getId()) {
|
||||
player.exportExcludedItems(c);
|
||||
}
|
||||
c.sendPacket(PacketCreator.charInfo(player));
|
||||
|
||||
@@ -29,7 +29,6 @@ import net.packet.InPacket;
|
||||
import scripting.npc.NPCScriptManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kevintjuh93
|
||||
*/
|
||||
public class ClickGuideHandler extends AbstractPacketHandler {
|
||||
|
||||
@@ -27,11 +27,10 @@ import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xterminator
|
||||
*/
|
||||
public final class CloseChalkboardHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
c.getPlayer().setChalkboard(null);
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
@@ -46,23 +46,25 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
AutobanFactory.FAST_ATTACK.alert(chr, "Time: " + timeElapsed);
|
||||
}
|
||||
chr.getAutobanManager().spam(8);*/
|
||||
|
||||
|
||||
AttackInfo attack = parseDamage(p, chr, false, false);
|
||||
if (chr.getBuffEffect(BuffStat.MORPH) != null) {
|
||||
if(chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
if (chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
// How are they attacking when the client won't let them?
|
||||
chr.getClient().disconnect(false, false);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (chr.getDojoEnergy() < 10000 && (attack.skill == 1009 || attack.skill == 10001009 || attack.skill == 20001009)) // PE hacking or maybe just lagging
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (GameConstants.isDojo(chr.getMap().getId()) && attack.numAttacked > 0) {
|
||||
chr.setDojoEnergy(chr.getDojoEnergy() + YamlConfig.config.server.DOJO_ENERGY_ATK);
|
||||
c.sendPacket(PacketCreator.getEnergy("energy", chr.getDojoEnergy()));
|
||||
}
|
||||
|
||||
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.closeRangeAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.speed, attack.direction, attack.display), false, true);
|
||||
int numFinisherOrbs = 0;
|
||||
Integer comboBuff = chr.getBuffedValue(BuffStat.COMBO);
|
||||
@@ -84,12 +86,17 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
ceffect = advcombo.getEffect(advComboSkillLevel);
|
||||
} else {
|
||||
int comboLv = chr.getSkillLevel(combo);
|
||||
if(comboLv <= 0 || chr.isGM()) comboLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
|
||||
if(comboLv > 0) ceffect = combo.getEffect(comboLv);
|
||||
else ceffect = null;
|
||||
if (comboLv <= 0 || chr.isGM()) {
|
||||
comboLv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
}
|
||||
|
||||
if (comboLv > 0) {
|
||||
ceffect = combo.getEffect(comboLv);
|
||||
} else {
|
||||
ceffect = null;
|
||||
}
|
||||
}
|
||||
if(ceffect != null) {
|
||||
if (ceffect != null) {
|
||||
if (orbcount < ceffect.getX() + 1) {
|
||||
int neworbcount = orbcount + 1;
|
||||
if (advComboSkillLevel > 0 && ceffect.makeChanceResult()) {
|
||||
@@ -99,11 +106,13 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
|
||||
int olv = chr.getSkillLevel(oid);
|
||||
if(olv <= 0) olv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
|
||||
if (olv <= 0) {
|
||||
olv = SkillFactory.getSkill(oid).getMaxLevel();
|
||||
}
|
||||
|
||||
int duration = combo.getEffect(olv).getDuration();
|
||||
List<Pair<BuffStat, Integer>> stat = Collections.singletonList(new Pair<>(BuffStat.COMBO, neworbcount));
|
||||
chr.setBuffedValue(BuffStat.COMBO, neworbcount);
|
||||
chr.setBuffedValue(BuffStat.COMBO, neworbcount);
|
||||
duration -= (int) (currentServerTime() - chr.getBuffedStarttime(BuffStat.COMBO));
|
||||
c.sendPacket(PacketCreator.giveBuff(oid, duration, stat));
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.giveForeignBuff(chr.getId(), stat), false);
|
||||
@@ -121,7 +130,7 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
if (dmgIt.hasNext()) {
|
||||
totDamageToOneMonster = dmgIt.next().get(0);
|
||||
}
|
||||
|
||||
|
||||
chr.safeAddHP(-1 * totDamageToOneMonster * attack.getAttackEffect(chr, null).getX() / 100);
|
||||
}
|
||||
if (attack.numAttacked > 0 && attack.skill == 1211002) {
|
||||
@@ -145,7 +154,7 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
if (chr.getDojoEnergy() < 10000) { // PE hacking or maybe just lagging
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
chr.setDojoEnergy(0);
|
||||
c.sendPacket(PacketCreator.getEnergy("energy", chr.getDojoEnergy()));
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "As you used the secret skill, your energy bar has been reset."));
|
||||
@@ -164,11 +173,11 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
|
||||
if ((chr.getSkillLevel(SkillFactory.getSkill(NightWalker.VANISH)) > 0 || chr.getSkillLevel(SkillFactory.getSkill(Rogue.DARK_SIGHT)) > 0) && chr.getBuffedValue(BuffStat.DARKSIGHT) != null) {// && chr.getBuffSource(BuffStat.DARKSIGHT) != 9101004
|
||||
chr.cancelEffectFromBuffStat(BuffStat.DARKSIGHT);
|
||||
chr.cancelBuffStats(BuffStat.DARKSIGHT);
|
||||
} else if(chr.getSkillLevel(SkillFactory.getSkill(WindArcher.WIND_WALK)) > 0 && chr.getBuffedValue(BuffStat.WIND_WALK) != null) {
|
||||
} else if (chr.getSkillLevel(SkillFactory.getSkill(WindArcher.WIND_WALK)) > 0 && chr.getBuffedValue(BuffStat.WIND_WALK) != null) {
|
||||
chr.cancelEffectFromBuffStat(BuffStat.WIND_WALK);
|
||||
chr.cancelBuffStats(BuffStat.WIND_WALK);
|
||||
}
|
||||
|
||||
|
||||
applyAttack(attack, chr, attackCount);
|
||||
}
|
||||
}
|
||||
@@ -31,55 +31,54 @@ import server.maps.MapleMap;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kevintjuh93
|
||||
*/
|
||||
public final class CoconutHandler extends AbstractPacketHandler {
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
/*CB 00 A6 00 06 01
|
||||
* A6 00 = coconut id
|
||||
* 06 01 = ?
|
||||
*/
|
||||
int id = p.readShort();
|
||||
MapleMap map = c.getPlayer().getMap();
|
||||
Coconut event = map.getCoconut();
|
||||
Coconuts nut = event.getCoconut(id);
|
||||
if (!nut.isHittable()){
|
||||
return;
|
||||
}
|
||||
if (event == null){
|
||||
return;
|
||||
}
|
||||
if (currentServerTime() < nut.getHitTime()){
|
||||
return;
|
||||
}
|
||||
if (nut.getHits() > 2 && Math.random() < 0.4) {
|
||||
if (Math.random() < 0.01 && event.getStopped() > 0) {
|
||||
nut.setHittable(false);
|
||||
event.stopCoconut();
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 1));
|
||||
return;
|
||||
}
|
||||
nut.setHittable(false); // for sure :)
|
||||
nut.resetHits(); // For next event (without restarts)
|
||||
if (Math.random() < 0.05 && event.getBombings() > 0) {
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 2));
|
||||
event.bombCoconut();
|
||||
} else if (event.getFalling() > 0) {
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 3));
|
||||
event.fallCoconut();
|
||||
if (c.getPlayer().getTeam() == 0) {
|
||||
event.addMapleScore();
|
||||
map.broadcastMessage(PacketCreator.serverNotice(5, c.getPlayer().getName() + " of Team Maple knocks down a coconut."));
|
||||
} else {
|
||||
event.addStoryScore();
|
||||
map.broadcastMessage(PacketCreator.serverNotice(5, c.getPlayer().getName() + " of Team Story knocks down a coconut."));
|
||||
}
|
||||
map.broadcastMessage(PacketCreator.coconutScore(event.getMapleScore(), event.getStoryScore()));
|
||||
}
|
||||
} else {
|
||||
nut.hit();
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 1));
|
||||
}
|
||||
}
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
/*CB 00 A6 00 06 01
|
||||
* A6 00 = coconut id
|
||||
* 06 01 = ?
|
||||
*/
|
||||
int id = p.readShort();
|
||||
MapleMap map = c.getPlayer().getMap();
|
||||
Coconut event = map.getCoconut();
|
||||
Coconuts nut = event.getCoconut(id);
|
||||
if (!nut.isHittable()) {
|
||||
return;
|
||||
}
|
||||
if (event == null) {
|
||||
return;
|
||||
}
|
||||
if (currentServerTime() < nut.getHitTime()) {
|
||||
return;
|
||||
}
|
||||
if (nut.getHits() > 2 && Math.random() < 0.4) {
|
||||
if (Math.random() < 0.01 && event.getStopped() > 0) {
|
||||
nut.setHittable(false);
|
||||
event.stopCoconut();
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 1));
|
||||
return;
|
||||
}
|
||||
nut.setHittable(false); // for sure :)
|
||||
nut.resetHits(); // For next event (without restarts)
|
||||
if (Math.random() < 0.05 && event.getBombings() > 0) {
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 2));
|
||||
event.bombCoconut();
|
||||
} else if (event.getFalling() > 0) {
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 3));
|
||||
event.fallCoconut();
|
||||
if (c.getPlayer().getTeam() == 0) {
|
||||
event.addMapleScore();
|
||||
map.broadcastMessage(PacketCreator.serverNotice(5, c.getPlayer().getName() + " of Team Maple knocks down a coconut."));
|
||||
} else {
|
||||
event.addStoryScore();
|
||||
map.broadcastMessage(PacketCreator.serverNotice(5, c.getPlayer().getName() + " of Team Story knocks down a coconut."));
|
||||
}
|
||||
map.broadcastMessage(PacketCreator.coconutScore(event.getMapleScore(), event.getStoryScore()));
|
||||
}
|
||||
} else {
|
||||
nut.hit();
|
||||
map.broadcastMessage(PacketCreator.hitCoconut(false, id, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,16 +45,15 @@ import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Penguins (Acrylic)
|
||||
* @author Ronan (HeavenMS)
|
||||
*/
|
||||
public final class CouponCodeHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
private static List<Pair<Integer, Pair<Integer, Integer>>> getNXCodeItems(Character chr, Connection con, int codeid) throws SQLException {
|
||||
Map<Integer, Integer> couponItems = new HashMap<>();
|
||||
Map<Integer, Integer> couponPoints = new HashMap<>(5);
|
||||
|
||||
|
||||
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM nxcode_items WHERE codeid = ?")) {
|
||||
ps.setInt(1, codeid);
|
||||
|
||||
@@ -81,36 +80,36 @@ public final class CouponCodeHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<Pair<Integer, Pair<Integer, Integer>>> ret = new LinkedList<>();
|
||||
if (!couponItems.isEmpty()) {
|
||||
for (Entry<Integer, Integer> e : couponItems.entrySet()) {
|
||||
int item = e.getKey(), qty = e.getValue();
|
||||
|
||||
|
||||
if (ItemInformationProvider.getInstance().getName(item) == null) {
|
||||
item = 4000000;
|
||||
qty = 1;
|
||||
|
||||
|
||||
FilePrinter.printError(FilePrinter.UNHANDLED_EVENT, "Error trying to redeem itemid " + item + " from codeid " + codeid + ".");
|
||||
}
|
||||
|
||||
|
||||
if (!chr.canHold(item, qty)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
ret.add(new Pair<>(5, new Pair<>(item, qty)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!couponPoints.isEmpty()) {
|
||||
for (Entry<Integer, Integer> e : couponPoints.entrySet()) {
|
||||
ret.add(new Pair<>(e.getKey(), new Pair<>(777, e.getValue())));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
private static Pair<Integer, List<Pair<Integer, Pair<Integer, Integer>>>> getNXCodeResult(Character chr, String code) {
|
||||
Client c = chr.getClient();
|
||||
List<Pair<Integer, Pair<Integer, Integer>>> ret = new LinkedList<>();
|
||||
@@ -158,31 +157,31 @@ public final class CouponCodeHandler extends AbstractPacketHandler {
|
||||
c.resetCsCoupon();
|
||||
return new Pair<>(0, ret);
|
||||
}
|
||||
|
||||
|
||||
private static int parseCouponResult(int res) {
|
||||
switch (res) {
|
||||
case -1:
|
||||
return 0xB0;
|
||||
|
||||
|
||||
case -2:
|
||||
return 0xB3;
|
||||
|
||||
|
||||
case -3:
|
||||
return 0xB2;
|
||||
|
||||
|
||||
case -4:
|
||||
return 0xBB;
|
||||
|
||||
|
||||
default:
|
||||
return 0xB1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.skip(2);
|
||||
String code = p.readString();
|
||||
|
||||
|
||||
if (c.tryacquireClient()) {
|
||||
try {
|
||||
Pair<Integer, List<Pair<Integer, Pair<Integer, Integer>>>> codeRes = getNXCodeResult(c.getPlayer(), code.toUpperCase());
|
||||
@@ -196,7 +195,7 @@ public final class CouponCodeHandler extends AbstractPacketHandler {
|
||||
int maplePoints = 0;
|
||||
int nxPrepaid = 0;
|
||||
int mesos = 0;
|
||||
|
||||
|
||||
for (Pair<Integer, Pair<Integer, Integer>> pair : codeRes.getRight()) {
|
||||
type = pair.getLeft();
|
||||
int quantity = pair.getRight().getRight();
|
||||
@@ -228,7 +227,7 @@ public final class CouponCodeHandler extends AbstractPacketHandler {
|
||||
|
||||
default:
|
||||
int item = pair.getRight().getLeft();
|
||||
|
||||
|
||||
short qty;
|
||||
if (quantity > Short.MAX_VALUE) {
|
||||
qty = Short.MAX_VALUE;
|
||||
@@ -237,7 +236,7 @@ public final class CouponCodeHandler extends AbstractPacketHandler {
|
||||
} else {
|
||||
qty = (short) quantity;
|
||||
}
|
||||
|
||||
|
||||
if (ItemInformationProvider.getInstance().isCash(item)) {
|
||||
Item it = CashShop.generateCouponItem(item, qty);
|
||||
|
||||
@@ -250,11 +249,11 @@ public final class CouponCodeHandler extends AbstractPacketHandler {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(cashItems.size() > 255) {
|
||||
if (cashItems.size() > 255) {
|
||||
List<Item> oldList = cashItems;
|
||||
cashItems = Arrays.asList(new Item[255]);
|
||||
int index = 0;
|
||||
for(Item item : oldList) {
|
||||
for (Item item : oldList) {
|
||||
cashItems.set(index, item);
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -37,13 +37,13 @@ public final class DamageSummonHandler extends AbstractPacketHandler {
|
||||
p.skip(1); // -1
|
||||
int damage = p.readInt();
|
||||
int monsterIdFrom = p.readInt();
|
||||
|
||||
|
||||
Character player = c.getPlayer();
|
||||
MapObject mmo = player.getMap().getMapObject(oid);
|
||||
|
||||
if(mmo != null && mmo instanceof Summon) {
|
||||
|
||||
if (mmo != null && mmo instanceof Summon) {
|
||||
Summon summon = (Summon) mmo;
|
||||
|
||||
|
||||
summon.addHP(-damage);
|
||||
if (summon.getHP() <= 0) {
|
||||
player.cancelEffectFromBuffStat(BuffStat.PUPPET);
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class DenyAllianceRequestHandler extends AbstractPacketHandler {
|
||||
p.readByte();
|
||||
String inviterName = p.readString();
|
||||
String guildName = p.readString();
|
||||
|
||||
|
||||
Character chr = c.getWorldServer().getPlayerStorage().getCharacterByName(inviterName);
|
||||
if (chr != null) {
|
||||
Alliance alliance = chr.getAlliance();
|
||||
|
||||
@@ -28,11 +28,10 @@ import net.packet.InPacket;
|
||||
import net.server.guild.Guild;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xterminator
|
||||
*/
|
||||
public final class DenyGuildRequestHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.readByte();
|
||||
|
||||
@@ -31,16 +31,16 @@ import net.server.coordinator.world.InviteCoordinator.InviteType;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public final class DenyPartyRequestHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.readByte();
|
||||
String[] cname = p.readString().split("PS: ");
|
||||
|
||||
|
||||
Character cfrom = c.getChannelServer().getPlayerStorage().getCharacterByName(cname[cname.length - 1]);
|
||||
if (cfrom != null) {
|
||||
Character chr = c.getPlayer();
|
||||
|
||||
|
||||
if (InviteCoordinator.answerInvite(InviteType.PARTY, chr.getId(), cfrom.getPartyId(), false).result == InviteResultType.DENIED) {
|
||||
chr.updatePartySearchAvailability(chr.getParty() == null);
|
||||
cfrom.sendPacket(PacketCreator.partyStatusMessage(23, chr.getName()));
|
||||
|
||||
@@ -27,12 +27,12 @@ import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
|
||||
public final class DistributeAPHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.readInt();
|
||||
int num = p.readInt();
|
||||
|
||||
|
||||
AssignAPProcessor.APAssignAction(c, num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public final class DistributeSPHandler extends AbstractPacketHandler {
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.readInt();
|
||||
int skillid = p.readInt();
|
||||
|
||||
|
||||
AssignSPProcessor.SPAssignAction(c, skillid);
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import server.maps.MapObject;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public final class DoorHandler extends AbstractPacketHandler {
|
||||
@@ -38,13 +37,13 @@ public final class DoorHandler extends AbstractPacketHandler {
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int ownerid = p.readInt();
|
||||
p.readByte(); // specifies if backwarp or not, 1 town to target, 0 target to town
|
||||
|
||||
|
||||
Character chr = c.getPlayer();
|
||||
if (chr.isChangingMaps() || chr.isBanned()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (MapObject obj : chr.getMap().getMapObjects()) {
|
||||
if (obj instanceof DoorObject) {
|
||||
DoorObject door = (DoorObject) obj;
|
||||
@@ -54,7 +53,7 @@ public final class DoorHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
c.sendPacket(PacketCreator.blockedMessage(6));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public final class DueyHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
if (!YamlConfig.config.server.USE_DUEY){
|
||||
if (!YamlConfig.config.server.USE_DUEY) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
byte operation = p.readByte();
|
||||
if (operation == DueyProcessor.Actions.TOSERVER_RECV_ITEM.getCode()) { // on click 'O' Button, thanks inhyuk
|
||||
DueyProcessor.dueySendTalk(c, false);
|
||||
@@ -48,15 +48,15 @@ public final class DueyHandler extends AbstractPacketHandler {
|
||||
String recipient = p.readString();
|
||||
boolean quick = p.readByte() != 0;
|
||||
String message = quick ? p.readString() : null;
|
||||
|
||||
|
||||
DueyProcessor.dueySendItem(c, inventId, itemPos, amount, mesos, message, recipient, quick);
|
||||
} else if (operation == DueyProcessor.Actions.TOSERVER_REMOVE_PACKAGE.getCode()) {
|
||||
int packageid = p.readInt();
|
||||
|
||||
|
||||
DueyProcessor.dueyRemovePackage(c, packageid, true);
|
||||
} else if (operation == DueyProcessor.Actions.TOSERVER_CLAIM_PACKAGE.getCode()) {
|
||||
int packageid = p.readInt();
|
||||
|
||||
|
||||
DueyProcessor.dueyClaimPackage(c, packageid);
|
||||
} else if (operation == DueyProcessor.Actions.TOSERVER_CLAIM_PACKAGE.getCode()) {
|
||||
DueyProcessor.dueySendTalk(c, false);
|
||||
|
||||
@@ -30,7 +30,6 @@ import server.maps.MiniDungeonInfo;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Flav
|
||||
*/
|
||||
public class EnterCashShopHandler extends AbstractPacketHandler {
|
||||
@@ -43,19 +42,19 @@ public class EnterCashShopHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if(mc.getEventInstance() != null) {
|
||||
|
||||
if (mc.getEventInstance() != null) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Entering Cash Shop or MTS are disabled when registered on an event."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if(MiniDungeonInfo.isDungeonMap(mc.getMapId())) {
|
||||
|
||||
if (MiniDungeonInfo.isDungeonMap(mc.getMapId())) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (mc.getCashShop().isOpened()) {
|
||||
return;
|
||||
}
|
||||
@@ -75,10 +74,10 @@ public class EnterCashShopHandler extends AbstractPacketHandler {
|
||||
mc.cancelDiseaseExpireTask();
|
||||
mc.cancelSkillCooldownTask();
|
||||
mc.cancelExpirationTask();
|
||||
|
||||
|
||||
mc.forfeitExpirableQuests();
|
||||
mc.cancelQuestExpirationTask();
|
||||
|
||||
|
||||
c.sendPacket(PacketCreator.openCashShop(c, false));
|
||||
c.sendPacket(PacketCreator.showCashInventory(c));
|
||||
c.sendPacket(PacketCreator.showGifts(mc.getCashShop().loadGifts()));
|
||||
|
||||
@@ -48,8 +48,8 @@ public final class EnterMTSHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
|
||||
if(!chr.isAlive() && YamlConfig.config.server.USE_BUYBACK_SYSTEM) {
|
||||
|
||||
if (!chr.isAlive() && YamlConfig.config.server.USE_BUYBACK_SYSTEM) {
|
||||
BuybackProcessor.processBuyback(c);
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
} else {
|
||||
@@ -58,18 +58,18 @@ public final class EnterMTSHandler extends AbstractPacketHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if(chr.getEventInstance() != null) {
|
||||
if (chr.getEventInstance() != null) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Entering Cash Shop or MTS are disabled when registered on an event."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if(MiniDungeonInfo.isDungeonMap(chr.getMapId())) {
|
||||
|
||||
if (MiniDungeonInfo.isDungeonMap(chr.getMapId())) {
|
||||
c.sendPacket(PacketCreator.serverNotice(5, "Changing channels or entering Cash Shop or MTS are disabled when inside a Mini-Dungeon."));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (FieldLimit.CANNOTMIGRATE.check(chr.getMap().getFieldLimit())) {
|
||||
chr.dropMessage(1, "You can't do it here in this map.");
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
@@ -88,7 +88,7 @@ public final class EnterMTSHandler extends AbstractPacketHandler {
|
||||
|
||||
chr.closePlayerInteractions();
|
||||
chr.closePartySearchInteractions();
|
||||
|
||||
|
||||
chr.unregisterChairBuff();
|
||||
Server.getInstance().getPlayerBuffStorage().addBuffsToStorage(chr.getId(), chr.getAllBuffs());
|
||||
Server.getInstance().getPlayerBuffStorage().addDiseasesToStorage(chr.getId(), chr.getAllDiseases());
|
||||
@@ -106,7 +106,7 @@ public final class EnterMTSHandler extends AbstractPacketHandler {
|
||||
chr.cancelQuestExpirationTask();
|
||||
|
||||
chr.saveCharToDB();
|
||||
|
||||
|
||||
c.getChannelServer().removePlayer(chr);
|
||||
chr.getMap().removePlayer(c.getPlayer());
|
||||
try {
|
||||
|
||||
@@ -32,7 +32,7 @@ public final class FaceExpressionHandler extends AbstractPacketHandler {
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
int emote = p.readInt();
|
||||
|
||||
|
||||
if (emote > 7) {
|
||||
int itemid = 5159992 + emote; // thanks RajanGrewal (Darter) for reporting unchecked emote itemid
|
||||
if (!ItemConstants.isFaceExpression(itemid) || chr.getInventory(ItemConstants.getInventoryType(itemid)).findById(itemid) == null) {
|
||||
@@ -41,8 +41,8 @@ public final class FaceExpressionHandler extends AbstractPacketHandler {
|
||||
} else if (emote < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(c.tryacquireClient()) {
|
||||
|
||||
if (c.tryacquireClient()) {
|
||||
try { // expecting players never intends to wear the emote 0 (default face, that changes back after 5sec timeout)
|
||||
if (chr.isLoggedinWorld()) {
|
||||
chr.changeFaceExpression(emote);
|
||||
|
||||
@@ -31,34 +31,33 @@ import net.server.coordinator.world.InviteCoordinator.InviteType;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jay Estrella
|
||||
* @author Ubaware
|
||||
*/
|
||||
public final class FamilyAddHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
if(!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
if (!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
return;
|
||||
}
|
||||
String toAdd = p.readString();
|
||||
Character addChr = c.getChannelServer().getPlayerStorage().getCharacterByName(toAdd);
|
||||
Character chr = c.getPlayer();
|
||||
if(addChr == null) {
|
||||
if (addChr == null) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(65, 0));
|
||||
} else if(addChr == chr) { //only possible through packet editing/client editing i think?
|
||||
} else if (addChr == chr) { //only possible through packet editing/client editing i think?
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
} else if(addChr.getMap() != chr.getMap() || (addChr.isHidden()) && chr.gmLevel() < addChr.gmLevel()) {
|
||||
} else if (addChr.getMap() != chr.getMap() || (addChr.isHidden()) && chr.gmLevel() < addChr.gmLevel()) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(69, 0));
|
||||
} else if(addChr.getLevel() <= 10) {
|
||||
} else if (addChr.getLevel() <= 10) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(77, 0));
|
||||
} else if(Math.abs(addChr.getLevel() - chr.getLevel()) > 20) {
|
||||
} else if (Math.abs(addChr.getLevel() - chr.getLevel()) > 20) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(72, 0));
|
||||
} else if(addChr.getFamily() != null && addChr.getFamily() == chr.getFamily()) { //same family
|
||||
} else if (addChr.getFamily() != null && addChr.getFamily() == chr.getFamily()) { //same family
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
} else if(InviteCoordinator.hasInvite(InviteType.FAMILY, addChr.getId())) {
|
||||
} else if (InviteCoordinator.hasInvite(InviteType.FAMILY, addChr.getId())) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(73, 0));
|
||||
} else if(chr.getFamily() != null && addChr.getFamily() != null && addChr.getFamily().getTotalGenerations() + chr.getFamily().getTotalGenerations() > YamlConfig.config.server.FAMILY_MAX_GENERATIONS) {
|
||||
} else if (chr.getFamily() != null && addChr.getFamily() != null && addChr.getFamily().getTotalGenerations() + chr.getFamily().getTotalGenerations() > YamlConfig.config.server.FAMILY_MAX_GENERATIONS) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(76, 0));
|
||||
} else {
|
||||
InviteCoordinator.createInvite(InviteType.FAMILY, chr, addChr, addChr.getId());
|
||||
|
||||
@@ -11,10 +11,16 @@ public class FamilyPreceptsHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
Family family = c.getPlayer().getFamily();
|
||||
if(family == null) return;
|
||||
if(family.getLeader().getChr() != c.getPlayer()) return; //only the leader can set the precepts
|
||||
if (family == null) {
|
||||
return;
|
||||
}
|
||||
if (family.getLeader().getChr() != c.getPlayer()) {
|
||||
return; //only the leader can set the precepts
|
||||
}
|
||||
String newPrecepts = p.readString();
|
||||
if(newPrecepts.length() > 200) return;
|
||||
if (newPrecepts.length() > 200) {
|
||||
return;
|
||||
}
|
||||
family.setMessage(newPrecepts, true);
|
||||
//family.broadcastFamilyInfoUpdate(); //probably don't need to broadcast for this?
|
||||
c.sendPacket(PacketCreator.getFamilyInfo(c.getPlayer().getFamilyEntry()));
|
||||
|
||||
@@ -31,42 +31,54 @@ public class FamilySeparateHandler extends AbstractPacketHandler {
|
||||
|
||||
@Override
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
if(!YamlConfig.config.server.USE_FAMILY_SYSTEM) return;
|
||||
if (!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
return;
|
||||
}
|
||||
Family oldFamily = c.getPlayer().getFamily();
|
||||
if(oldFamily == null) return;
|
||||
if (oldFamily == null) {
|
||||
return;
|
||||
}
|
||||
FamilyEntry forkOn = null;
|
||||
boolean isSenior;
|
||||
if(p.available() > 0) { //packet 0x95 doesn't send id, since there is only one senior
|
||||
if (p.available() > 0) { //packet 0x95 doesn't send id, since there is only one senior
|
||||
forkOn = c.getPlayer().getFamily().getEntryByID(p.readInt());
|
||||
if(!c.getPlayer().getFamilyEntry().isJunior(forkOn)) return; //packet editing?
|
||||
if (!c.getPlayer().getFamilyEntry().isJunior(forkOn)) {
|
||||
return; //packet editing?
|
||||
}
|
||||
isSenior = true;
|
||||
} else {
|
||||
forkOn = c.getPlayer().getFamilyEntry();
|
||||
isSenior = false;
|
||||
}
|
||||
if(forkOn == null) return;
|
||||
|
||||
if (forkOn == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FamilyEntry senior = forkOn.getSenior();
|
||||
if(senior == null) return;
|
||||
if (senior == null) {
|
||||
return;
|
||||
}
|
||||
int levelDiff = Math.abs(c.getPlayer().getLevel() - senior.getLevel());
|
||||
int cost = 2500 * levelDiff;
|
||||
cost += levelDiff * levelDiff;
|
||||
if(c.getPlayer().getMeso() < cost) {
|
||||
if (c.getPlayer().getMeso() < cost) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(isSenior ? 81 : 80, cost));
|
||||
return;
|
||||
}
|
||||
c.getPlayer().gainMeso(-cost);
|
||||
int repCost = separateRepCost(forkOn);
|
||||
senior.gainReputation(-repCost, false);
|
||||
if(senior.getSenior() != null) senior.getSenior().gainReputation(-(repCost/2), false);
|
||||
if (senior.getSenior() != null) {
|
||||
senior.getSenior().gainReputation(-(repCost / 2), false);
|
||||
}
|
||||
forkOn.announceToSenior(PacketCreator.serverNotice(5, forkOn.getName() + " has left the family."), true);
|
||||
forkOn.fork();
|
||||
c.sendPacket(PacketCreator.getFamilyInfo(forkOn)); //pedigree info will be requested from the client if the window is open
|
||||
forkOn.updateSeniorFamilyInfo(true);
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(1, 0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static int separateRepCost(FamilyEntry junior) {
|
||||
int level = junior.getLevel();
|
||||
int ret = level / 20;
|
||||
|
||||
@@ -18,16 +18,22 @@ public class FamilySummonResponseHandler extends AbstractPacketHandler {
|
||||
|
||||
@Override
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
if(!YamlConfig.config.server.USE_FAMILY_SYSTEM) return;
|
||||
if (!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
return;
|
||||
}
|
||||
p.readString(); //family name
|
||||
boolean accept = p.readByte() != 0;
|
||||
InviteResult inviteResult = InviteCoordinator.answerInvite(InviteType.FAMILY_SUMMON, c.getPlayer().getId(), c.getPlayer(), accept);
|
||||
if(inviteResult.result == InviteResultType.NOT_FOUND) return;
|
||||
if (inviteResult.result == InviteResultType.NOT_FOUND) {
|
||||
return;
|
||||
}
|
||||
Character inviter = inviteResult.from;
|
||||
FamilyEntry inviterEntry = inviter.getFamilyEntry();
|
||||
if(inviterEntry == null) return;
|
||||
if (inviterEntry == null) {
|
||||
return;
|
||||
}
|
||||
MapleMap map = (MapleMap) inviteResult.params[0];
|
||||
if(accept && inviter.getMap() == map) { //cancel if inviter has changed maps
|
||||
if (accept && inviter.getMap() == map) { //cancel if inviter has changed maps
|
||||
c.getPlayer().changeMap(map, map.getPortal(0));
|
||||
} else {
|
||||
inviterEntry.refundEntitlement(FamilyEntitlement.SUMMON_FAMILY);
|
||||
|
||||
@@ -35,35 +35,34 @@ import server.maps.MapleMap;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Moogra
|
||||
* @author Ubaware
|
||||
*/
|
||||
public final class FamilyUseHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
if(!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
if (!YamlConfig.config.server.USE_FAMILY_SYSTEM) {
|
||||
return;
|
||||
}
|
||||
FamilyEntitlement type = FamilyEntitlement.values()[p.readInt()];
|
||||
int cost = type.getRepCost();
|
||||
FamilyEntry entry = c.getPlayer().getFamilyEntry();
|
||||
if(entry.getReputation() < cost || entry.isEntitlementUsed(type)) {
|
||||
if (entry.getReputation() < cost || entry.isEntitlementUsed(type)) {
|
||||
return; // shouldn't even be able to request it
|
||||
}
|
||||
c.sendPacket(PacketCreator.getFamilyInfo(entry));
|
||||
Character victim;
|
||||
if(type == FamilyEntitlement.FAMILY_REUINION || type == FamilyEntitlement.SUMMON_FAMILY) {
|
||||
if (type == FamilyEntitlement.FAMILY_REUINION || type == FamilyEntitlement.SUMMON_FAMILY) {
|
||||
victim = c.getChannelServer().getPlayerStorage().getCharacterByName(p.readString());
|
||||
if(victim != null && victim != c.getPlayer()) {
|
||||
if(victim.getFamily() == c.getPlayer().getFamily()) {
|
||||
if (victim != null && victim != c.getPlayer()) {
|
||||
if (victim.getFamily() == c.getPlayer().getFamily()) {
|
||||
MapleMap targetMap = victim.getMap();
|
||||
MapleMap ownMap = c.getPlayer().getMap();
|
||||
if(targetMap != null) {
|
||||
if(type == FamilyEntitlement.FAMILY_REUINION) {
|
||||
if(!FieldLimit.CANNOTMIGRATE.check(ownMap.getFieldLimit()) && !FieldLimit.CANNOTVIPROCK.check(targetMap.getFieldLimit())
|
||||
if (targetMap != null) {
|
||||
if (type == FamilyEntitlement.FAMILY_REUINION) {
|
||||
if (!FieldLimit.CANNOTMIGRATE.check(ownMap.getFieldLimit()) && !FieldLimit.CANNOTVIPROCK.check(targetMap.getFieldLimit())
|
||||
&& (targetMap.getForcedReturnId() == 999999999 || targetMap.getId() < 100000000) && targetMap.getEventInstance() == null) {
|
||||
|
||||
|
||||
c.getPlayer().changeMap(victim.getMap(), victim.getMap().getPortal(0));
|
||||
useEntitlement(entry, type);
|
||||
} else {
|
||||
@@ -71,10 +70,10 @@ public final class FamilyUseHandler extends AbstractPacketHandler {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(!FieldLimit.CANNOTMIGRATE.check(targetMap.getFieldLimit()) && !FieldLimit.CANNOTVIPROCK.check(ownMap.getFieldLimit())
|
||||
if (!FieldLimit.CANNOTMIGRATE.check(targetMap.getFieldLimit()) && !FieldLimit.CANNOTVIPROCK.check(ownMap.getFieldLimit())
|
||||
&& (ownMap.getForcedReturnId() == 999999999 || ownMap.getId() < 100000000) && ownMap.getEventInstance() == null) {
|
||||
|
||||
if(InviteCoordinator.hasInvite(InviteType.FAMILY_SUMMON, victim.getId())) {
|
||||
|
||||
if (InviteCoordinator.hasInvite(InviteType.FAMILY_SUMMON, victim.getId())) {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(74, 0));
|
||||
return;
|
||||
}
|
||||
@@ -91,7 +90,7 @@ public final class FamilyUseHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.sendFamilyMessage(67, 0));
|
||||
}
|
||||
}
|
||||
} else if(type == FamilyEntitlement.FAMILY_BONDING) {
|
||||
} else if (type == FamilyEntitlement.FAMILY_BONDING) {
|
||||
//not implemented
|
||||
} else {
|
||||
boolean party = false;
|
||||
@@ -99,39 +98,39 @@ public final class FamilyUseHandler extends AbstractPacketHandler {
|
||||
float rate = 1.5f;
|
||||
int duration = 15;
|
||||
do {
|
||||
switch(type) {
|
||||
case PARTY_EXP_2_30MIN:
|
||||
party = true;
|
||||
isExp = true;
|
||||
type = FamilyEntitlement.SELF_EXP_2_30MIN;
|
||||
continue;
|
||||
case PARTY_DROP_2_30MIN:
|
||||
party = true;
|
||||
type = FamilyEntitlement.SELF_DROP_2_30MIN;
|
||||
continue;
|
||||
case SELF_DROP_2_30MIN:
|
||||
duration = 30;
|
||||
case SELF_DROP_2:
|
||||
rate = 2.0f;
|
||||
case SELF_DROP_1_5:
|
||||
break;
|
||||
case SELF_EXP_2_30MIN:
|
||||
duration = 30;
|
||||
case SELF_EXP_2:
|
||||
rate = 2.0f;
|
||||
case SELF_EXP_1_5:
|
||||
isExp = true;
|
||||
default:
|
||||
break;
|
||||
switch (type) {
|
||||
case PARTY_EXP_2_30MIN:
|
||||
party = true;
|
||||
isExp = true;
|
||||
type = FamilyEntitlement.SELF_EXP_2_30MIN;
|
||||
continue;
|
||||
case PARTY_DROP_2_30MIN:
|
||||
party = true;
|
||||
type = FamilyEntitlement.SELF_DROP_2_30MIN;
|
||||
continue;
|
||||
case SELF_DROP_2_30MIN:
|
||||
duration = 30;
|
||||
case SELF_DROP_2:
|
||||
rate = 2.0f;
|
||||
case SELF_DROP_1_5:
|
||||
break;
|
||||
case SELF_EXP_2_30MIN:
|
||||
duration = 30;
|
||||
case SELF_EXP_2:
|
||||
rate = 2.0f;
|
||||
case SELF_EXP_1_5:
|
||||
isExp = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
} while(true);
|
||||
} while (true);
|
||||
//not implemented
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean useEntitlement(FamilyEntry entry, FamilyEntitlement entitlement) {
|
||||
if(entry.useEntitlement(entitlement)) {
|
||||
if (entry.useEntitlement(entitlement)) {
|
||||
entry.gainReputation(-entitlement.getRepCost(), false);
|
||||
entry.getChr().sendPacket(PacketCreator.getFamilyInfo(entry));
|
||||
return true;
|
||||
|
||||
@@ -31,27 +31,27 @@ import tools.FilePrinter;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public class FieldDamageMobHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int mobOid = p.readInt(); // packet structure found thanks to Darter (Rajan)
|
||||
int dmg = p.readInt();
|
||||
|
||||
|
||||
Character chr = c.getPlayer();
|
||||
MapleMap map = chr.getMap();
|
||||
|
||||
|
||||
if (map.getEnvironment().isEmpty()) { // no environment objects activated to actually hit the mob
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use an obstacle on mapid " + map.getId() + " to attack.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Monster mob = map.getMonsterByOid(mobOid);
|
||||
if (mob != null) {
|
||||
if (dmg < 0 || dmg > GameConstants.MAX_FIELD_MOB_DAMAGE) {
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use an obstacle on mapid " + map.getId() + " to attack " + MonsterInformationProvider.getInstance().getMobNameFromId(mob.getId()) + " with damage " + dmg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
map.broadcastMessage(chr, PacketCreator.damageMonster(mobOid, dmg), true);
|
||||
map.damageMonster(chr, mob, dmg);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kevintjuh93
|
||||
*/
|
||||
public class FredrickHandler extends AbstractPacketHandler {
|
||||
|
||||
@@ -33,43 +33,43 @@ import tools.LogHelper;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public final class GeneralChatHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
String s = p.readString();
|
||||
Character chr = c.getPlayer();
|
||||
if(chr.getAutobanManager().getLastSpam(7) + 200 > currentServerTime()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (s.length() > Byte.MAX_VALUE && !chr.isGM()) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit in General Chat.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to send text with length of " + s.length());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
char heading = s.charAt(0);
|
||||
if (CommandsExecutor.isCommand(c, s)) {
|
||||
CommandsExecutor.getInstance().handle(c, s);
|
||||
} else if (heading != '/') {
|
||||
int show = p.readByte();
|
||||
if(chr.getMap().isMuted() && !chr.isGM()) {
|
||||
chr.dropMessage(5, "The map you are in is currently muted. Please try again later.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chr.isHidden()) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.getChatText(chr.getId(), s, chr.getWhiteChat(), show));
|
||||
if (YamlConfig.config.server.USE_ENABLE_CHAT_LOG) {
|
||||
LogHelper.logChat(c, "General", s);
|
||||
}
|
||||
} else {
|
||||
chr.getMap().broadcastGMMessage(PacketCreator.getChatText(chr.getId(), s, chr.getWhiteChat(), show));
|
||||
if (YamlConfig.config.server.USE_ENABLE_CHAT_LOG) {
|
||||
LogHelper.logChat(c, "GM General", s);
|
||||
}
|
||||
}
|
||||
|
||||
chr.getAutobanManager().spam(7);
|
||||
}
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
String s = p.readString();
|
||||
Character chr = c.getPlayer();
|
||||
if (chr.getAutobanManager().getLastSpam(7) + 200 > currentServerTime()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
if (s.length() > Byte.MAX_VALUE && !chr.isGM()) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit in General Chat.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to send text with length of " + s.length());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
char heading = s.charAt(0);
|
||||
if (CommandsExecutor.isCommand(c, s)) {
|
||||
CommandsExecutor.getInstance().handle(c, s);
|
||||
} else if (heading != '/') {
|
||||
int show = p.readByte();
|
||||
if (chr.getMap().isMuted() && !chr.isGM()) {
|
||||
chr.dropMessage(5, "The map you are in is currently muted. Please try again later.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chr.isHidden()) {
|
||||
chr.getMap().broadcastMessage(PacketCreator.getChatText(chr.getId(), s, chr.getWhiteChat(), show));
|
||||
if (YamlConfig.config.server.USE_ENABLE_CHAT_LOG) {
|
||||
LogHelper.logChat(c, "General", s);
|
||||
}
|
||||
} else {
|
||||
chr.getMap().broadcastGMMessage(PacketCreator.getChatText(chr.getId(), s, chr.getWhiteChat(), show));
|
||||
if (YamlConfig.config.server.USE_ENABLE_CHAT_LOG) {
|
||||
LogHelper.logChat(c, "GM General", s);
|
||||
}
|
||||
}
|
||||
|
||||
chr.getAutobanManager().spam(7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import tools.FilePrinter;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public final class GiveFameHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character target = (Character) c.getPlayer().getMap().getMapObject(p.readInt());
|
||||
@@ -46,7 +46,7 @@ public final class GiveFameHandler extends AbstractPacketHandler {
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FameStatus status = player.canGiveFame(target);
|
||||
if (status == FameStatus.OK) {
|
||||
if (target.gainFame(famechange, player, mode)) {
|
||||
|
||||
@@ -34,14 +34,14 @@ import java.awt.*;
|
||||
* @author GabrielSin
|
||||
*/
|
||||
public class GrenadeEffectHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
Point position = new Point(p.readInt(), p.readInt());
|
||||
int keyDown = p.readInt();
|
||||
int skillId = p.readInt();
|
||||
|
||||
|
||||
switch (skillId) {
|
||||
case NightWalker.POISON_BOMB:
|
||||
case Gunslinger.GRENADE:
|
||||
@@ -54,5 +54,5 @@ public class GrenadeEffectHandler extends AbstractPacketHandler {
|
||||
FilePrinter.printError(FilePrinter.UNHANDLED_EVENT, "The skill id: " + skillId + " is not coded in " + this.getClass().getName() + ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
mc.dropMessage(1, "The Guild name you have chosen is not accepted.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Set<Character> eligibleMembers = new HashSet<>(Guild.getEligiblePlayersForGuild(mc));
|
||||
if (eligibleMembers.size() < YamlConfig.config.server.CREATE_GUILD_MIN_PARTNERS) {
|
||||
if (mc.getMap().getAllPlayers().size() < YamlConfig.config.server.CREATE_GUILD_MIN_PARTNERS) {
|
||||
@@ -86,33 +86,34 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
// players may be unaware of not belonging on a party in order to become eligible, thanks Hair (Legalize) for pointing this out
|
||||
mc.dropMessage(1, "Please make sure everyone you are trying to invite is neither on a guild nor on a party.");
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!Party.createParty(mc, true)) {
|
||||
mc.dropMessage(1, "You cannot create a new Guild while in a party.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Set<Integer> eligibleCids = new HashSet<>();
|
||||
for (Character chr : eligibleMembers) {
|
||||
eligibleCids.add(chr.getId());
|
||||
}
|
||||
|
||||
|
||||
c.getWorldServer().getMatchCheckerCoordinator().createMatchConfirmation(MatchCheckerType.GUILD_CREATION, c.getWorld(), mc.getId(), eligibleCids, guildName);
|
||||
break;
|
||||
case 0x05:
|
||||
if (mc.getGuildId() <= 0 || mc.getGuildRank() > 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String targetName = p.readString();
|
||||
GuildResponse mgr = Guild.sendInvitation(c, targetName);
|
||||
if (mgr != null) {
|
||||
c.sendPacket(mgr.getPacket(targetName));
|
||||
} else {} // already sent invitation, do nothing
|
||||
|
||||
} else {
|
||||
} // already sent invitation, do nothing
|
||||
|
||||
break;
|
||||
case 0x06:
|
||||
if (mc.getGuildId() > 0) {
|
||||
@@ -125,27 +126,29 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
System.out.println("[Hack] " + mc.getName() + " attempted to join a guild with a different character id.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!Guild.answerInvitation(cid, mc.getName(), gid, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
mc.getMGC().setGuildId(gid); // joins the guild
|
||||
mc.getMGC().setGuildRank(5); // start at lowest rank
|
||||
mc.getMGC().setAllianceRank(5);
|
||||
|
||||
|
||||
int s = Server.getInstance().addGuildMember(mc.getMGC(), mc);
|
||||
if (s == 0) {
|
||||
mc.dropMessage(1, "The guild you are trying to join is already full.");
|
||||
mc.getMGC().setGuildId(0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
c.sendPacket(GuildPackets.showGuildInfo(mc));
|
||||
|
||||
|
||||
allianceId = mc.getGuild().getAllianceId();
|
||||
if(allianceId > 0) Server.getInstance().getAlliance(allianceId).updateAlliancePackets(mc);
|
||||
|
||||
if (allianceId > 0) {
|
||||
Server.getInstance().getAlliance(allianceId).updateAlliancePackets(mc);
|
||||
}
|
||||
|
||||
mc.saveGuildStatus(); // update database
|
||||
mc.getMap().broadcastPacket(mc, GuildPackets.guildNameChanged(mc.getId(), mc.getGuild().getName())); // thanks Vcoc for pointing out an issue with updating guild tooltip to players in the map
|
||||
mc.getMap().broadcastPacket(mc, GuildPackets.guildMarkChanged(mc.getId(), mc.getGuild()));
|
||||
@@ -157,15 +160,17 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
System.out.println("[Hack] " + mc.getName() + " tried to quit guild under the name \"" + name + "\" and current guild id of " + mc.getGuildId() + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
allianceId = mc.getGuild().getAllianceId();
|
||||
|
||||
|
||||
c.sendPacket(GuildPackets.updateGP(mc.getGuildId(), 0));
|
||||
Server.getInstance().leaveGuild(mc.getMGC());
|
||||
|
||||
|
||||
c.sendPacket(GuildPackets.showGuildInfo(null));
|
||||
if(allianceId > 0) Server.getInstance().getAlliance(allianceId).updateAlliancePackets(mc);
|
||||
|
||||
if (allianceId > 0) {
|
||||
Server.getInstance().getAlliance(allianceId).updateAlliancePackets(mc);
|
||||
}
|
||||
|
||||
mc.getMGC().setGuildId(0);
|
||||
mc.getMGC().setGuildRank(5);
|
||||
mc.saveGuildStatus();
|
||||
@@ -173,16 +178,18 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
break;
|
||||
case 0x08:
|
||||
allianceId = mc.getGuild().getAllianceId();
|
||||
|
||||
|
||||
cid = p.readInt();
|
||||
name = p.readString();
|
||||
if (mc.getGuildRank() > 2 || mc.getGuildId() <= 0) {
|
||||
System.out.println("[Hack] " + mc.getName() + " is trying to expel without rank 1 or 2.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Server.getInstance().expelMember(mc.getMGC(), name, cid);
|
||||
if(allianceId > 0) Server.getInstance().getAlliance(allianceId).updateAlliancePackets(mc);
|
||||
if (allianceId > 0) {
|
||||
Server.getInstance().getAlliance(allianceId).updateAlliancePackets(mc);
|
||||
}
|
||||
break;
|
||||
case 0x0d:
|
||||
if (mc.getGuildId() <= 0 || mc.getGuildRank() != 1) {
|
||||
@@ -193,7 +200,7 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
ranks[i] = p.readString();
|
||||
}
|
||||
|
||||
|
||||
Server.getInstance().changeRankTitle(mc.getGuildId(), ranks);
|
||||
break;
|
||||
case 0x0e:
|
||||
@@ -222,19 +229,21 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
short logo = p.readShort();
|
||||
byte logocolor = p.readByte();
|
||||
Server.getInstance().setGuildEmblem(mc.getGuildId(), bg, bgcolor, logo, logocolor);
|
||||
|
||||
|
||||
if (mc.getGuild() != null && mc.getGuild().getAllianceId() > 0) {
|
||||
Alliance alliance = mc.getAlliance();
|
||||
Server.getInstance().allianceMessage(alliance.getId(), GuildPackets.getGuildAlliances(alliance, c.getWorld()), -1, -1);
|
||||
}
|
||||
|
||||
|
||||
mc.gainMeso(-YamlConfig.config.server.CHANGE_EMBLEM_COST, true, false, true);
|
||||
mc.getGuild().broadcastNameChanged();
|
||||
mc.getGuild().broadcastEmblemChanged();
|
||||
break;
|
||||
case 0x10:
|
||||
if (mc.getGuildId() <= 0 || mc.getGuildRank() > 2) {
|
||||
if(mc.getGuildId() <= 0) System.out.println("[Hack] " + mc.getName() + " tried to change guild notice while not in a guild.");
|
||||
if (mc.getGuildId() <= 0) {
|
||||
System.out.println("[Hack] " + mc.getName() + " tried to change guild notice while not in a guild.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
String notice = p.readString();
|
||||
@@ -246,12 +255,12 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
case 0x1E:
|
||||
p.readInt();
|
||||
World wserv = c.getWorldServer();
|
||||
|
||||
|
||||
if (mc.getParty() != null) {
|
||||
wserv.getMatchCheckerCoordinator().dismissMatchConfirmation(mc.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int leaderid = wserv.getMatchCheckerCoordinator().getMatchConfirmationLeaderid(mc.getId());
|
||||
if (leaderid != -1) {
|
||||
boolean result = p.readByte() != 0;
|
||||
@@ -264,13 +273,13 @@ public final class GuildOperationHandler extends AbstractPacketHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wserv.getMatchCheckerCoordinator().answerMatchConfirmation(mc.getId(), result);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unhandled GUILD_OPERATION packet: \n" + p.toString());
|
||||
System.out.println("Unhandled GUILD_OPERATION packet: \n" + p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,24 +35,28 @@ public final class HealOvertimeHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
if(!chr.isLoggedinWorld()) return;
|
||||
|
||||
if (!chr.isLoggedinWorld()) {
|
||||
return;
|
||||
}
|
||||
|
||||
AutobanManager abm = chr.getAutobanManager();
|
||||
int timestamp = Server.getInstance().getCurrentTimestamp();
|
||||
p.skip(8);
|
||||
|
||||
|
||||
short healHP = p.readShort();
|
||||
if (healHP != 0) {
|
||||
abm.setTimestamp(8, timestamp, 28); // thanks Vcoc & Thora for pointing out d/c happening here
|
||||
if ((abm.getLastSpam(0) + 1500) > timestamp) AutobanFactory.FAST_HP_HEALING.addPoint(abm, "Fast hp healing");
|
||||
|
||||
if ((abm.getLastSpam(0) + 1500) > timestamp) {
|
||||
AutobanFactory.FAST_HP_HEALING.addPoint(abm, "Fast hp healing");
|
||||
}
|
||||
|
||||
MapleMap map = chr.getMap();
|
||||
int abHeal = (int)(77 * map.getRecovery() * 1.5); // thanks Ari for noticing players not getting healed in sauna in certain cases
|
||||
int abHeal = (int) (77 * map.getRecovery() * 1.5); // thanks Ari for noticing players not getting healed in sauna in certain cases
|
||||
if (healHP > abHeal) {
|
||||
AutobanFactory.HIGH_HP_HEALING.autoban(chr, "Healing: " + healHP + "; Max is " + abHeal + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
chr.addHP(healHP);
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.showHpHealed(chr.getId(), healHP), false);
|
||||
abm.spam(0, timestamp);
|
||||
|
||||
@@ -38,14 +38,13 @@ import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author XoticStory
|
||||
*/
|
||||
public final class HiredMerchantRequest extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
|
||||
|
||||
try {
|
||||
for (MapObject mmo : chr.getMap().getMapObjectsInRange(chr.getPosition(), 23000, Arrays.asList(MapObjectType.HIRED_MERCHANT, MapObjectType.PLAYER))) {
|
||||
if (mmo instanceof Character) {
|
||||
@@ -71,7 +70,7 @@ public final class HiredMerchantRequest extends AbstractPacketHandler {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
if (GameConstants.isFreeMarketRoom(chr.getMapId())) {
|
||||
if (!chr.hasMerchant()) {
|
||||
try {
|
||||
|
||||
@@ -26,7 +26,6 @@ import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BubblesDev
|
||||
*/
|
||||
public final class InnerPortalHandler extends AbstractPacketHandler {
|
||||
|
||||
@@ -41,37 +41,45 @@ public final class InventoryMergeHandler extends AbstractPacketHandler {
|
||||
Character chr = c.getPlayer();
|
||||
p.readInt();
|
||||
chr.getAutobanManager().setTimestamp(2, Server.getInstance().getCurrentTimestamp(), 4);
|
||||
|
||||
if(!YamlConfig.config.server.USE_ITEM_SORT) {
|
||||
|
||||
if (!YamlConfig.config.server.USE_ITEM_SORT) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
byte invType = p.readByte();
|
||||
if (invType < 1 || invType > 5) {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
InventoryType inventoryType = InventoryType.getByType(invType);
|
||||
Inventory inventory = c.getPlayer().getInventory(inventoryType);
|
||||
Inventory inventory = c.getPlayer().getInventory(inventoryType);
|
||||
inventory.lockInventory();
|
||||
try {
|
||||
//------------------- RonanLana's SLOT MERGER -----------------
|
||||
|
||||
|
||||
ItemInformationProvider ii = ItemInformationProvider.getInstance();
|
||||
Item srcItem, dstItem;
|
||||
|
||||
for(short dst = 1; dst <= inventory.getSlotLimit(); dst++) {
|
||||
for (short dst = 1; dst <= inventory.getSlotLimit(); dst++) {
|
||||
dstItem = inventory.getItem(dst);
|
||||
if(dstItem == null) continue;
|
||||
if (dstItem == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for(short src = (short)(dst + 1); src <= inventory.getSlotLimit(); src++) {
|
||||
for (short src = (short) (dst + 1); src <= inventory.getSlotLimit(); src++) {
|
||||
srcItem = inventory.getItem(src);
|
||||
if(srcItem == null) continue;
|
||||
if (srcItem == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(dstItem.getItemId() != srcItem.getItemId()) continue;
|
||||
if(dstItem.getQuantity() == ii.getSlotMax(c, inventory.getItem(dst).getItemId())) break;
|
||||
if (dstItem.getItemId() != srcItem.getItemId()) {
|
||||
continue;
|
||||
}
|
||||
if (dstItem.getQuantity() == ii.getSlotMax(c, inventory.getItem(dst).getItemId())) {
|
||||
break;
|
||||
}
|
||||
|
||||
InventoryManipulator.move(c, inventoryType, src, dst);
|
||||
}
|
||||
@@ -105,7 +113,7 @@ public final class InventoryMergeHandler extends AbstractPacketHandler {
|
||||
} finally {
|
||||
inventory.unlockInventory();
|
||||
}
|
||||
|
||||
|
||||
c.sendPacket(PacketCreator.finishedSort(inventoryType.getType()));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BubblesDev
|
||||
* @author Ronan
|
||||
*/
|
||||
@@ -45,18 +44,22 @@ class PairedQuicksort {
|
||||
private int j = 0;
|
||||
private final ArrayList<Integer> intersect;
|
||||
ItemInformationProvider ii = ItemInformationProvider.getInstance();
|
||||
|
||||
|
||||
private void PartitionByItemId(int Esq, int Dir, ArrayList<Item> A) {
|
||||
Item x, w;
|
||||
|
||||
i = Esq;
|
||||
j = Dir;
|
||||
|
||||
|
||||
x = A.get((i + j) / 2);
|
||||
do {
|
||||
while (x.getItemId() > A.get(i).getItemId()) i++;
|
||||
while (x.getItemId() < A.get(j).getItemId()) j--;
|
||||
|
||||
while (x.getItemId() > A.get(i).getItemId()) {
|
||||
i++;
|
||||
}
|
||||
while (x.getItemId() < A.get(j).getItemId()) {
|
||||
j--;
|
||||
}
|
||||
|
||||
if (i <= j) {
|
||||
w = A.get(i);
|
||||
A.set(i, A.get(j));
|
||||
@@ -67,23 +70,27 @@ class PairedQuicksort {
|
||||
}
|
||||
} while (i <= j);
|
||||
}
|
||||
|
||||
|
||||
private int getWatkForProjectile(Item item) {
|
||||
return ii.getWatkForProjectile(item.getItemId());
|
||||
}
|
||||
|
||||
|
||||
private void PartitionByProjectileAtk(int Esq, int Dir, ArrayList<Item> A) {
|
||||
Item x, w;
|
||||
|
||||
i = Esq;
|
||||
j = Dir;
|
||||
|
||||
|
||||
x = A.get((i + j) / 2);
|
||||
do {
|
||||
int watk = getWatkForProjectile(x);
|
||||
while (watk < getWatkForProjectile(A.get(i))) i++;
|
||||
while (watk > getWatkForProjectile(A.get(j))) j--;
|
||||
|
||||
while (watk < getWatkForProjectile(A.get(i))) {
|
||||
i++;
|
||||
}
|
||||
while (watk > getWatkForProjectile(A.get(j))) {
|
||||
j--;
|
||||
}
|
||||
|
||||
if (i <= j) {
|
||||
w = A.get(i);
|
||||
A.set(i, A.get(j));
|
||||
@@ -94,18 +101,22 @@ class PairedQuicksort {
|
||||
}
|
||||
} while (i <= j);
|
||||
}
|
||||
|
||||
|
||||
private void PartitionByName(int Esq, int Dir, ArrayList<Item> A) {
|
||||
Item x, w;
|
||||
|
||||
i = Esq;
|
||||
j = Dir;
|
||||
|
||||
|
||||
x = A.get((i + j) / 2);
|
||||
do {
|
||||
while (ii.getName(x.getItemId()).compareTo(ii.getName(A.get(i).getItemId())) > 0) i++;
|
||||
while (ii.getName(x.getItemId()).compareTo(ii.getName(A.get(j).getItemId())) < 0) j--;
|
||||
|
||||
while (ii.getName(x.getItemId()).compareTo(ii.getName(A.get(i).getItemId())) > 0) {
|
||||
i++;
|
||||
}
|
||||
while (ii.getName(x.getItemId()).compareTo(ii.getName(A.get(j).getItemId())) < 0) {
|
||||
j--;
|
||||
}
|
||||
|
||||
if (i <= j) {
|
||||
w = A.get(i);
|
||||
A.set(i, A.get(j));
|
||||
@@ -116,18 +127,22 @@ class PairedQuicksort {
|
||||
}
|
||||
} while (i <= j);
|
||||
}
|
||||
|
||||
|
||||
private void PartitionByQuantity(int Esq, int Dir, ArrayList<Item> A) {
|
||||
Item x, w;
|
||||
|
||||
i = Esq;
|
||||
j = Dir;
|
||||
|
||||
|
||||
x = A.get((i + j) / 2);
|
||||
do {
|
||||
while (x.getQuantity() > A.get(i).getQuantity()) i++;
|
||||
while (x.getQuantity() < A.get(j).getQuantity()) j--;
|
||||
|
||||
while (x.getQuantity() > A.get(i).getQuantity()) {
|
||||
i++;
|
||||
}
|
||||
while (x.getQuantity() < A.get(j).getQuantity()) {
|
||||
j--;
|
||||
}
|
||||
|
||||
if (i <= j) {
|
||||
w = A.get(i);
|
||||
A.set(i, A.get(j));
|
||||
@@ -138,22 +153,26 @@ class PairedQuicksort {
|
||||
}
|
||||
} while (i <= j);
|
||||
}
|
||||
|
||||
|
||||
private void PartitionByLevel(int Esq, int Dir, ArrayList<Item> A) {
|
||||
Equip x, w;
|
||||
|
||||
i = Esq;
|
||||
j = Dir;
|
||||
|
||||
x = (Equip)(A.get((i + j) / 2));
|
||||
|
||||
|
||||
x = (Equip) (A.get((i + j) / 2));
|
||||
|
||||
do {
|
||||
|
||||
while (x.getLevel() > ((Equip)A.get(i)).getLevel()) i++;
|
||||
while (x.getLevel() < ((Equip)A.get(j)).getLevel()) j--;
|
||||
|
||||
while (x.getLevel() > ((Equip) A.get(i)).getLevel()) {
|
||||
i++;
|
||||
}
|
||||
while (x.getLevel() < ((Equip) A.get(j)).getLevel()) {
|
||||
j--;
|
||||
}
|
||||
|
||||
if (i <= j) {
|
||||
w = (Equip)A.get(i);
|
||||
w = (Equip) A.get(i);
|
||||
A.set(i, A.get(j));
|
||||
A.set(j, w);
|
||||
|
||||
@@ -164,40 +183,44 @@ class PairedQuicksort {
|
||||
}
|
||||
|
||||
void MapleQuicksort(int Esq, int Dir, ArrayList<Item> A, int sort) {
|
||||
switch(sort) {
|
||||
switch (sort) {
|
||||
case 3:
|
||||
PartitionByLevel(Esq, Dir, A);
|
||||
break;
|
||||
|
||||
|
||||
case 2:
|
||||
PartitionByName(Esq, Dir, A);
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
PartitionByQuantity(Esq, Dir, A);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
PartitionByItemId(Esq, Dir, A);
|
||||
}
|
||||
|
||||
|
||||
if (Esq < j) MapleQuicksort(Esq, j, A, sort);
|
||||
if (i < Dir) MapleQuicksort(i, Dir, A, sort);
|
||||
|
||||
|
||||
if (Esq < j) {
|
||||
MapleQuicksort(Esq, j, A, sort);
|
||||
}
|
||||
if (i < Dir) {
|
||||
MapleQuicksort(i, Dir, A, sort);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int getItemSubtype(Item it) {
|
||||
return it.getItemId() / 10000;
|
||||
}
|
||||
|
||||
|
||||
private int[] BinarySearchElement(ArrayList<Item> A, int rangeId) {
|
||||
int st = 0, en = A.size() - 1;
|
||||
|
||||
|
||||
int mid = -1, idx = -1;
|
||||
while (en >= st) {
|
||||
idx = (st + en) / 2;
|
||||
mid = getItemSubtype(A.get(idx));
|
||||
|
||||
|
||||
if (mid == rangeId) {
|
||||
break;
|
||||
} else if (mid < rangeId) {
|
||||
@@ -206,55 +229,57 @@ class PairedQuicksort {
|
||||
en = idx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (en < st) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
st = idx - 1;
|
||||
en = idx + 1;
|
||||
while (st >= 0 && getItemSubtype(A.get(st)) == rangeId) {
|
||||
st -= 1;
|
||||
}
|
||||
st += 1;
|
||||
|
||||
|
||||
while (en < A.size() && getItemSubtype(A.get(en)) == rangeId) {
|
||||
en += 1;
|
||||
}
|
||||
en -= 1;
|
||||
|
||||
|
||||
return new int[]{st, en};
|
||||
}
|
||||
|
||||
|
||||
public void reverseSortSublist(ArrayList<Item> A, int[] range) {
|
||||
if (range != null) {
|
||||
PartitionByProjectileAtk(range[0], range[1], A);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PairedQuicksort(ArrayList<Item> A, int primarySort, int secondarySort) {
|
||||
intersect = new ArrayList<>();
|
||||
|
||||
if(A.size() > 0) {
|
||||
|
||||
if (A.size() > 0) {
|
||||
MapleQuicksort(0, A.size() - 1, A, primarySort);
|
||||
|
||||
|
||||
if (A.get(0).getInventoryType().equals(InventoryType.USE)) { // thanks KDA & Vcoc for suggesting stronger projectiles coming before weaker ones
|
||||
reverseSortSublist(A, BinarySearchElement(A, 206)); // arrows
|
||||
reverseSortSublist(A, BinarySearchElement(A, 207)); // stars
|
||||
reverseSortSublist(A, BinarySearchElement(A, 233)); // bullets
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
intersect.add(0);
|
||||
for(int ind = 1; ind < A.size(); ind++) {
|
||||
if(A.get(ind - 1).getItemId() != A.get(ind).getItemId()) {
|
||||
for (int ind = 1; ind < A.size(); ind++) {
|
||||
if (A.get(ind - 1).getItemId() != A.get(ind).getItemId()) {
|
||||
intersect.add(ind);
|
||||
}
|
||||
}
|
||||
intersect.add(A.size());
|
||||
|
||||
for(int ind = 0; ind < intersect.size() - 1; ind++) {
|
||||
if(intersect.get(ind + 1) > intersect.get(ind)) MapleQuicksort(intersect.get(ind), intersect.get(ind + 1) - 1, A, secondarySort);
|
||||
|
||||
for (int ind = 0; ind < intersect.size() - 1; ind++) {
|
||||
if (intersect.get(ind + 1) > intersect.get(ind)) {
|
||||
MapleQuicksort(intersect.get(ind), intersect.get(ind + 1) - 1, A, secondarySort);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,21 +290,21 @@ public final class InventorySortHandler extends AbstractPacketHandler {
|
||||
Character chr = c.getPlayer();
|
||||
p.readInt();
|
||||
chr.getAutobanManager().setTimestamp(3, Server.getInstance().getCurrentTimestamp(), 4);
|
||||
|
||||
if(!YamlConfig.config.server.USE_ITEM_SORT) {
|
||||
|
||||
if (!YamlConfig.config.server.USE_ITEM_SORT) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
byte invType = p.readByte();
|
||||
if (invType < 1 || invType > 5) {
|
||||
c.disconnect(false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ArrayList<Item> itemarray = new ArrayList<>();
|
||||
List<ModifyInventory> mods = new ArrayList<>();
|
||||
|
||||
|
||||
Inventory inventory = chr.getInventory(InventoryType.getByType(invType));
|
||||
inventory.lockInventory();
|
||||
try {
|
||||
@@ -307,7 +332,7 @@ public final class InventorySortHandler extends AbstractPacketHandler {
|
||||
} finally {
|
||||
inventory.unlockInventory();
|
||||
}
|
||||
|
||||
|
||||
c.sendPacket(PacketCreator.modifyInventory(true, mods));
|
||||
c.sendPacket(PacketCreator.finishedSort2(invType));
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
|
||||
@@ -29,23 +29,22 @@ import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
*/
|
||||
public final class ItemMoveHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
p.skip(4);
|
||||
if(c.getPlayer().getAutobanManager().getLastSpam(6) + 300 > currentServerTime()) {
|
||||
if (c.getPlayer().getAutobanManager().getLastSpam(6) + 300 > currentServerTime()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
InventoryType type = InventoryType.getByType(p.readByte());
|
||||
short src = p.readShort(); //is there any reason to use byte instead of short in src and action?
|
||||
short action = p.readShort();
|
||||
short quantity = p.readShort();
|
||||
|
||||
|
||||
if (src < 0 && action > 0) {
|
||||
InventoryManipulator.unequip(c, src, action);
|
||||
} else if (action < 0) {
|
||||
@@ -55,8 +54,10 @@ public final class ItemMoveHandler extends AbstractPacketHandler {
|
||||
} else {
|
||||
InventoryManipulator.move(c, type, src, action);
|
||||
}
|
||||
|
||||
if (c.getPlayer().getMap().getHPDec() > 0) c.getPlayer().resetHpDecreaseTask();
|
||||
|
||||
if (c.getPlayer().getMap().getHPDec() > 0) {
|
||||
c.getPlayer().resetHpDecreaseTask();
|
||||
}
|
||||
c.getPlayer().getAutobanManager().spam(6);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import tools.FilePrinter;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
* @author Ronan
|
||||
*/
|
||||
@@ -45,15 +44,17 @@ public final class ItemPickupHandler extends AbstractPacketHandler {
|
||||
int oid = p.readInt();
|
||||
Character chr = c.getPlayer();
|
||||
MapObject ob = chr.getMap().getMapObject(oid);
|
||||
if(ob == null) return;
|
||||
|
||||
if (ob == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point charPos = chr.getPosition();
|
||||
Point obPos = ob.getPosition();
|
||||
if (Math.abs(charPos.getX() - obPos.getX()) > 800 || Math.abs(charPos.getY() - obPos.getY()) > 600) {
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to pick up an item too far away. Mapid: " + chr.getMapId() + " Player pos: " + charPos + " Object pos: " + obPos);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
chr.pickupItem(ob);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,10 +46,12 @@ public final class ItemRewardHandler extends AbstractPacketHandler {
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
byte slot = (byte) p.readShort();
|
||||
int itemId = p.readInt(); // will load from xml I don't care.
|
||||
|
||||
|
||||
Item it = c.getPlayer().getInventory(InventoryType.USE).getItem(slot); // null check here thanks to Thora
|
||||
if (it == null || it.getItemId() != itemId || c.getPlayer().getInventory(InventoryType.USE).countById(itemId) < 1) return;
|
||||
|
||||
if (it == null || it.getItemId() != itemId || c.getPlayer().getInventory(InventoryType.USE).countById(itemId) < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemInformationProvider ii = ItemInformationProvider.getInstance();
|
||||
Pair<Integer, List<RewardItem>> rewards = ii.getItemReward(itemId);
|
||||
for (RewardItem reward : rewards.getRight()) {
|
||||
@@ -58,10 +60,10 @@ public final class ItemRewardHandler extends AbstractPacketHandler {
|
||||
break;
|
||||
}
|
||||
if (Randomizer.nextInt(rewards.getLeft()) < reward.prob) {//Is it even possible to get an item with prob 1?
|
||||
if (ItemConstants.getInventoryType(reward.itemid) == InventoryType.EQUIP) {
|
||||
if (ItemConstants.getInventoryType(reward.itemid) == InventoryType.EQUIP) {
|
||||
final Item item = ii.getEquipById(reward.itemid);
|
||||
if (reward.period != -1) {
|
||||
item.setExpiration(currentServerTime() + (reward.period * 60 * 60 * 10));
|
||||
item.setExpiration(currentServerTime() + (reward.period * 60 * 60 * 10));
|
||||
}
|
||||
InventoryManipulator.addFromDrop(c, item, false);
|
||||
} else {
|
||||
|
||||
@@ -31,53 +31,53 @@ import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
|
||||
public final class KeymapChangeHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
if (p.available() >= 8) {
|
||||
int mode = p.readInt();
|
||||
if(mode == 0) {
|
||||
int numChanges = p.readInt();
|
||||
for (int i = 0; i < numChanges; i++) {
|
||||
int key = p.readInt();
|
||||
int type = p.readByte();
|
||||
int action = p.readInt();
|
||||
|
||||
if(type == 1) {
|
||||
Skill skill = SkillFactory.getSkill(action);
|
||||
boolean isBanndedSkill;
|
||||
if (skill != null) {
|
||||
isBanndedSkill = GameConstants.bannedBindSkills(skill.getId());
|
||||
if (isBanndedSkill || (!c.getPlayer().isGM() && GameConstants.isGMSkills(skill.getId())) || (!GameConstants.isInJobTree(skill.getId(), c.getPlayer().getJob().getId()) && !c.getPlayer().isGM())) { //for those skills are are "technically" in the beginner tab, like bamboo rain in Dojo or skills you find in PYPQ
|
||||
//AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit keymapping.");
|
||||
//FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use skill " + skill.getId());
|
||||
//c.disconnect(true, false);
|
||||
//return;
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
if (p.available() >= 8) {
|
||||
int mode = p.readInt();
|
||||
if (mode == 0) {
|
||||
int numChanges = p.readInt();
|
||||
for (int i = 0; i < numChanges; i++) {
|
||||
int key = p.readInt();
|
||||
int type = p.readByte();
|
||||
int action = p.readInt();
|
||||
|
||||
continue; // fk that
|
||||
}
|
||||
if (type == 1) {
|
||||
Skill skill = SkillFactory.getSkill(action);
|
||||
boolean isBanndedSkill;
|
||||
if (skill != null) {
|
||||
isBanndedSkill = GameConstants.bannedBindSkills(skill.getId());
|
||||
if (isBanndedSkill || (!c.getPlayer().isGM() && GameConstants.isGMSkills(skill.getId())) || (!GameConstants.isInJobTree(skill.getId(), c.getPlayer().getJob().getId()) && !c.getPlayer().isGM())) { //for those skills are are "technically" in the beginner tab, like bamboo rain in Dojo or skills you find in PYPQ
|
||||
//AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit keymapping.");
|
||||
//FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use skill " + skill.getId());
|
||||
//c.disconnect(true, false);
|
||||
//return;
|
||||
|
||||
continue; // fk that
|
||||
}
|
||||
/* if (c.getPlayer().getSkillLevel(skill) < 1) { HOW WOULD A SKILL EVEN BE AVAILABLE TO KEYBINDING
|
||||
continue; IF THERE IS NOT EVEN A SINGLE POINT USED INTO IT??
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
c.getPlayer().changeKeybinding(key, new KeyBinding(type, action));
|
||||
}
|
||||
} else if(mode == 1) { // Auto HP Potion
|
||||
int itemID = p.readInt();
|
||||
if(itemID != 0 && c.getPlayer().getInventory(InventoryType.USE).findById(itemID) == null) {
|
||||
c.disconnect(false, false); // Don't let them send a packet with a use item they dont have.
|
||||
return;
|
||||
}
|
||||
c.getPlayer().changeKeybinding(91, new KeyBinding(7, itemID));
|
||||
} else if(mode == 2) { // Auto MP Potion
|
||||
int itemID = p.readInt();
|
||||
if(itemID != 0 && c.getPlayer().getInventory(InventoryType.USE).findById(itemID) == null) {
|
||||
c.disconnect(false, false); // Don't let them send a packet with a use item they dont have.
|
||||
return;
|
||||
}
|
||||
c.getPlayer().changeKeybinding(92, new KeyBinding(7, itemID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.getPlayer().changeKeybinding(key, new KeyBinding(type, action));
|
||||
}
|
||||
} else if (mode == 1) { // Auto HP Potion
|
||||
int itemID = p.readInt();
|
||||
if (itemID != 0 && c.getPlayer().getInventory(InventoryType.USE).findById(itemID) == null) {
|
||||
c.disconnect(false, false); // Don't let them send a packet with a use item they dont have.
|
||||
return;
|
||||
}
|
||||
c.getPlayer().changeKeybinding(91, new KeyBinding(7, itemID));
|
||||
} else if (mode == 2) { // Auto MP Potion
|
||||
int itemID = p.readInt();
|
||||
if (itemID != 0 && c.getPlayer().getInventory(InventoryType.USE).findById(itemID) == null) {
|
||||
c.disconnect(false, false); // Don't let them send a packet with a use item they dont have.
|
||||
return;
|
||||
}
|
||||
c.getPlayer().changeKeybinding(92, new KeyBinding(7, itemID));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,11 @@ import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kevintjuh93
|
||||
*/
|
||||
public class LeftKnockbackHandler extends AbstractPacketHandler {
|
||||
public void handlePacket(InPacket p, final Client c) {
|
||||
c.sendPacket(PacketCreator.leftKnockBack());
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
public void handlePacket(InPacket p, final Client c) {
|
||||
c.sendPacket(PacketCreator.leftKnockBack());
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
// TODO add karma-to-untradeable flag on sold items here
|
||||
|
||||
|
||||
if (!c.getPlayer().getCashShop().isOpened()) {
|
||||
return;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
Connection con = null;
|
||||
try {
|
||||
con = DatabaseConnection.getConnection();
|
||||
|
||||
|
||||
PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM mts_items WHERE seller = ?");
|
||||
ps.setInt(1, c.getPlayer().getId());
|
||||
ResultSet rs = ps.executeQuery();
|
||||
@@ -214,7 +214,7 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
ps.executeUpdate();
|
||||
ps.close();
|
||||
InventoryManipulator.removeFromSlot(c, invType, slot, quantity, false);
|
||||
|
||||
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
@@ -537,7 +537,7 @@ public final class MTSHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.MTSFailBuy());
|
||||
}
|
||||
} else {
|
||||
System.out.println("Unhandled OP(MTS): " + op + " Packet: " + p.toString());
|
||||
System.out.println("Unhandled OP(MTS): " + op + " Packet: " + p);
|
||||
}
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.showMTSCash(c.getPlayer()));
|
||||
|
||||
@@ -35,9 +35,9 @@ import server.StatEffect;
|
||||
import tools.PacketCreator;
|
||||
|
||||
public final class MagicDamageHandler extends AbstractDealDamageHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character chr = c.getPlayer();
|
||||
|
||||
/*long timeElapsed = currentServerTime() - chr.getAutobanManager().getLastSpam(8);
|
||||
if(timeElapsed < 300) {
|
||||
@@ -45,43 +45,43 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
|
||||
}
|
||||
chr.getAutobanManager().spam(8);*/
|
||||
|
||||
AttackInfo attack = parseDamage(p, chr, false, true);
|
||||
|
||||
if (chr.getBuffEffect(BuffStat.MORPH) != null) {
|
||||
if(chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
// How are they attacking when the client won't let them?
|
||||
chr.getClient().disconnect(false, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameConstants.isDojo(chr.getMap().getId()) && attack.numAttacked > 0) {
|
||||
chr.setDojoEnergy(chr.getDojoEnergy() + + YamlConfig.config.server.DOJO_ENERGY_ATK);
|
||||
c.sendPacket(PacketCreator.getEnergy("energy", chr.getDojoEnergy()));
|
||||
}
|
||||
AttackInfo attack = parseDamage(p, chr, false, true);
|
||||
|
||||
int charge = (attack.skill == Evan.FIRE_BREATH || attack.skill == Evan.ICE_BREATH || attack.skill == FPArchMage.BIG_BANG || attack.skill == ILArchMage.BIG_BANG || attack.skill == Bishop.BIG_BANG) ? attack.charge : -1;
|
||||
Packet packet = PacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, charge, attack.speed, attack.direction, attack.display);
|
||||
|
||||
chr.getMap().broadcastMessage(chr, packet, false, true);
|
||||
StatEffect effect = attack.getAttackEffect(chr, null);
|
||||
Skill skill = SkillFactory.getSkill(attack.skill);
|
||||
StatEffect effect_ = skill.getEffect(chr.getSkillLevel(skill));
|
||||
if (effect_.getCooldown() > 0) {
|
||||
if (chr.skillIsCooling(attack.skill)) {
|
||||
return;
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.skillCooldown(attack.skill, effect_.getCooldown()));
|
||||
chr.addCooldown(attack.skill, currentServerTime(), effect_.getCooldown() * 1000);
|
||||
}
|
||||
}
|
||||
applyAttack(attack, chr, effect.getAttackCount());
|
||||
Skill eaterSkill = SkillFactory.getSkill((chr.getJob().getId() - (chr.getJob().getId() % 10)) * 10000);// MP Eater, works with right job
|
||||
int eaterLevel = chr.getSkillLevel(eaterSkill);
|
||||
if (eaterLevel > 0) {
|
||||
for (Integer singleDamage : attack.allDamage.keySet()) {
|
||||
eaterSkill.getEffect(eaterLevel).applyPassive(chr, chr.getMap().getMapObject(singleDamage), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chr.getBuffEffect(BuffStat.MORPH) != null) {
|
||||
if (chr.getBuffEffect(BuffStat.MORPH).isMorphWithoutAttack()) {
|
||||
// How are they attacking when the client won't let them?
|
||||
chr.getClient().disconnect(false, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameConstants.isDojo(chr.getMap().getId()) && attack.numAttacked > 0) {
|
||||
chr.setDojoEnergy(chr.getDojoEnergy() + +YamlConfig.config.server.DOJO_ENERGY_ATK);
|
||||
c.sendPacket(PacketCreator.getEnergy("energy", chr.getDojoEnergy()));
|
||||
}
|
||||
|
||||
int charge = (attack.skill == Evan.FIRE_BREATH || attack.skill == Evan.ICE_BREATH || attack.skill == FPArchMage.BIG_BANG || attack.skill == ILArchMage.BIG_BANG || attack.skill == Bishop.BIG_BANG) ? attack.charge : -1;
|
||||
Packet packet = PacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, charge, attack.speed, attack.direction, attack.display);
|
||||
|
||||
chr.getMap().broadcastMessage(chr, packet, false, true);
|
||||
StatEffect effect = attack.getAttackEffect(chr, null);
|
||||
Skill skill = SkillFactory.getSkill(attack.skill);
|
||||
StatEffect effect_ = skill.getEffect(chr.getSkillLevel(skill));
|
||||
if (effect_.getCooldown() > 0) {
|
||||
if (chr.skillIsCooling(attack.skill)) {
|
||||
return;
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.skillCooldown(attack.skill, effect_.getCooldown()));
|
||||
chr.addCooldown(attack.skill, currentServerTime(), effect_.getCooldown() * 1000);
|
||||
}
|
||||
}
|
||||
applyAttack(attack, chr, effect.getAttackCount());
|
||||
Skill eaterSkill = SkillFactory.getSkill((chr.getJob().getId() - (chr.getJob().getId() % 10)) * 10000);// MP Eater, works with right job
|
||||
int eaterLevel = chr.getSkillLevel(eaterSkill);
|
||||
if (eaterLevel > 0) {
|
||||
for (Integer singleDamage : attack.allDamage.keySet()) {
|
||||
eaterSkill.getEffect(eaterLevel).applyPassive(chr, chr.getMap().getMapObject(singleDamage), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,10 @@ import net.AbstractPacketHandler;
|
||||
import net.packet.InPacket;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jay Estrella, Ronan
|
||||
*/
|
||||
public final class MakerSkillHandler extends AbstractPacketHandler {
|
||||
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
MakerProcessor.makerAction(p, c);
|
||||
|
||||
@@ -28,41 +28,40 @@ import net.packet.InPacket;
|
||||
import tools.PacketCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matze
|
||||
* @author Ronan - concurrency protection
|
||||
*/
|
||||
public final class MesoDropHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character player = c.getPlayer();
|
||||
if (!player.isAlive()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
p.skip(4);
|
||||
int meso = p.readInt();
|
||||
|
||||
if (c.tryacquireClient()) { // thanks imbee for noticing players not being able to throw mesos too fast
|
||||
try {
|
||||
if (meso <= player.getMeso() && meso > 9 && meso < 50001) {
|
||||
player.gainMeso(-meso, false, true, false);
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
c.releaseClient();
|
||||
}
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.attemptCatchFish(meso)) {
|
||||
player.getMap().disappearingMesoDrop(meso, player, player, player.getPosition());
|
||||
} else {
|
||||
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2);
|
||||
}
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character player = c.getPlayer();
|
||||
if (!player.isAlive()) {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
p.skip(4);
|
||||
int meso = p.readInt();
|
||||
|
||||
if (c.tryacquireClient()) { // thanks imbee for noticing players not being able to throw mesos too fast
|
||||
try {
|
||||
if (meso <= player.getMeso() && meso > 9 && meso < 50001) {
|
||||
player.gainMeso(-meso, false, true, false);
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
c.releaseClient();
|
||||
}
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.attemptCatchFish(meso)) {
|
||||
player.getMap().disappearingMesoDrop(meso, player, player, player.getPosition());
|
||||
} else {
|
||||
player.getMap().spawnMesoDrop(meso, player.getPosition(), player, player, true, (byte) 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,10 @@ public final class MobBanishPlayerHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int mobid = p.readInt(); // mob banish handling detected thanks to MedicOP
|
||||
|
||||
|
||||
Character chr = c.getPlayer();
|
||||
Monster mob = chr.getMap().getMonsterById(mobid);
|
||||
|
||||
|
||||
if (mob != null) {
|
||||
BanishInfo banishInfo = mob.getBanish();
|
||||
if (banishInfo != null) {
|
||||
|
||||
@@ -31,59 +31,58 @@ import tools.PacketCreator;
|
||||
import tools.Randomizer;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Xotic (XoticStory) & BubblesDev
|
||||
*/
|
||||
|
||||
public final class MobDamageMobFriendlyHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int attacker = p.readInt();
|
||||
p.readInt();
|
||||
int damaged = p.readInt();
|
||||
|
||||
MapleMap map = c.getPlayer().getMap();
|
||||
Monster monster = map.getMonsterByOid(damaged);
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
int attacker = p.readInt();
|
||||
p.readInt();
|
||||
int damaged = p.readInt();
|
||||
|
||||
if (monster == null || map.getMonsterByOid(attacker) == null) {
|
||||
return;
|
||||
}
|
||||
MapleMap map = c.getPlayer().getMap();
|
||||
Monster monster = map.getMonsterByOid(damaged);
|
||||
|
||||
int damage = Randomizer.nextInt(((monster.getMaxHp() / 13 + monster.getPADamage() * 10)) * 2 + 500) / 10; // Formula planned by Beng.
|
||||
|
||||
if (monster.getHp() - damage < 1) { // friendly dies
|
||||
if(monster.getId() == 9300102) {
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "The Watch Hog has been injured by the aliens. Better luck next time..."));
|
||||
} else if (monster.getId() == 9300061) { //moon bunny
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "The Moon Bunny went home because he was sick."));
|
||||
} else if(monster.getId() == 9300093) { //tylus
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Tylus has fallen by the overwhelming forces of the ambush."));
|
||||
} else if(monster.getId() == 9300137) { //juliet
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Juliet has fainted in the middle of the combat."));
|
||||
} else if(monster.getId() == 9300138) { //romeo
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Romeo has fainted in the middle of the combat."));
|
||||
} else if(monster.getId() == 9400322 || monster.getId() == 9400327 || monster.getId() == 9400332) { //snowman
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "The Snowman has melted on the heat of the battle."));
|
||||
} else if(monster.getId() == 9300162) { //delli
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Delli vanished after the ambush, sheets still laying on the ground..."));
|
||||
}
|
||||
|
||||
map.killFriendlies(monster);
|
||||
} else {
|
||||
EventInstanceManager eim = map.getEventInstance();
|
||||
if (eim != null) {
|
||||
eim.friendlyDamaged(monster);
|
||||
}
|
||||
}
|
||||
|
||||
monster.applyAndGetHpDamage(damage, false);
|
||||
int remainingHp = monster.getHp();
|
||||
if(remainingHp <= 0) {
|
||||
remainingHp = 0;
|
||||
map.removeMapObject(monster);
|
||||
}
|
||||
if (monster == null || map.getMonsterByOid(attacker) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
map.broadcastMessage(PacketCreator.MobDamageMobFriendly(monster, damage, remainingHp), monster.getPosition());
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
int damage = Randomizer.nextInt(((monster.getMaxHp() / 13 + monster.getPADamage() * 10)) * 2 + 500) / 10; // Formula planned by Beng.
|
||||
|
||||
if (monster.getHp() - damage < 1) { // friendly dies
|
||||
if (monster.getId() == 9300102) {
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "The Watch Hog has been injured by the aliens. Better luck next time..."));
|
||||
} else if (monster.getId() == 9300061) { //moon bunny
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "The Moon Bunny went home because he was sick."));
|
||||
} else if (monster.getId() == 9300093) { //tylus
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Tylus has fallen by the overwhelming forces of the ambush."));
|
||||
} else if (monster.getId() == 9300137) { //juliet
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Juliet has fainted in the middle of the combat."));
|
||||
} else if (monster.getId() == 9300138) { //romeo
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Romeo has fainted in the middle of the combat."));
|
||||
} else if (monster.getId() == 9400322 || monster.getId() == 9400327 || monster.getId() == 9400332) { //snowman
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "The Snowman has melted on the heat of the battle."));
|
||||
} else if (monster.getId() == 9300162) { //delli
|
||||
map.broadcastMessage(PacketCreator.serverNotice(6, "Delli vanished after the ambush, sheets still laying on the ground..."));
|
||||
}
|
||||
|
||||
map.killFriendlies(monster);
|
||||
} else {
|
||||
EventInstanceManager eim = map.getEventInstance();
|
||||
if (eim != null) {
|
||||
eim.friendlyDamaged(monster);
|
||||
}
|
||||
}
|
||||
|
||||
monster.applyAndGetHpDamage(damage, false);
|
||||
int remainingHp = monster.getHp();
|
||||
if (remainingHp <= 0) {
|
||||
remainingHp = 0;
|
||||
map.removeMapObject(monster);
|
||||
}
|
||||
|
||||
map.broadcastMessage(PacketCreator.MobDamageMobFriendly(monster, damage, remainingHp), monster.getPosition());
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,6 @@ import tools.PacketCreator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jay Estrella
|
||||
* @author Ronan
|
||||
*/
|
||||
@@ -50,54 +49,54 @@ public final class MobDamageMobHandler extends AbstractPacketHandler {
|
||||
boolean magic = p.readByte() == 0;
|
||||
int dmg = p.readInt();
|
||||
Character chr = c.getPlayer();
|
||||
|
||||
|
||||
MapleMap map = chr.getMap();
|
||||
Monster attacker = map.getMonsterByOid(from);
|
||||
Monster damaged = map.getMonsterByOid(to);
|
||||
|
||||
|
||||
if (attacker != null && damaged != null) {
|
||||
int maxDmg = calcMaxDamage(attacker, damaged, magic); // thanks Darter (YungMoozi) for reporting unchecked dmg
|
||||
|
||||
|
||||
if (dmg > maxDmg) {
|
||||
AutobanFactory.DAMAGE_HACK.alert(c.getPlayer(), "Possible packet editing hypnotize damage exploit."); // thanks Rien dev team
|
||||
|
||||
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " had hypnotized " + MonsterInformationProvider.getInstance().getMobNameFromId(attacker.getId()) + " to attack " + MonsterInformationProvider.getInstance().getMobNameFromId(damaged.getId()) + " with damage " + dmg + " (max: " + maxDmg + ")");
|
||||
dmg = maxDmg;
|
||||
}
|
||||
|
||||
|
||||
map.damageMonster(chr, damaged, dmg);
|
||||
map.broadcastMessage(chr, PacketCreator.damageMonster(to, dmg), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int calcMaxDamage(Monster attacker, Monster damaged, boolean magic) {
|
||||
int attackerAtk, damagedDef, attackerLevel = attacker.getLevel();
|
||||
double maxDamage;
|
||||
if (magic) {
|
||||
int atkRate = calcModifier(attacker, MonsterStatus.MAGIC_ATTACK_UP, MonsterStatus.MATK);
|
||||
attackerAtk = (attacker.getStats().getMADamage() * atkRate) / 100;
|
||||
|
||||
|
||||
int defRate = calcModifier(damaged, MonsterStatus.MAGIC_DEFENSE_UP, MonsterStatus.MDEF);
|
||||
damagedDef = (damaged.getStats().getMDDamage() * defRate) / 100;
|
||||
|
||||
|
||||
maxDamage = ((attackerAtk * (1.15 + (0.025 * attackerLevel))) - (0.75 * damagedDef)) * (Math.log(Math.abs(damagedDef - attackerAtk)) / Math.log(12));
|
||||
} else {
|
||||
int atkRate = calcModifier(attacker, MonsterStatus.WEAPON_ATTACK_UP, MonsterStatus.WATK);
|
||||
attackerAtk = (attacker.getStats().getPADamage() * atkRate) / 100;
|
||||
|
||||
|
||||
int defRate = calcModifier(damaged, MonsterStatus.WEAPON_DEFENSE_UP, MonsterStatus.WDEF);
|
||||
damagedDef = (damaged.getStats().getPDDamage() * defRate) / 100;
|
||||
|
||||
|
||||
maxDamage = ((attackerAtk * (1.15 + (0.025 * attackerLevel))) - (0.75 * damagedDef)) * (Math.log(Math.abs(damagedDef - attackerAtk)) / Math.log(17));
|
||||
}
|
||||
|
||||
|
||||
return (int) maxDamage;
|
||||
}
|
||||
|
||||
|
||||
private static int calcModifier(Monster monster, MonsterStatus buff, MonsterStatus nerf) {
|
||||
int atkModifier;
|
||||
final Map<MonsterStatus, MonsterStatusEffect> monsterStati = monster.getStati();
|
||||
|
||||
|
||||
MonsterStatusEffect atkBuff = monsterStati.get(buff);
|
||||
if (atkBuff != null) {
|
||||
atkModifier = atkBuff.getStati().get(buff);
|
||||
@@ -109,7 +108,7 @@ public final class MobDamageMobHandler extends AbstractPacketHandler {
|
||||
if (atkNerf != null) {
|
||||
atkModifier -= atkNerf.getStati().get(nerf);
|
||||
}
|
||||
|
||||
|
||||
return atkModifier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
*@author Drago (Dragohe4rt)
|
||||
*/
|
||||
* @author Drago (Dragohe4rt)
|
||||
*/
|
||||
|
||||
public final class MonsterCarnivalHandler extends AbstractPacketHandler {
|
||||
|
||||
@@ -54,7 +54,7 @@ public final class MonsterCarnivalHandler extends AbstractPacketHandler {
|
||||
int tab = p.readByte();
|
||||
int num = p.readByte();
|
||||
int neededCP = 0;
|
||||
if (tab == 0) {
|
||||
if (tab == 0) {
|
||||
final List<Pair<Integer, Integer>> mobs = c.getPlayer().getMap().getMobsToSpawn();
|
||||
if (num >= mobs.size() || c.getPlayer().getCP() < mobs.get(num).right) {
|
||||
c.sendPacket(PacketCreator.CPQMessage((byte) 1));
|
||||
@@ -70,7 +70,7 @@ public final class MonsterCarnivalHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (c.getPlayer().getTeam() == 0) {
|
||||
mcpq.summonR();
|
||||
} else {
|
||||
@@ -139,7 +139,7 @@ public final class MonsterCarnivalHandler extends AbstractPacketHandler {
|
||||
c.sendPacket(PacketCreator.enableActions());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
MonsterCarnival mcpq = c.getPlayer().getMonsterCarnival();
|
||||
if (mcpq != null) {
|
||||
if (!mcpq.canGuardianR() && c.getPlayer().getTeam() == 0 || !mcpq.canGuardianB() && c.getPlayer().getTeam() == 1) {
|
||||
@@ -171,7 +171,7 @@ public final class MonsterCarnivalHandler extends AbstractPacketHandler {
|
||||
}
|
||||
c.getPlayer().gainCP(-neededCP);
|
||||
c.getPlayer().getMap().broadcastMessage(PacketCreator.playerSummoned(c.getPlayer().getName(), tab, num));
|
||||
}catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -43,13 +43,14 @@ public class MoveDragonHandler extends AbstractMovementPacketHandler {
|
||||
updatePosition(p, dragon, 0);
|
||||
long movementDataLength = p.getPosition() - movementDataStart; //how many bytes were read by updatePosition
|
||||
p.seek(movementDataStart);
|
||||
|
||||
|
||||
if (chr.isHidden()) {
|
||||
chr.getMap().broadcastGMPacket(chr, PacketCreator.moveDragon(dragon, startPos, p, movementDataLength));
|
||||
} else {
|
||||
chr.getMap().broadcastMessage(chr, PacketCreator.moveDragon(dragon, startPos, p, movementDataLength), dragon.getPosition());
|
||||
}
|
||||
} catch (EmptyMovementException e) {}
|
||||
} catch (EmptyMovementException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,138 +47,141 @@ import java.util.List;
|
||||
* @author Ronan (HeavenMS)
|
||||
*/
|
||||
public final class MoveLifeHandler extends AbstractMovementPacketHandler {
|
||||
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character player = c.getPlayer();
|
||||
MapleMap map = player.getMap();
|
||||
|
||||
if (player.isChangingMaps()) { // thanks Lame for noticing mob movement shuffle (mob OID on different maps) happening on map transitions
|
||||
return;
|
||||
}
|
||||
|
||||
int objectid = p.readInt();
|
||||
short moveid = p.readShort();
|
||||
MapObject mmo = map.getMapObject(objectid);
|
||||
if (mmo == null || mmo.getType() != MapObjectType.MONSTER) {
|
||||
return;
|
||||
}
|
||||
|
||||
Monster monster = (Monster) mmo;
|
||||
List<Character> banishPlayers = null;
|
||||
|
||||
byte pNibbles = p.readByte();
|
||||
byte rawActivity = p.readByte();
|
||||
int skillId = p.readByte() & 0xff;
|
||||
int skillLv = p.readByte() & 0xff;
|
||||
short pOption = p.readShort();
|
||||
p.skip(8);
|
||||
|
||||
if (rawActivity >= 0) {
|
||||
rawActivity = (byte) (rawActivity & 0xFF >> 1);
|
||||
}
|
||||
|
||||
boolean isAttack = inRangeInclusive(rawActivity, 24, 41);
|
||||
boolean isSkill = inRangeInclusive(rawActivity, 42, 59);
|
||||
|
||||
MobSkill toUse = null;
|
||||
int useSkillId = 0, useSkillLevel = 0;
|
||||
|
||||
MobSkill nextUse = null;
|
||||
int nextSkillId = 0, nextSkillLevel = 0;
|
||||
|
||||
boolean nextMovementCouldBeSkill = !(isSkill || (pNibbles != 0));
|
||||
|
||||
int castPos;
|
||||
if (isSkill) {
|
||||
useSkillId = skillId;
|
||||
useSkillLevel = skillLv;
|
||||
|
||||
castPos = monster.getSkillPos(useSkillId, useSkillLevel);
|
||||
if (castPos != -1) {
|
||||
toUse = MobSkillFactory.getMobSkill(useSkillId, useSkillLevel);
|
||||
|
||||
if (monster.canUseSkill(toUse, true)) {
|
||||
int animationTime = MonsterInformationProvider.getInstance().getMobSkillAnimationTime(toUse);
|
||||
if(animationTime > 0 && toUse.getSkillId() != 129) {
|
||||
toUse.applyDelayedEffect(player, monster, true, animationTime);
|
||||
} else {
|
||||
banishPlayers = new LinkedList<>();
|
||||
toUse.applyEffect(player, monster, true, banishPlayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
castPos = (rawActivity - 24) / 2;
|
||||
|
||||
int atkStatus = monster.canUseAttack(castPos, isSkill);
|
||||
if (atkStatus < 1) {
|
||||
rawActivity = -1;
|
||||
pOption = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mobMp = monster.getMp();
|
||||
if (nextMovementCouldBeSkill) {
|
||||
int noSkills = monster.getNoSkills();
|
||||
if (noSkills > 0) {
|
||||
int rndSkill = Randomizer.nextInt(noSkills);
|
||||
|
||||
Pair<Integer, Integer> skillToUse = monster.getSkills().get(rndSkill);
|
||||
nextSkillId = skillToUse.getLeft();
|
||||
nextSkillLevel = skillToUse.getRight();
|
||||
nextUse = MobSkillFactory.getMobSkill(nextSkillId, nextSkillLevel);
|
||||
|
||||
if (!(nextUse != null && monster.canUseSkill(nextUse, false) && nextUse.getHP() >= (int) (((float) monster.getHp() / monster.getMaxHp()) * 100) && mobMp >= nextUse.getMpCon())) {
|
||||
// thanks OishiiKawaiiDesu for noticing mobs trying to cast skills they are not supposed to be able
|
||||
|
||||
nextSkillId = 0;
|
||||
nextSkillLevel = 0;
|
||||
nextUse = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.readByte();
|
||||
p.readInt(); // whatever
|
||||
short start_x = p.readShort(); // hmm.. startpos?
|
||||
short start_y = p.readShort(); // hmm...
|
||||
Point startPos = new Point(start_x, start_y - 2);
|
||||
Point serverStartPos = new Point(monster.getPosition());
|
||||
|
||||
Boolean aggro = monster.aggroMoveLifeUpdate(player);
|
||||
if (aggro == null) return;
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character player = c.getPlayer();
|
||||
MapleMap map = player.getMap();
|
||||
|
||||
if (nextUse != null) {
|
||||
c.sendPacket(PacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro, nextSkillId, nextSkillLevel));
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro));
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
int movementDataStart = p.getPosition();
|
||||
updatePosition(p, monster, -2); // Thanks Doodle & ZERO傑洛 for noticing sponge-based bosses moving out of stage in case of no-offset applied
|
||||
long movementDataLength = p.getPosition() - movementDataStart; //how many bytes were read by updatePosition
|
||||
p.seek(movementDataStart);
|
||||
|
||||
if (YamlConfig.config.server.USE_DEBUG_SHOW_RCVD_MVLIFE) {
|
||||
System.out.println((isSkill ? "SKILL " : (isAttack ? "ATTCK " : " ")) + "castPos: " + castPos + " rawAct: " + rawActivity + " opt: " + pOption + " skillID: " + useSkillId + " skillLV: " + useSkillLevel + " " + "allowSkill: " + nextMovementCouldBeSkill + " mobMp: " + mobMp);
|
||||
}
|
||||
|
||||
map.broadcastMessage(player, PacketCreator.moveMonster(objectid, nextMovementCouldBeSkill, rawActivity, useSkillId, useSkillLevel, pOption, startPos, p, movementDataLength), serverStartPos);
|
||||
//updatePosition(res, monster, -2); //does this need to be done after the packet is broadcast?
|
||||
map.moveMonster(monster, monster.getPosition());
|
||||
} catch (EmptyMovementException e) {}
|
||||
|
||||
if (banishPlayers != null) {
|
||||
for (Character chr : banishPlayers) {
|
||||
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (player.isChangingMaps()) { // thanks Lame for noticing mob movement shuffle (mob OID on different maps) happening on map transitions
|
||||
return;
|
||||
}
|
||||
|
||||
private static boolean inRangeInclusive(Byte pVal, Integer pMin, Integer pMax) {
|
||||
return !(pVal < pMin) || (pVal > pMax);
|
||||
}
|
||||
int objectid = p.readInt();
|
||||
short moveid = p.readShort();
|
||||
MapObject mmo = map.getMapObject(objectid);
|
||||
if (mmo == null || mmo.getType() != MapObjectType.MONSTER) {
|
||||
return;
|
||||
}
|
||||
|
||||
Monster monster = (Monster) mmo;
|
||||
List<Character> banishPlayers = null;
|
||||
|
||||
byte pNibbles = p.readByte();
|
||||
byte rawActivity = p.readByte();
|
||||
int skillId = p.readByte() & 0xff;
|
||||
int skillLv = p.readByte() & 0xff;
|
||||
short pOption = p.readShort();
|
||||
p.skip(8);
|
||||
|
||||
if (rawActivity >= 0) {
|
||||
rawActivity = (byte) (rawActivity & 0xFF >> 1);
|
||||
}
|
||||
|
||||
boolean isAttack = inRangeInclusive(rawActivity, 24, 41);
|
||||
boolean isSkill = inRangeInclusive(rawActivity, 42, 59);
|
||||
|
||||
MobSkill toUse = null;
|
||||
int useSkillId = 0, useSkillLevel = 0;
|
||||
|
||||
MobSkill nextUse = null;
|
||||
int nextSkillId = 0, nextSkillLevel = 0;
|
||||
|
||||
boolean nextMovementCouldBeSkill = !(isSkill || (pNibbles != 0));
|
||||
|
||||
int castPos;
|
||||
if (isSkill) {
|
||||
useSkillId = skillId;
|
||||
useSkillLevel = skillLv;
|
||||
|
||||
castPos = monster.getSkillPos(useSkillId, useSkillLevel);
|
||||
if (castPos != -1) {
|
||||
toUse = MobSkillFactory.getMobSkill(useSkillId, useSkillLevel);
|
||||
|
||||
if (monster.canUseSkill(toUse, true)) {
|
||||
int animationTime = MonsterInformationProvider.getInstance().getMobSkillAnimationTime(toUse);
|
||||
if (animationTime > 0 && toUse.getSkillId() != 129) {
|
||||
toUse.applyDelayedEffect(player, monster, true, animationTime);
|
||||
} else {
|
||||
banishPlayers = new LinkedList<>();
|
||||
toUse.applyEffect(player, monster, true, banishPlayers);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
castPos = (rawActivity - 24) / 2;
|
||||
|
||||
int atkStatus = monster.canUseAttack(castPos, isSkill);
|
||||
if (atkStatus < 1) {
|
||||
rawActivity = -1;
|
||||
pOption = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mobMp = monster.getMp();
|
||||
if (nextMovementCouldBeSkill) {
|
||||
int noSkills = monster.getNoSkills();
|
||||
if (noSkills > 0) {
|
||||
int rndSkill = Randomizer.nextInt(noSkills);
|
||||
|
||||
Pair<Integer, Integer> skillToUse = monster.getSkills().get(rndSkill);
|
||||
nextSkillId = skillToUse.getLeft();
|
||||
nextSkillLevel = skillToUse.getRight();
|
||||
nextUse = MobSkillFactory.getMobSkill(nextSkillId, nextSkillLevel);
|
||||
|
||||
if (!(nextUse != null && monster.canUseSkill(nextUse, false) && nextUse.getHP() >= (int) (((float) monster.getHp() / monster.getMaxHp()) * 100) && mobMp >= nextUse.getMpCon())) {
|
||||
// thanks OishiiKawaiiDesu for noticing mobs trying to cast skills they are not supposed to be able
|
||||
|
||||
nextSkillId = 0;
|
||||
nextSkillLevel = 0;
|
||||
nextUse = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.readByte();
|
||||
p.readInt(); // whatever
|
||||
short start_x = p.readShort(); // hmm.. startpos?
|
||||
short start_y = p.readShort(); // hmm...
|
||||
Point startPos = new Point(start_x, start_y - 2);
|
||||
Point serverStartPos = new Point(monster.getPosition());
|
||||
|
||||
Boolean aggro = monster.aggroMoveLifeUpdate(player);
|
||||
if (aggro == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextUse != null) {
|
||||
c.sendPacket(PacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro, nextSkillId, nextSkillLevel));
|
||||
} else {
|
||||
c.sendPacket(PacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro));
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
int movementDataStart = p.getPosition();
|
||||
updatePosition(p, monster, -2); // Thanks Doodle & ZERO傑洛 for noticing sponge-based bosses moving out of stage in case of no-offset applied
|
||||
long movementDataLength = p.getPosition() - movementDataStart; //how many bytes were read by updatePosition
|
||||
p.seek(movementDataStart);
|
||||
|
||||
if (YamlConfig.config.server.USE_DEBUG_SHOW_RCVD_MVLIFE) {
|
||||
System.out.println((isSkill ? "SKILL " : (isAttack ? "ATTCK " : " ")) + "castPos: " + castPos + " rawAct: " + rawActivity + " opt: " + pOption + " skillID: " + useSkillId + " skillLV: " + useSkillLevel + " " + "allowSkill: " + nextMovementCouldBeSkill + " mobMp: " + mobMp);
|
||||
}
|
||||
|
||||
map.broadcastMessage(player, PacketCreator.moveMonster(objectid, nextMovementCouldBeSkill, rawActivity, useSkillId, useSkillLevel, pOption, startPos, p, movementDataLength), serverStartPos);
|
||||
//updatePosition(res, monster, -2); //does this need to be done after the packet is broadcast?
|
||||
map.moveMonster(monster, monster.getPosition());
|
||||
} catch (EmptyMovementException e) {
|
||||
}
|
||||
|
||||
if (banishPlayers != null) {
|
||||
for (Character chr : banishPlayers) {
|
||||
chr.changeMapBanish(monster.getBanish().getMap(), monster.getBanish().getPortal(), monster.getBanish().getMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean inRangeInclusive(Byte pVal, Integer pMin, Integer pMax) {
|
||||
return !(pVal < pMin) || (pVal > pMax);
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public final class MovePetHandler extends AbstractMovementPacketHandler {
|
||||
p.readLong();
|
||||
// Point startPos = StreamUtil.readShortPoint(slea);
|
||||
List<LifeMovementFragment> res;
|
||||
|
||||
|
||||
try {
|
||||
res = parseMovement(p);
|
||||
} catch (EmptyMovementException e) {
|
||||
|
||||
@@ -35,13 +35,14 @@ public final class MovePlayerHandler extends AbstractMovementPacketHandler {
|
||||
updatePosition(p, c.getPlayer(), 0);
|
||||
long movementDataLength = p.getPosition() - movementDataStart; //how many bytes were read by updatePosition
|
||||
p.seek(movementDataStart);
|
||||
|
||||
|
||||
c.getPlayer().getMap().movePlayer(c.getPlayer(), c.getPlayer().getPosition());
|
||||
if (c.getPlayer().isHidden()) {
|
||||
c.getPlayer().getMap().broadcastGMMessage(c.getPlayer(), PacketCreator.movePlayer(c.getPlayer().getId(), p, movementDataLength), false);
|
||||
} else {
|
||||
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), PacketCreator.movePlayer(c.getPlayer().getId(), p, movementDataLength), false);
|
||||
}
|
||||
} catch (EmptyMovementException e) {}
|
||||
} catch (EmptyMovementException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +51,10 @@ public final class MoveSummonHandler extends AbstractMovementPacketHandler {
|
||||
updatePosition(p, summon, 0);
|
||||
long movementDataLength = p.getPosition() - movementDataStart; //how many bytes were read by updatePosition
|
||||
p.seek(movementDataStart);
|
||||
|
||||
|
||||
player.getMap().broadcastMessage(player, PacketCreator.moveSummon(player.getId(), oid, startPos, p, movementDataLength), summon.getPosition());
|
||||
} catch (EmptyMovementException e) {}
|
||||
} catch (EmptyMovementException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ public final class MultiChatHandler extends AbstractPacketHandler {
|
||||
@Override
|
||||
public final void handlePacket(InPacket p, Client c) {
|
||||
Character player = c.getPlayer();
|
||||
if(player.getAutobanManager().getLastSpam(7) + 200 > currentServerTime()) {
|
||||
return;
|
||||
if (player.getAutobanManager().getLastSpam(7) + 200 > currentServerTime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int type = p.readByte(); // 0 for buddys, 1 for partys
|
||||
int numRecipients = p.readByte();
|
||||
int[] recipients = new int[numRecipients];
|
||||
@@ -49,11 +49,11 @@ public final class MultiChatHandler extends AbstractPacketHandler {
|
||||
}
|
||||
String chattext = p.readString();
|
||||
if (chattext.length() > Byte.MAX_VALUE && !player.isGM()) {
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit chats.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to send text with length of " + chattext.length());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit chats.");
|
||||
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to send text with length of " + chattext.length());
|
||||
c.disconnect(true, false);
|
||||
return;
|
||||
}
|
||||
World world = c.getWorldServer();
|
||||
if (type == 0) {
|
||||
world.buddyChat(recipients, player.getId(), player.getName(), chattext);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user