Switch to Maven file structure

This commit is contained in:
P0nk
2021-03-30 21:07:35 +02:00
parent 4acc5675d6
commit 813643036b
817 changed files with 16 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
/**
*
* @author Ronan
*/
public interface AbstractCharacterListener {
public void onHpChanged(int oldHp);
public void onHpmpPoolUpdate();
public void onStatUpdate();
public void onAnnounceStatPoolUpdate();
}

View File

@@ -0,0 +1,761 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import config.YamlConfig;
import constants.game.GameConstants;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.MonitoredReadLock;
import net.server.audit.locks.MonitoredReentrantReadWriteLock;
import net.server.audit.locks.MonitoredWriteLock;
import net.server.audit.locks.factory.MonitoredReadLockFactory;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
import net.server.audit.locks.factory.MonitoredWriteLockFactory;
import server.maps.AbstractAnimatedMapleMapObject;
import server.maps.MapleMap;
/**
*
* @author RonanLana
*/
public abstract class AbstractMapleCharacterObject extends AbstractAnimatedMapleMapObject {
protected MapleMap map;
protected int str, dex, luk, int_, hp, maxhp, mp, maxmp;
protected int hpMpApUsed, remainingAp;
protected int[] remainingSp = new int[10];
protected transient int clientmaxhp, clientmaxmp, localmaxhp = 50, localmaxmp = 5;
protected float transienthp = Float.NEGATIVE_INFINITY, transientmp = Float.NEGATIVE_INFINITY;
private AbstractCharacterListener listener = null;
protected Map<MapleStat, Integer> statUpdates = new HashMap<>();
protected Lock effLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CHARACTER_EFF, true);
protected MonitoredReadLock statRlock;
protected MonitoredWriteLock statWlock;
protected AbstractMapleCharacterObject() {
MonitoredReentrantReadWriteLock locks = new MonitoredReentrantReadWriteLock(MonitoredLockType.CHARACTER_STA, true);
statRlock = MonitoredReadLockFactory.createLock(locks);
statWlock = MonitoredWriteLockFactory.createLock(locks);
for (int i = 0; i < remainingSp.length; i++) {
remainingSp[i] = 0;
}
}
protected void setListener(AbstractCharacterListener listener) {
this.listener = listener;
}
public void setMap(MapleMap map) {
this.map = map;
}
public MapleMap getMap() {
return map;
}
public int getStr() {
statRlock.lock();
try {
return str;
} finally {
statRlock.unlock();
}
}
public int getDex() {
statRlock.lock();
try {
return dex;
} finally {
statRlock.unlock();
}
}
public int getInt() {
statRlock.lock();
try {
return int_;
} finally {
statRlock.unlock();
}
}
public int getLuk() {
statRlock.lock();
try {
return luk;
} finally {
statRlock.unlock();
}
}
public int getRemainingAp() {
statRlock.lock();
try {
return remainingAp;
} finally {
statRlock.unlock();
}
}
protected int getRemainingSp(int jobid) {
statRlock.lock();
try {
return remainingSp[GameConstants.getSkillBook(jobid)];
} finally {
statRlock.unlock();
}
}
public int[] getRemainingSps() {
statRlock.lock();
try {
return Arrays.copyOf(remainingSp, remainingSp.length);
} finally {
statRlock.unlock();
}
}
public int getHpMpApUsed() {
statRlock.lock();
try {
return hpMpApUsed;
} finally {
statRlock.unlock();
}
}
public boolean isAlive() {
statRlock.lock();
try {
return hp > 0;
} finally {
statRlock.unlock();
}
}
public int getHp() {
statRlock.lock();
try {
return hp;
} finally {
statRlock.unlock();
}
}
public int getMp() {
statRlock.lock();
try {
return mp;
} finally {
statRlock.unlock();
}
}
public int getMaxHp() {
statRlock.lock();
try {
return maxhp;
} finally {
statRlock.unlock();
}
}
public int getMaxMp() {
statRlock.lock();
try {
return maxmp;
} finally {
statRlock.unlock();
}
}
public int getClientMaxHp() {
return clientmaxhp;
}
public int getClientMaxMp() {
return clientmaxmp;
}
public int getCurrentMaxHp() {
return localmaxhp;
}
public int getCurrentMaxMp() {
return localmaxmp;
}
private void setHpMpApUsed(int mpApUsed) {
this.hpMpApUsed = mpApUsed;
}
private void dispatchHpChanged(final int oldHp) {
listener.onHpChanged(oldHp);
}
private void dispatchHpmpPoolUpdated() {
listener.onHpmpPoolUpdate();
}
private void dispatchStatUpdated() {
listener.onStatUpdate();
}
private void dispatchStatPoolUpdateAnnounced() {
listener.onAnnounceStatPoolUpdate();
}
protected void setHp(int newHp) {
int oldHp = hp;
int thp = newHp;
if (thp < 0) {
thp = 0;
} else if (thp > localmaxhp) {
thp = localmaxhp;
}
if (this.hp != thp) this.transienthp = Float.NEGATIVE_INFINITY;
this.hp = thp;
dispatchHpChanged(oldHp);
}
protected void setMp(int newMp) {
int tmp = newMp;
if (tmp < 0) {
tmp = 0;
} else if (tmp > localmaxmp) {
tmp = localmaxmp;
}
if (this.mp != tmp) this.transientmp = Float.NEGATIVE_INFINITY;
this.mp = tmp;
}
private void setRemainingAp(int remainingAp) {
this.remainingAp = remainingAp;
}
private void setRemainingSp(int remainingSp, int skillbook) {
this.remainingSp[skillbook] = remainingSp;
}
protected void setMaxHp(int hp_) {
if (this.maxhp < hp_) this.transienthp = Float.NEGATIVE_INFINITY;
this.maxhp = hp_;
this.clientmaxhp = Math.min(30000, hp_);
}
protected void setMaxMp(int mp_) {
if (this.maxmp < mp_) this.transientmp = Float.NEGATIVE_INFINITY;
this.maxmp = mp_;
this.clientmaxmp = Math.min(30000, mp_);
}
private static long clampStat(int v, int min, int max) {
return (v < min) ? min : ((v > max) ? max : v);
}
private static long calcStatPoolNode(Integer v, int displacement) {
long r;
if (v == null) {
r = -32768;
} else {
r = clampStat(v, -32767, 32767);
}
return ((r & 0x0FFFF) << displacement);
}
private static long calcStatPoolLong(Integer v1, Integer v2, Integer v3, Integer v4) {
long ret = 0;
ret |= calcStatPoolNode(v1, 48);
ret |= calcStatPoolNode(v2, 32);
ret |= calcStatPoolNode(v3, 16);
ret |= calcStatPoolNode(v4, 0);
return ret;
}
private void changeStatPool(Long hpMpPool, Long strDexIntLuk, Long newSp, int newAp, boolean silent) {
effLock.lock();
statWlock.lock();
try {
statUpdates.clear();
boolean poolUpdate = false;
boolean statUpdate = false;
if (hpMpPool != null) {
short newHp = (short) (hpMpPool >> 48);
short newMp = (short) (hpMpPool >> 32);
short newMaxHp = (short) (hpMpPool >> 16);
short newMaxMp = (short) (hpMpPool.shortValue());
if (newMaxHp != Short.MIN_VALUE) {
if (newMaxHp < 50) {
newMaxHp = 50;
}
poolUpdate = true;
setMaxHp(newMaxHp);
statUpdates.put(MapleStat.MAXHP, clientmaxhp);
statUpdates.put(MapleStat.HP, hp);
}
if (newHp != Short.MIN_VALUE) {
setHp(newHp);
statUpdates.put(MapleStat.HP, hp);
}
if (newMaxMp != Short.MIN_VALUE) {
if (newMaxMp < 5) {
newMaxMp = 5;
}
poolUpdate = true;
setMaxMp(newMaxMp);
statUpdates.put(MapleStat.MAXMP, clientmaxmp);
statUpdates.put(MapleStat.MP, mp);
}
if (newMp != Short.MIN_VALUE) {
setMp(newMp);
statUpdates.put(MapleStat.MP, mp);
}
}
if (strDexIntLuk != null) {
short newStr = (short) (strDexIntLuk >> 48);
short newDex = (short) (strDexIntLuk >> 32);
short newInt = (short) (strDexIntLuk >> 16);
short newLuk = (short) (strDexIntLuk.shortValue());
if (newStr >= 4) {
setStr(newStr);
statUpdates.put(MapleStat.STR, str);
}
if (newDex >= 4) {
setDex(newDex);
statUpdates.put(MapleStat.DEX, dex);
}
if (newInt >= 4) {
setInt(newInt);
statUpdates.put(MapleStat.INT, int_);
}
if (newLuk >= 4) {
setLuk(newLuk);
statUpdates.put(MapleStat.LUK, luk);
}
if (newAp >= 0) {
setRemainingAp(newAp);
statUpdates.put(MapleStat.AVAILABLEAP, remainingAp);
}
statUpdate = true;
}
if (newSp != null) {
short sp = (short) (newSp >> 16);
short skillbook = (short) (newSp.shortValue());
setRemainingSp(sp, skillbook);
statUpdates.put(MapleStat.AVAILABLESP, remainingSp[skillbook]);
}
if (!statUpdates.isEmpty()) {
if (poolUpdate) {
dispatchHpmpPoolUpdated();
}
if (statUpdate) {
dispatchStatUpdated();
}
if (!silent) {
dispatchStatPoolUpdateAnnounced();
}
}
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void healHpMp() {
updateHpMp(30000);
}
public void updateHpMp(int x) {
updateHpMp(x, x);
}
public void updateHpMp(int newhp, int newmp) {
changeHpMp(newhp, newmp, false);
}
protected void changeHpMp(int newhp, int newmp, boolean silent) {
changeHpMpPool(newhp, newmp, null, null, silent);
}
private void changeHpMpPool(Integer hp, Integer mp, Integer maxhp, Integer maxmp, boolean silent) {
long hpMpPool = calcStatPoolLong(hp, mp, maxhp, maxmp);
changeStatPool(hpMpPool, null, null, -1, silent);
}
public void updateHp(int hp) {
updateHpMaxHp(hp, null);
}
public void updateMaxHp(int maxhp) {
updateHpMaxHp(null, maxhp);
}
public void updateHpMaxHp(int hp, int maxhp) {
updateHpMaxHp(Integer.valueOf(hp), Integer.valueOf(maxhp));
}
private void updateHpMaxHp(Integer hp, Integer maxhp) {
changeHpMpPool(hp, null, maxhp, null, false);
}
public void updateMp(int mp) {
updateMpMaxMp(mp, null);
}
public void updateMaxMp(int maxmp) {
updateMpMaxMp(null, maxmp);
}
public void updateMpMaxMp(int mp, int maxmp) {
updateMpMaxMp(Integer.valueOf(mp), Integer.valueOf(maxmp));
}
private void updateMpMaxMp(Integer mp, Integer maxmp) {
changeHpMpPool(null, mp, null, maxmp, false);
}
public void updateMaxHpMaxMp(int maxhp, int maxmp) {
changeHpMpPool(null, null, maxhp, maxmp, false);
}
protected void enforceMaxHpMp() {
effLock.lock();
statWlock.lock();
try {
if (mp > localmaxmp || hp > localmaxhp) {
changeHpMp(hp, mp, false);
}
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public int safeAddHP(int delta) {
effLock.lock();
statWlock.lock();
try {
if (hp + delta <= 0) {
delta = -hp + 1;
}
addHP(delta);
return delta;
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void addHP(int delta) {
effLock.lock();
statWlock.lock();
try {
updateHp(hp + delta);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void addMP(int delta) {
effLock.lock();
statWlock.lock();
try {
updateMp(mp + delta);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void addMPHP(int hpDelta, int mpDelta) {
effLock.lock();
statWlock.lock();
try {
updateHpMp(hp + hpDelta, mp + mpDelta);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
protected void addMaxMPMaxHP(int hpdelta, int mpdelta, boolean silent) {
effLock.lock();
statWlock.lock();
try {
changeHpMpPool(null, null, maxhp + hpdelta, maxmp + mpdelta, silent);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void addMaxHP(int delta) {
effLock.lock();
statWlock.lock();
try {
updateMaxHp(maxhp + delta);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void addMaxMP(int delta) {
effLock.lock();
statWlock.lock();
try {
updateMaxMp(maxmp + delta);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
private void setStr(int str) {
this.str = str;
}
private void setDex(int dex) {
this.dex = dex;
}
private void setInt(int int_) {
this.int_ = int_;
}
private void setLuk(int luk) {
this.luk = luk;
}
public boolean assignStr(int x) {
return assignStrDexIntLuk(x, null, null, null);
}
public boolean assignDex(int x) {
return assignStrDexIntLuk(null, x, null, null);
}
public boolean assignInt(int x) {
return assignStrDexIntLuk(null, null, x, null);
}
public boolean assignLuk(int x) {
return assignStrDexIntLuk(null, null, null, x);
}
public boolean assignHP(int deltaHP, int deltaAp) {
effLock.lock();
statWlock.lock();
try {
if (remainingAp - deltaAp < 0 || hpMpApUsed + deltaAp < 0 || maxhp >= 30000) {
return false;
}
long hpMpPool = calcStatPoolLong(null, null, maxhp + deltaHP, maxmp);
long strDexIntLuk = calcStatPoolLong(str, dex, int_, luk);
changeStatPool(hpMpPool, strDexIntLuk, null, remainingAp - deltaAp, false);
setHpMpApUsed(hpMpApUsed + deltaAp);
return true;
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public boolean assignMP(int deltaMP, int deltaAp) {
effLock.lock();
statWlock.lock();
try {
if (remainingAp - deltaAp < 0 || hpMpApUsed + deltaAp < 0 || maxmp >= 30000) {
return false;
}
long hpMpPool = calcStatPoolLong(null, null, maxhp, maxmp + deltaMP);
long strDexIntLuk = calcStatPoolLong(str, dex, int_, luk);
changeStatPool(hpMpPool, strDexIntLuk, null, remainingAp - deltaAp, false);
setHpMpApUsed(hpMpApUsed + deltaAp);
return true;
} finally {
statWlock.unlock();
effLock.unlock();
}
}
private static int apAssigned(Integer x) {
return x != null ? x : 0;
}
public boolean assignStrDexIntLuk(int deltaStr, int deltaDex, int deltaInt, int deltaLuk) {
return assignStrDexIntLuk(Integer.valueOf(deltaStr), Integer.valueOf(deltaDex), Integer.valueOf(deltaInt), Integer.valueOf(deltaLuk));
}
private boolean assignStrDexIntLuk(Integer deltaStr, Integer deltaDex, Integer deltaInt, Integer deltaLuk) {
effLock.lock();
statWlock.lock();
try {
int apUsed = apAssigned(deltaStr) + apAssigned(deltaDex) + apAssigned(deltaInt) + apAssigned(deltaLuk);
if (apUsed > remainingAp) {
return false;
}
int newStr = str, newDex = dex, newInt = int_, newLuk = luk;
if (deltaStr != null) newStr += deltaStr; // thanks Rohenn for noticing an NPE case after "null" started being used
if (deltaDex != null) newDex += deltaDex;
if (deltaInt != null) newInt += deltaInt;
if (deltaLuk != null) newLuk += deltaLuk;
if (newStr < 4 || newStr > YamlConfig.config.server.MAX_AP) {
return false;
}
if (newDex < 4 || newDex > YamlConfig.config.server.MAX_AP) {
return false;
}
if (newInt < 4 || newInt > YamlConfig.config.server.MAX_AP) {
return false;
}
if (newLuk < 4 || newLuk > YamlConfig.config.server.MAX_AP) {
return false;
}
int newAp = remainingAp - apUsed;
updateStrDexIntLuk(newStr, newDex, newInt, newLuk, newAp);
return true;
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void updateStrDexIntLuk(int x) {
updateStrDexIntLuk(x, x, x, x, -1);
}
public void changeRemainingAp(int x, boolean silent) {
effLock.lock();
statWlock.lock();
try {
changeStrDexIntLuk(str, dex, int_, luk, x, silent);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
public void gainAp(int deltaAp, boolean silent) {
effLock.lock();
statWlock.lock();
try {
changeRemainingAp(Math.max(0, remainingAp + deltaAp), silent);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
protected void updateStrDexIntLuk(int str, int dex, int int_, int luk, int remainingAp) {
changeStrDexIntLuk(str, dex, int_, luk, remainingAp, false);
}
private void changeStrDexIntLuk(Integer str, Integer dex, Integer int_, Integer luk, int remainingAp, boolean silent) {
long strDexIntLuk = calcStatPoolLong(str, dex, int_, luk);
changeStatPool(null, strDexIntLuk, null, remainingAp, silent);
}
private void changeStrDexIntLukSp(Integer str, Integer dex, Integer int_, Integer luk, int remainingAp, int remainingSp, int skillbook, boolean silent) {
long strDexIntLuk = calcStatPoolLong(str, dex, int_, luk);
long sp = calcStatPoolLong(0, 0, remainingSp, skillbook);
changeStatPool(null, strDexIntLuk, sp, remainingAp, silent);
}
protected void updateStrDexIntLukSp(int str, int dex, int int_, int luk, int remainingAp, int remainingSp, int skillbook) {
changeStrDexIntLukSp(str, dex, int_, luk, remainingAp, remainingSp, skillbook, false);
}
protected void setRemainingSp(int[] sps) {
effLock.lock();
statWlock.lock();
try {
System.arraycopy(sps, 0, remainingSp, 0, sps.length);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
protected void updateRemainingSp(int remainingSp, int skillbook) {
changeRemainingSp(remainingSp, skillbook, false);
}
protected void changeRemainingSp(int remainingSp, int skillbook, boolean silent) {
long sp = calcStatPoolLong(0, 0, remainingSp, skillbook);
changeStatPool(null, null, sp, Short.MIN_VALUE, silent);
}
public void gainSp(int deltaSp, int skillbook, boolean silent) {
effLock.lock();
statWlock.lock();
try {
changeRemainingSp(Math.max(0, remainingSp[skillbook] + deltaSp), skillbook, silent);
} finally {
statWlock.unlock();
effLock.unlock();
}
}
}

View File

@@ -0,0 +1,181 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import net.server.PlayerStorage;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
public class BuddyList {
public enum BuddyOperation {
ADDED, DELETED
}
public enum BuddyAddResult {
BUDDYLIST_FULL, ALREADY_ON_LIST, OK
}
private Map<Integer, BuddylistEntry> buddies = new LinkedHashMap<>();
private int capacity;
private Deque<CharacterNameAndId> pendingRequests = new LinkedList<>();
public BuddyList(int capacity) {
this.capacity = capacity;
}
public boolean contains(int characterId) {
synchronized(buddies) {
return buddies.containsKey(Integer.valueOf(characterId));
}
}
public boolean containsVisible(int characterId) {
BuddylistEntry ble;
synchronized(buddies) {
ble = buddies.get(characterId);
}
if (ble == null) {
return false;
}
return ble.isVisible();
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
public BuddylistEntry get(int characterId) {
synchronized(buddies) {
return buddies.get(Integer.valueOf(characterId));
}
}
public BuddylistEntry get(String characterName) {
String lowerCaseName = characterName.toLowerCase();
for (BuddylistEntry ble : getBuddies()) {
if (ble.getName().toLowerCase().equals(lowerCaseName)) {
return ble;
}
}
return null;
}
public void put(BuddylistEntry entry) {
synchronized(buddies) {
buddies.put(Integer.valueOf(entry.getCharacterId()), entry);
}
}
public void remove(int characterId) {
synchronized(buddies) {
buddies.remove(Integer.valueOf(characterId));
}
}
public Collection<BuddylistEntry> getBuddies() {
synchronized(buddies) {
return Collections.unmodifiableCollection(buddies.values());
}
}
public boolean isFull() {
synchronized(buddies) {
return buddies.size() >= capacity;
}
}
public int[] getBuddyIds() {
synchronized(buddies) {
int buddyIds[] = new int[buddies.size()];
int i = 0;
for (BuddylistEntry ble : buddies.values()) {
buddyIds[i++] = ble.getCharacterId();
}
return buddyIds;
}
}
public void broadcast(byte[] packet, PlayerStorage pstorage) {
for(int bid : getBuddyIds()) {
MapleCharacter chr = pstorage.getCharacterById(bid);
if(chr != null && chr.isLoggedinWorld()) {
chr.announce(packet);
}
}
}
public void loadFromDb(int characterId) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT b.buddyid, b.pending, b.group, c.name as buddyname FROM buddies as b, characters as c WHERE c.id = b.buddyid AND b.characterid = ?");
ps.setInt(1, characterId);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
if (rs.getInt("pending") == 1) {
pendingRequests.push(new CharacterNameAndId(rs.getInt("buddyid"), rs.getString("buddyname")));
} else {
put(new BuddylistEntry(rs.getString("buddyname"), rs.getString("group"), rs.getInt("buddyid"), (byte) -1, true));
}
}
rs.close();
ps.close();
ps = con.prepareStatement("DELETE FROM buddies WHERE pending = 1 AND characterid = ?");
ps.setInt(1, characterId);
ps.executeUpdate();
ps.close();
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public CharacterNameAndId pollPendingRequest() {
return pendingRequests.pollLast();
}
public void addBuddyRequest(MapleClient c, int cidFrom, String nameFrom, int channelFrom) {
put(new BuddylistEntry(nameFrom, "Default Group", cidFrom, channelFrom, false));
if (pendingRequests.isEmpty()) {
c.announce(MaplePacketCreator.requestBuddylistAdd(cidFrom, c.getPlayer().getId(), nameFrom));
} else {
pendingRequests.push(new CharacterNameAndId(cidFrom, nameFrom));
}
}
}

View File

@@ -0,0 +1,110 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
public class BuddylistEntry {
private String name;
private String group;
private int cid;
private int channel;
private boolean visible;
/**
*
* @param name
* @param characterId
* @param channel should be -1 if the buddy is offline
* @param visible
*/
public BuddylistEntry(String name, String group, int characterId, int channel, boolean visible) {
this.name = name;
this.group = group;
this.cid = characterId;
this.channel = channel;
this.visible = visible;
}
/**
* @return the channel the character is on. If the character is offline returns -1.
*/
public int getChannel() {
return channel;
}
public void setChannel(int channel) {
this.channel = channel;
}
public boolean isOnline() {
return channel >= 0;
}
public String getName() {
return name;
}
public String getGroup() {
return group;
}
public int getCharacterId() {
return cid;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
public void changeGroup(String group) {
this.group = group;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + cid;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final BuddylistEntry other = (BuddylistEntry) obj;
if (cid != other.cid) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,41 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
public class CharacterNameAndId {
private int id;
private String name;
public CharacterNameAndId(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,148 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
public enum MapleBuffStat {
//SLOW(0x1L),
MORPH(0x2L),
RECOVERY(0x4L),
MAPLE_WARRIOR(0x8L),
STANCE(0x10L),
SHARP_EYES(0x20L),
MANA_REFLECTION(0x40L),
//ALWAYS_RIGHT(0X80L),
SHADOW_CLAW(0x100L),
INFINITY(0x200L),
HOLY_SHIELD(0x400L),
HAMSTRING(0x800L),
BLIND(0x1000L),
CONCENTRATE(0x2000L),
PUPPET(0x4000L),
ECHO_OF_HERO(0x8000L),
MESO_UP_BY_ITEM(0x10000L),
GHOST_MORPH(0x20000L),
AURA(0x40000L),
CONFUSE(0x80000L),
// ------ COUPON feature ------
COUPON_EXP1(0x100000L),
COUPON_EXP2(0x200000L),
COUPON_EXP3(0x400000L), COUPON_EXP4(0x400000L),
COUPON_DRP1(0x800000L),
COUPON_DRP2(0x1000000L), COUPON_DRP3(0x1000000L),
// ------ monster card buffs, thanks to Arnah (Vertisy) ------
ITEM_UP_BY_ITEM(0x100000L),
RESPECT_PIMMUNE(0x200000L),
RESPECT_MIMMUNE(0x400000L),
DEFENSE_ATT(0x800000L),
DEFENSE_STATE(0x1000000L),
HPREC(0x2000000L),
MPREC(0x4000000L),
BERSERK_FURY(0x8000000L),
DIVINE_BODY(0x10000000L),
SPARK(0x20000000L),
MAP_CHAIR(0x40000000L),
FINALATTACK(0x80000000L),
WATK(0x100000000L),
WDEF(0x200000000L),
MATK(0x400000000L),
MDEF(0x800000000L),
ACC(0x1000000000L),
AVOID(0x2000000000L),
HANDS(0x4000000000L),
SPEED(0x8000000000L),
JUMP(0x10000000000L),
MAGIC_GUARD(0x20000000000L),
DARKSIGHT(0x40000000000L),
BOOSTER(0x80000000000L),
POWERGUARD(0x100000000000L),
HYPERBODYHP(0x200000000000L),
HYPERBODYMP(0x400000000000L),
INVINCIBLE(0x800000000000L),
SOULARROW(0x1000000000000L),
STUN(0x2000000000000L),
POISON(0x4000000000000L),
SEAL(0x8000000000000L),
DARKNESS(0x10000000000000L),
COMBO(0x20000000000000L),
SUMMON(0x20000000000000L),
WK_CHARGE(0x40000000000000L),
DRAGONBLOOD(0x80000000000000L),
HOLY_SYMBOL(0x100000000000000L),
MESOUP(0x200000000000000L),
SHADOWPARTNER(0x400000000000000L),
PICKPOCKET(0x800000000000000L),
MESOGUARD(0x1000000000000000L),
EXP_INCREASE(0x2000000000000000L),
WEAKEN(0x4000000000000000L),
MAP_PROTECTION(0x8000000000000000L),
//all incorrect buffstats
SLOW(0x200000000L, true),
ELEMENTAL_RESET(0x200000000L, true),
MAGIC_SHIELD(0x400000000L, true),
MAGIC_RESISTANCE(0x800000000L, true),
// needs Soul Stone
//end incorrect buffstats
WIND_WALK(0x400000000L, true),
ARAN_COMBO(0x1000000000L, true),
COMBO_DRAIN(0x2000000000L, true),
COMBO_BARRIER(0x4000000000L, true),
BODY_PRESSURE(0x8000000000L, true),
SMART_KNOCKBACK(0x10000000000L, true),
BERSERK(0x20000000000L, true),
ENERGY_CHARGE(0x4000000000000L, true),
DASH2(0x8000000000000L, true), // correct (speed)
DASH(0x10000000000000L, true), // correct (jump)
MONSTER_RIDING(0x20000000000000L, true),
SPEED_INFUSION(0x40000000000000L, true),
HOMING_BEACON(0x80000000000000L, true);
private final long i;
private final boolean isFirst;
private MapleBuffStat(long i, boolean isFirst) {
this.i = i;
this.isFirst = isFirst;
}
private MapleBuffStat(long i) {
this.i = i;
this.isFirst = false;
}
public long getValue() {
return i;
}
public boolean isFirst() {
return isFirst;
}
@Override
public String toString() {
return name();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import constants.game.GameConstants;
public enum MapleDisease {
NULL(0x0),
SLOW(0x1, 126),
SEDUCE(0x80, 128),
FISHABLE(0x100),
ZOMBIFY(0x4000),
CONFUSE(0x80000, 132),
STUN(0x2000000000000L, 123),
POISON(0x4000000000000L, 125),
SEAL(0x8000000000000L, 120),
DARKNESS(0x10000000000000L, 121),
WEAKEN(0x4000000000000000L, 122),
CURSE(0x8000000000000000L, 124);
private long i;
private boolean first;
private int mobskill;
private MapleDisease(long i) {
this(i, false, 0);
}
private MapleDisease(long i, int skill) {
this(i, false, skill);
}
private MapleDisease(long i, boolean first, int skill) {
this.i = i;
this.first = first;
this.mobskill = skill;
}
public long getValue() {
return i;
}
public boolean isFirst() {
return first;
}
public int getDisease() {
return mobskill;
}
public static MapleDisease ordinal(int ord) {
try {
return MapleDisease.values()[ord];
} catch (IndexOutOfBoundsException io) {
return NULL;
}
}
public static final MapleDisease getRandom() {
MapleDisease[] diseases = GameConstants.CPQ_DISEASES;
return diseases[(int) (Math.random() * diseases.length)];
}
public static final MapleDisease getBySkill(final int skill) {
for (MapleDisease d : MapleDisease.values()) {
if (d.getDisease() == skill && d.getDisease() != 0) {
return d;
}
}
return null;
}
}

View File

@@ -0,0 +1,34 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 ~ 2010 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License version 3
as published by the Free Software Foundation. You may not use, modify
or distribute this program under any other version of the
GNU Affero General Public License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
/**
*
* @author anybody can do this
*/
public class MapleDiseaseValueHolder {
public long startTime, length;
public MapleDiseaseValueHolder(long start, long length) {
this.startTime = start;
this.length = length;
}
}

View File

@@ -0,0 +1,303 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import net.server.Server;
import net.server.world.World;
import tools.DatabaseConnection;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*
* @author Jay Estrella - Mr.Trash :3
* @author Ubaware
*/
public class MapleFamily {
private static final AtomicInteger familyIDCounter = new AtomicInteger();
private final int id, world;
private final Map<Integer, MapleFamilyEntry> members = new ConcurrentHashMap<Integer, MapleFamilyEntry>();
private MapleFamilyEntry leader;
private String name;
private String preceptsMessage = "";
private int totalGenerations;
public MapleFamily(int id, int world) {
int newId = id;
if(id == -1) {
// get next available family id
while(idInUse(newId = familyIDCounter.incrementAndGet())) {
}
}
this.id = newId;
this.world = world;
}
private static boolean idInUse(int id) {
for(World world : Server.getInstance().getWorlds()) {
if(world.getFamily(id) != null) return true;
}
return false;
}
public int getID() {
return id;
}
public int getWorld() {
return world;
}
public void setLeader(MapleFamilyEntry leader) {
this.leader = leader;
setName(leader.getName());
}
public MapleFamilyEntry getLeader() {
return leader;
}
private void setName(String name) {
this.name = name;
}
public int getTotalMembers() {
return members.size();
}
public int getTotalGenerations() {
return totalGenerations;
}
public void setTotalGenerations(int generations) {
this.totalGenerations = generations;
}
public String getName() {
return this.name;
}
public void setMessage(String message, boolean save) {
this.preceptsMessage = message;
if(save) {
try (Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE family_character SET precepts = ? WHERE cid = ?")) {
ps.setString(1, message);
ps.setInt(2, getLeader().getChrId());
ps.executeUpdate();
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not save new precepts for family " + getID() + ".");
e.printStackTrace();
}
}
}
public String getMessage() {
return preceptsMessage;
}
public void addEntry(MapleFamilyEntry entry) {
members.put(entry.getChrId(), entry);
}
public void removeEntryBranch(MapleFamilyEntry root) {
members.remove(root.getChrId());
for(MapleFamilyEntry junior : root.getJuniors()) {
if(junior != null) removeEntryBranch(junior);
}
}
public void addEntryTree(MapleFamilyEntry root) {
members.put(root.getChrId(), root);
for(MapleFamilyEntry junior : root.getJuniors()) {
if(junior != null) addEntryTree(junior);
}
}
public MapleFamilyEntry getEntryByID(int cid) {
return members.get(cid);
}
public void broadcast(byte[] packet) {
broadcast(packet, -1);
}
public void broadcast(byte[] packet, int ignoreID) {
for(MapleFamilyEntry entry : members.values()) {
MapleCharacter chr = entry.getChr();
if(chr != null) {
if(chr.getId() == ignoreID) continue;
chr.getClient().announce(packet);
}
}
}
public void broadcastFamilyInfoUpdate() {
for(MapleFamilyEntry entry : members.values()) {
MapleCharacter chr = entry.getChr();
if(chr != null) {
chr.getClient().announce(MaplePacketCreator.getFamilyInfo(entry));
}
}
}
public void resetDailyReps() {
for(MapleFamilyEntry entry : members.values()) {
entry.setTodaysRep(0);
entry.setRepsToSenior(0);
entry.resetEntitlementUsages();
}
}
public static void loadAllFamilies() {
try(Connection con = DatabaseConnection.getConnection()) {
List<Pair<Pair<Integer, Integer>, MapleFamilyEntry>> unmatchedJuniors = new ArrayList<Pair<Pair<Integer, Integer>, MapleFamilyEntry>>(200); // <<world, seniorid> familyEntry>
try(PreparedStatement psEntries = con.prepareStatement("SELECT * FROM family_character")) {
ResultSet rsEntries = psEntries.executeQuery();
while(rsEntries.next()) { // can be optimized
int cid = rsEntries.getInt("cid");
String name = null;
int level = -1;
int jobID = -1;
int world = -1;
try(PreparedStatement ps = con.prepareStatement("SELECT world, name, level, job FROM characters WHERE id = ?")) {
ps.setInt(1, cid);
ResultSet rs = ps.executeQuery();
if(rs.next()) {
world = rs.getInt("world");
name = rs.getString("name");
level = rs.getInt("level");
jobID = rs.getInt("job");
} else {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Could not load character information of " + cid + " in loadAllFamilies(). (RECORD DOES NOT EXIST)");
continue;
}
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not load character information of " + cid + " in loadAllFamilies(). (SQL ERROR)");
continue;
}
int familyid = rsEntries.getInt("familyid");
int seniorid = rsEntries.getInt("seniorid");
int reputation = rsEntries.getInt("reputation");
int todaysRep = rsEntries.getInt("todaysrep");
int totalRep = rsEntries.getInt("totalreputation");
int repsToSenior = rsEntries.getInt("reptosenior");
String precepts = rsEntries.getString("precepts");
//Timestamp lastResetTime = rsEntries.getTimestamp("lastresettime"); //taken care of by FamilyDailyResetTask
World wserv = Server.getInstance().getWorld(world);
if (wserv == null) {
continue;
}
MapleFamily family = wserv.getFamily(familyid);
if(family == null) {
family = new MapleFamily(familyid, world);
Server.getInstance().getWorld(world).addFamily(familyid, family);
}
MapleFamilyEntry familyEntry = new MapleFamilyEntry(family, cid, name, level, MapleJob.getById(jobID));
family.addEntry(familyEntry);
if(seniorid <= 0) {
family.setLeader(familyEntry);
family.setMessage(precepts, false);
}
MapleFamilyEntry senior = family.getEntryByID(seniorid);
if(senior != null) {
familyEntry.setSenior(family.getEntryByID(seniorid), false);
} else {
if(seniorid > 0) unmatchedJuniors.add(new Pair<Pair<Integer, Integer>, MapleFamilyEntry>(new Pair<Integer, Integer>(world, seniorid), familyEntry));
}
familyEntry.setReputation(reputation);
familyEntry.setTodaysRep(todaysRep);
familyEntry.setTotalReputation(totalRep);
familyEntry.setRepsToSenior(repsToSenior);
//load used entitlements
try (PreparedStatement ps = con.prepareStatement("SELECT entitlementid FROM family_entitlement WHERE charid = ?")) {
ps.setInt(1, familyEntry.getChrId());
ResultSet rs = ps.executeQuery();
while(rs.next()) {
familyEntry.setEntitlementUsed(rs.getInt("entitlementid"));
}
}
}
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get family_character entries.");
e.printStackTrace();
}
// link missing ones (out of order)
for(Pair<Pair<Integer, Integer>, MapleFamilyEntry> unmatchedJunior : unmatchedJuniors) {
int world = unmatchedJunior.getLeft().getLeft();
int seniorid = unmatchedJunior.getLeft().getRight();
MapleFamilyEntry junior = unmatchedJunior.getRight();
MapleFamilyEntry senior = Server.getInstance().getWorld(world).getFamily(junior.getFamily().getID()).getEntryByID(seniorid);
if(senior != null) {
junior.setSenior(senior, false);
} else {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Missing senior for character " + junior.getName() + " in world " + world);
}
}
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get DB connection.");
e.printStackTrace();
}
for(World world : Server.getInstance().getWorlds()) {
for(MapleFamily family : world.getFamilies()) {
family.getLeader().doFullCount();
}
}
}
public void saveAllMembersRep() { //was used for autosave task, but character autosave should be enough
try(Connection con = DatabaseConnection.getConnection()) {
con.setAutoCommit(false);
boolean success = true;
for(MapleFamilyEntry entry : members.values()) {
success = entry.saveReputation(con);
if(!success) break;
}
if(!success) {
con.rollback();
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Family rep autosave failed for family " + getID() + " on " + Calendar.getInstance().getTime().toString() + ".");
}
con.setAutoCommit(true);
//reset repChanged after successful save
for(MapleFamilyEntry entry : members.values()) {
entry.savedSuccessfully();
}
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get connection to DB.");
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,41 @@
package client;
public enum MapleFamilyEntitlement {
FAMILY_REUINION(1, 300, "Family Reunion", "[Target] Me\\n[Effect] Teleport directly to the Family member of your choice."),
SUMMON_FAMILY(1, 500, "Summon Family", "[Target] 1 Family member\\n[Effect] Summon a Family member of choice to the map you're in."),
SELF_DROP_1_5(1, 700, "My Drop Rate 1.5x (15 min)", "[Target] Me\\n[Time] 15 min.\\n[Effect] Monster drop rate will be increased #c1.5x#.\\n* If the Drop Rate event is in progress, this will be nullified."),
SELF_EXP_1_5(1, 800, "My EXP 1.5x (15 min)", "[Target] Me\\n[Time] 15 min.\\n[Effect] EXP earned from hunting will be increased #c1.5x#.\\n* If the EXP event is in progress, this will be nullified."),
FAMILY_BONDING(1, 1000, "Family Bonding (30 min)", "[Target] At least 6 Family members online that are below me in the Pedigree\\n[Time] 30 min.\\n[Effect] Monster drop rate and EXP earned will be increased #c2x#. \\n* If the EXP event is in progress, this will be nullified."),
SELF_DROP_2(1, 1200, "My Drop Rate 2x (15 min)", "[Target] Me\\n[Time] 15 min.\\n[Effect] Monster drop rate will be increased #c2x#.\\n* If the Drop Rate event is in progress, this will be nullified."),
SELF_EXP_2(1, 1500, "My EXP 2x (15 min)", "[Target] Me\\n[Time] 15 min.\\n[Effect] EXP earned from hunting will be increased #c2x#.\\n* If the EXP event is in progress, this will be nullified."),
SELF_DROP_2_30MIN(1, 2000, "My Drop Rate 2x (30 min)", "[Target] Me\\n[Time] 30 min.\\n[Effect] Monster drop rate will be increased #c2x#.\\n* If the Drop Rate event is in progress, this will be nullified."),
SELF_EXP_2_30MIN(1, 2500, "My EXP 2x (30 min)", "[Target] Me\\n[Time] 30 min.\\n[Effect] EXP earned from hunting will be increased #c2x#. \\n* If the EXP event is in progress, this will be nullified."),
PARTY_DROP_2_30MIN(1, 4000, "My Party Drop Rate 2x (30 min)", "[Target] My party\\n[Time] 30 min.\\n[Effect] Monster drop rate will be increased #c2x#.\\n* If the Drop Rate event is in progress, this will be nullified."),
PARTY_EXP_2_30MIN(1, 5000, "My Party EXP 2x (30 min)", "[Target] My party\\n[Time] 30 min.\\n[Effect] EXP earned from hunting will be increased #c2x#.\\n* If the EXP event is in progress, this will be nullified.");
private final int usageLimit, repCost;
private final String name, description;
private MapleFamilyEntitlement(int usageLimit, int repCost, String name, String description) {
this.usageLimit = usageLimit;
this.repCost = repCost;
this.name = name;
this.description = description;
}
public int getUsageLimit() {
return usageLimit;
}
public int getRepCost() {
return repCost;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
}

View File

@@ -0,0 +1,552 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.server.Server;
import tools.DatabaseConnection;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Pair;
/**
* @author Ubaware
*/
public class MapleFamilyEntry {
private final int characterID;
private volatile MapleFamily family;
private volatile MapleCharacter character;
private volatile MapleFamilyEntry senior;
private final MapleFamilyEntry[] juniors = new MapleFamilyEntry[2];
private final int[] entitlements = new int[11];
private volatile int reputation, totalReputation;
private volatile int todaysRep, repsToSenior; //both are daily values
private volatile int totalJuniors, totalSeniors;
private volatile int generation;
private volatile boolean repChanged; //used to ignore saving unchanged rep values
// cached values for offline players
private String charName;
private int level;
private MapleJob job;
public MapleFamilyEntry(MapleFamily family, int characterID, String charName, int level, MapleJob job) {
this.family = family;
this.characterID = characterID;
this.charName = charName;
this.level = level;
this.job = job;
}
public MapleCharacter getChr() {
return character;
}
public void setCharacter(MapleCharacter newCharacter) {
if(newCharacter == null) cacheOffline(newCharacter);
else newCharacter.setFamilyEntry(this);
this.character = newCharacter;
}
private void cacheOffline(MapleCharacter chr) {
if(chr != null) {
charName = chr.getName();
level = chr.getLevel();
job = chr.getJob();
}
}
public synchronized void join(MapleFamilyEntry senior) {
if(senior == null || getSenior() != null) return;
MapleFamily oldFamily = getFamily();
MapleFamily newFamily = senior.getFamily();
setSenior(senior, false);
addSeniorCount(newFamily.getTotalGenerations(), newFamily); //count will be overwritten by doFullCount()
newFamily.getLeader().doFullCount(); //easier than keeping track of numbers
oldFamily.setMessage(null, true);
newFamily.addEntryTree(this);
Server.getInstance().getWorld(oldFamily.getWorld()).removeFamily(oldFamily.getID());
//db
try(Connection con = DatabaseConnection.getConnection()) {
con.setAutoCommit(false);
boolean success = updateDBChangeFamily(con, getChrId(), newFamily.getID(), senior.getChrId());
for(MapleFamilyEntry junior : juniors) { // better to duplicate this than the SQL code
if(junior != null) {
success = junior.updateNewFamilyDB(con); // recursively updates juniors in db
if(!success) break;
}
}
if(!success) {
con.rollback();
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Could not absorb " + oldFamily.getName() + " family into " + newFamily.getName() + " family. (SQL ERROR)");
}
con.setAutoCommit(true);
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get connection to DB.");
e.printStackTrace();
}
}
public synchronized void fork() {
MapleFamily oldFamily = getFamily();
MapleFamilyEntry oldSenior = getSenior();
family = new MapleFamily(-1, oldFamily.getWorld());
Server.getInstance().getWorld(family.getWorld()).addFamily(family.getID(), family);
setSenior(null, false);
family.setLeader(this);
addSeniorCount(-getTotalSeniors(), family);
setTotalSeniors(0);
if(oldSenior != null) {
oldSenior.addJuniorCount(-getTotalJuniors());
oldSenior.removeJunior(this);
oldFamily.getLeader().doFullCount();
}
oldFamily.removeEntryBranch(this);
family.addEntryTree(this);
this.repsToSenior = 0;
this.repChanged = true;
family.setMessage("", true);
doFullCount(); //to make sure all counts are correct
// update db
try(Connection con = DatabaseConnection.getConnection()) {
con.setAutoCommit(false);
boolean success = updateDBChangeFamily(con, getChrId(), getFamily().getID(), 0);
for(MapleFamilyEntry junior : juniors) { // better to duplicate this than the SQL code
if(junior != null) {
success = junior.updateNewFamilyDB(con); // recursively updates juniors in db
if(!success) break;
}
}
if(!success) {
con.rollback();
FilePrinter.printError(FilePrinter.FAMILY_ERROR, "Could not fork family with new leader " + getName() + ". (Old senior : " + oldSenior.getName() + ", leader :" + oldFamily.getLeader().getName() + ")");
}
con.setAutoCommit(true);
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get connection to DB.");
e.printStackTrace();
}
}
private synchronized boolean updateNewFamilyDB(Connection con) {
if(!updateFamilyEntryDB(con, getChrId(), getFamily().getID())) return false;
if(!updateCharacterFamilyDB(con, getChrId(), getFamily().getID(), true)) return false;
for(MapleFamilyEntry junior : juniors) {
if(junior != null) {
if(!junior.updateNewFamilyDB(con)) return false;
}
}
return true;
}
private static boolean updateFamilyEntryDB(Connection con, int cid, int familyid) {
try(PreparedStatement ps = con.prepareStatement("UPDATE family_character SET familyid = ? WHERE cid = ?")) {
ps.setInt(1, familyid);
ps.setInt(2, cid);
ps.executeUpdate();
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not update family id in 'family_character' for character id " + cid + ". (fork)");
e.printStackTrace();
return false;
}
return true;
}
private synchronized void addSeniorCount(int seniorCount, MapleFamily newFamily) { // traverses tree and subtracts seniors and updates family
if(newFamily != null) this.family = newFamily;
setTotalSeniors(getTotalSeniors() + seniorCount);
this.generation += seniorCount;
for(MapleFamilyEntry junior : juniors) {
if(junior != null) junior.addSeniorCount(seniorCount, newFamily);
}
}
private synchronized void addJuniorCount(int juniorCount) { // climbs tree and adds junior count
setTotalJuniors(getTotalJuniors() + juniorCount);
MapleFamilyEntry senior = getSenior();
if(senior != null) senior.addJuniorCount(juniorCount);
}
public MapleFamily getFamily() {
return family;
}
public int getChrId() {
return characterID;
}
public String getName() {
MapleCharacter chr = character;
if(chr != null) return chr.getName();
else return charName;
}
public int getLevel() {
MapleCharacter chr = character;
if(chr != null) return chr.getLevel();
else return level;
}
public MapleJob getJob() {
MapleCharacter chr = character;
if(chr != null) return chr.getJob();
else return job;
}
public int getReputation() {
return reputation;
}
public int getTodaysRep() {
return todaysRep;
}
public void setReputation(int reputation) {
if(reputation != this.reputation) this.repChanged = true;
this.reputation = reputation;
}
public void setTodaysRep(int today) {
if(today != todaysRep) this.repChanged = true;
this.todaysRep = today;
}
public int getRepsToSenior() {
return repsToSenior;
}
public void setRepsToSenior(int reputation) {
if(reputation != this.repsToSenior) this.repChanged = true;
this.repsToSenior = reputation;
}
public void gainReputation(int gain, boolean countTowardsTotal) {
gainReputation(gain, countTowardsTotal, this);
}
private void gainReputation(int gain, boolean countTowardsTotal, MapleFamilyEntry from) {
if(gain != 0) repChanged = true;
this.reputation += gain;
this.todaysRep += gain;
if(gain > 0 && countTowardsTotal) {
this.totalReputation += gain;
}
MapleCharacter chr = getChr();
if(chr != null) chr.announce(MaplePacketCreator.sendGainRep(gain, from != null ? from.getName() : ""));
}
public void giveReputationToSenior(int gain, boolean includeSuperSenior) {
int actualGain = gain;
MapleFamilyEntry senior = getSenior();
if(senior != null && senior.getLevel() < getLevel() && gain > 0) actualGain /= 2; //don't halve negative values
if(senior != null) {
senior.gainReputation(actualGain, true, this);
if(actualGain > 0) {
this.repsToSenior += actualGain;
this.repChanged = true;
}
if(includeSuperSenior) {
senior = senior.getSenior();
if(senior != null) {
senior.gainReputation(actualGain, true, this);
}
}
}
}
public int getTotalReputation() {
return totalReputation;
}
public void setTotalReputation(int totalReputation) {
if(totalReputation != this.totalReputation) this.repChanged = true;
this.totalReputation = totalReputation;
}
public MapleFamilyEntry getSenior() {
return senior;
}
public synchronized boolean setSenior(MapleFamilyEntry senior, boolean save) {
if(this.senior == senior) return false;
MapleFamilyEntry oldSenior = this.senior;
this.senior = senior;
if(senior != null) {
if(senior.addJunior(this)) {
if(save) {
updateDBChangeFamily(getChrId(), senior.getFamily().getID(), senior.getChrId());
}
if(this.repsToSenior != 0) this.repChanged = true;
this.repsToSenior = 0;
this.addSeniorCount(1, null);
this.setTotalSeniors(senior.getTotalSeniors() + 1);
return true;
}
} else {
if(oldSenior != null) {
oldSenior.removeJunior(this);
}
}
return false;
}
private static boolean updateDBChangeFamily(int cid, int familyid, int seniorid) {
try(Connection con = DatabaseConnection.getConnection()) {
return updateDBChangeFamily(con, cid, familyid, seniorid);
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get connection to DB.");
e.printStackTrace();
return false;
}
}
private static boolean updateDBChangeFamily(Connection con, int cid, int familyid, int seniorid) {
try(PreparedStatement ps = con.prepareStatement("UPDATE family_character SET familyid = ?, seniorid = ?, reptosenior = 0 WHERE cid = ?")) {
ps.setInt(1, familyid);
ps.setInt(2, seniorid);
ps.setInt(3, cid);
ps.executeUpdate();
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not update seniorid in 'family_character' for character id " + cid + ".");
e.printStackTrace();
return false;
}
return updateCharacterFamilyDB(con, cid, familyid, false);
}
private static boolean updateCharacterFamilyDB(Connection con, int charid, int familyid, boolean fork) {
try(PreparedStatement ps = con.prepareStatement("UPDATE characters SET familyid = ? WHERE id = ?")) {
ps.setInt(1, familyid);
ps.setInt(2, charid);
ps.executeUpdate();
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not update familyid in 'characters' for character id " + charid + " when changing family. " + (fork ? "(fork)" : ""));
e.printStackTrace();
return false;
}
return true;
}
public List<MapleFamilyEntry> getJuniors() {
return Collections.unmodifiableList(Arrays.asList(juniors));
}
public MapleFamilyEntry getOtherJunior(MapleFamilyEntry junior) {
if(juniors[0] == junior) return juniors[1];
else if(juniors[1] == junior) return juniors[0];
return null;
}
public int getJuniorCount() { //close enough to be relatively consistent to multiple threads (and the result is not vital)
int juniorCount = 0;
if(juniors[0] != null) juniorCount++;
if(juniors[1] != null) juniorCount++;
return juniorCount;
}
public synchronized boolean addJunior(MapleFamilyEntry newJunior) {
for(int i = 0; i < juniors.length; i++) {
if(juniors[i] == null) { // successfully add new junior to family
juniors[i] = newJunior;
addJuniorCount(1);
getFamily().addEntry(newJunior);
return true;
}
}
return false;
}
public synchronized boolean isJunior(MapleFamilyEntry entry) { //require locking since result accuracy is vital
if(juniors[0] == entry) return true;
else if(juniors[1] == entry) return true;
return false;
}
public synchronized boolean removeJunior(MapleFamilyEntry junior) {
for(int i = 0; i < juniors.length; i++) {
if(juniors[i] == junior) {
juniors[i] = null;
return true;
}
}
return false;
}
public int getTotalSeniors() {
return totalSeniors;
}
public void setTotalSeniors(int totalSeniors) {
this.totalSeniors = totalSeniors;
}
public int getTotalJuniors() {
return totalJuniors;
}
public void setTotalJuniors(int totalJuniors) {
this.totalJuniors = totalJuniors;
}
public void announceToSenior(byte[] packet, boolean includeSuperSenior) {
MapleFamilyEntry senior = getSenior();
if(senior != null) {
MapleCharacter seniorChr = senior.getChr();
if(seniorChr != null) seniorChr.announce(packet);
senior = senior.getSenior();
if(includeSuperSenior && senior != null) {
seniorChr = senior.getChr();
if(seniorChr != null) seniorChr.announce(packet);
}
}
}
public void updateSeniorFamilyInfo(boolean includeSuperSenior) {
MapleFamilyEntry senior = getSenior();
if(senior != null) {
MapleCharacter seniorChr = senior.getChr();
if(seniorChr != null) seniorChr.announce(MaplePacketCreator.getFamilyInfo(senior));
senior = senior.getSenior();
if(includeSuperSenior && senior != null) {
seniorChr = senior.getChr();
if(seniorChr != null) seniorChr.announce(MaplePacketCreator.getFamilyInfo(senior));
}
}
}
/**
* Traverses entire family tree to update senior/junior counts. Call on leader.
*/
public synchronized void doFullCount() {
Pair<Integer, Integer> counts = this.traverseAndUpdateCounts(0);
getFamily().setTotalGenerations(counts.getLeft() + 1);
}
private Pair<Integer, Integer> traverseAndUpdateCounts(int seniors) { // recursion probably limits family size, but it should handle a depth of a few thousand
setTotalSeniors(seniors);
this.generation = seniors;
int juniorCount = 0;
int highestGeneration = this.generation;
for(MapleFamilyEntry entry : juniors) {
if(entry != null) {
Pair<Integer, Integer> counts = entry.traverseAndUpdateCounts(seniors + 1);
juniorCount += counts.getRight(); //total juniors
if(counts.getLeft() > highestGeneration) highestGeneration = counts.getLeft();
}
}
setTotalJuniors(juniorCount);
return new Pair<>(highestGeneration, juniorCount); //creating new objects to return is a bit inefficient, but cleaner than packing into a long
}
public boolean useEntitlement(MapleFamilyEntitlement entitlement) {
int id = entitlement.ordinal();
if(entitlements[id] >= 1) return false;
try(Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("INSERT INTO family_entitlement (entitlementid, charid, timestamp) VALUES (?, ?, ?)")) {
ps.setInt(1, id);
ps.setInt(2, getChrId());
ps.setLong(3, System.currentTimeMillis());
ps.executeUpdate();
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not insert new row in 'family_entitlement' for character " + getName() + ".");
e.printStackTrace();
}
entitlements[id]++;
return true;
}
public boolean refundEntitlement(MapleFamilyEntitlement entitlement) {
int id = entitlement.ordinal();
try(Connection con = DatabaseConnection.getConnection(); PreparedStatement ps = con.prepareStatement("DELETE FROM family_entitlement WHERE entitlementid = ? AND charid = ?")) {
ps.setInt(1, id);
ps.setInt(2, getChrId());
ps.executeUpdate();
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not refund family entitlement \"" + entitlement.getName() + "\" for character " + getName() + ".");
e.printStackTrace();
}
entitlements[id] = 0;
return true;
}
public boolean isEntitlementUsed(MapleFamilyEntitlement entitlement) {
return entitlements[entitlement.ordinal()] >= 1;
}
public int getEntitlementUsageCount(MapleFamilyEntitlement entitlement) {
return entitlements[entitlement.ordinal()];
}
public void setEntitlementUsed(int id) {
entitlements[id]++;
}
public void resetEntitlementUsages() {
for(MapleFamilyEntitlement entitlement : MapleFamilyEntitlement.values()) {
entitlements[entitlement.ordinal()] = 0;
}
}
public boolean saveReputation() {
if(!repChanged) return true;
try(Connection con = DatabaseConnection.getConnection()) {
return saveReputation(con);
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Could not get connection to DB.");
e.printStackTrace();
return false;
}
}
public boolean saveReputation(Connection con) {
if(!repChanged) return true;
try (PreparedStatement ps = con.prepareStatement("UPDATE family_character SET reputation = ?, todaysrep = ?, totalreputation = ?, reptosenior = ? WHERE cid = ?")) {
ps.setInt(1, getReputation());
ps.setInt(2, getTodaysRep());
ps.setInt(3, getTotalReputation());
ps.setInt(4, getRepsToSenior());
ps.setInt(5, getChrId());
ps.executeUpdate();
} catch(SQLException e) {
FilePrinter.printError(FilePrinter.FAMILY_ERROR, e, "Failed to autosave rep to 'family_character' for charid " + getChrId());
e.printStackTrace();
return false;
}
return true;
}
public void savedSuccessfully() {
this.repChanged = false;
}
}

View File

@@ -0,0 +1,135 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
public enum MapleJob {
BEGINNER(0),
WARRIOR(100),
FIGHTER(110), CRUSADER(111), HERO(112),
PAGE(120), WHITEKNIGHT(121), PALADIN(122),
SPEARMAN(130), DRAGONKNIGHT(131), DARKKNIGHT(132),
MAGICIAN(200),
FP_WIZARD(210), FP_MAGE(211), FP_ARCHMAGE(212),
IL_WIZARD(220), IL_MAGE(221), IL_ARCHMAGE(222),
CLERIC(230), PRIEST(231), BISHOP(232),
BOWMAN(300),
HUNTER(310), RANGER(311), BOWMASTER(312),
CROSSBOWMAN(320), SNIPER(321), MARKSMAN(322),
THIEF(400),
ASSASSIN(410), HERMIT(411), NIGHTLORD(412),
BANDIT(420), CHIEFBANDIT(421), SHADOWER(422),
PIRATE(500),
BRAWLER(510), MARAUDER(511), BUCCANEER(512),
GUNSLINGER(520), OUTLAW(521), CORSAIR(522),
MAPLELEAF_BRIGADIER(800),
GM(900), SUPERGM(910),
NOBLESSE(1000),
DAWNWARRIOR1(1100), DAWNWARRIOR2(1110), DAWNWARRIOR3(1111), DAWNWARRIOR4(1112),
BLAZEWIZARD1(1200), BLAZEWIZARD2(1210), BLAZEWIZARD3(1211), BLAZEWIZARD4(1212),
WINDARCHER1(1300), WINDARCHER2(1310), WINDARCHER3(1311), WINDARCHER4(1312),
NIGHTWALKER1(1400), NIGHTWALKER2(1410), NIGHTWALKER3(1411), NIGHTWALKER4(1412),
THUNDERBREAKER1(1500), THUNDERBREAKER2(1510), THUNDERBREAKER3(1511), THUNDERBREAKER4(1512),
LEGEND(2000), EVAN(2001),
ARAN1(2100), ARAN2(2110), ARAN3(2111), ARAN4(2112),
EVAN1(2200), EVAN2(2210), EVAN3(2211), EVAN4(2212), EVAN5(2213), EVAN6(2214),
EVAN7(2215), EVAN8(2216), EVAN9(2217), EVAN10(2218);
final int jobid;
final static int maxId = 22; // maxId = (EVAN / 100);
private MapleJob(int id) {
jobid = id;
}
public static int getMax() {
return maxId;
}
public int getId() {
return jobid;
}
public static MapleJob getById(int id) {
for (MapleJob l : MapleJob.values()) {
if (l.getId() == id) {
return l;
}
}
return null;
}
public static MapleJob getBy5ByteEncoding(int encoded) {
switch (encoded) {
case 2:
return WARRIOR;
case 4:
return MAGICIAN;
case 8:
return BOWMAN;
case 16:
return THIEF;
case 32:
return PIRATE;
case 1024:
return NOBLESSE;
case 2048:
return DAWNWARRIOR1;
case 4096:
return BLAZEWIZARD1;
case 8192:
return WINDARCHER1;
case 16384:
return NIGHTWALKER1;
case 32768:
return THUNDERBREAKER1;
default:
return BEGINNER;
}
}
public boolean isA(MapleJob basejob) { // thanks Steve (kaito1410) for pointing out an improvement here
int basebranch = basejob.getId() / 10;
return (getId() / 10 == basebranch && getId() >= basejob.getId()) || (basebranch % 10 == 0 && getId() / 100 == basejob.getId() / 100);
}
public int getJobNiche() {
return (jobid / 100) % 10;
/*
case 0: BEGINNER;
case 1: WARRIOR;
case 2: MAGICIAN;
case 3: BOWMAN;
case 4: THIEF;
case 5: PIRATE;
*/
}
}

View File

@@ -0,0 +1,127 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
/**
* @author PurpleMadness < Patrick :O >
*/
public class MapleMount {
private int itemid;
private int skillid;
private int tiredness;
private int exp;
private int level;
private MapleCharacter owner;
private boolean active;
public MapleMount(MapleCharacter owner, int id, int skillid) {
this.itemid = id;
this.skillid = skillid;
this.tiredness = 0;
this.level = 1;
this.exp = 0;
this.owner = owner;
active = true;
}
public int getItemId() {
return itemid;
}
public int getSkillId() {
return skillid;
}
/**
* 1902000 - Hog
* 1902001 - Silver Mane
* 1902002 - Red Draco
* 1902005 - Mimiana
* 1902006 - Mimio
* 1902007 - Shinjou
* 1902008 - Frog
* 1902009 - Ostrich
* 1902010 - Frog
* 1902011 - Turtle
* 1902012 - Yeti
* @return the id
*/
public int getId() {
if (this.itemid < 1903000) {
return itemid - 1901999;
}
return 5;
}
public int getTiredness() {
return tiredness;
}
public int getExp() {
return exp;
}
public int getLevel() {
return level;
}
public void setTiredness(int newtiredness) {
this.tiredness = newtiredness;
if (tiredness < 0) {
tiredness = 0;
}
}
public int incrementAndGetTiredness() {
this.tiredness++;
return this.tiredness;
}
public void setExp(int newexp) {
this.exp = newexp;
}
public void setLevel(int newlevel) {
this.level = newlevel;
}
public void setItemId(int newitemid) {
this.itemid = newitemid;
}
public void setSkillId(int newskillid) {
this.skillid = newskillid;
}
public void setActive(boolean set) {
this.active = set;
}
public boolean isActive() {
return active;
}
public void empty() {
if(owner != null) owner.getClient().getWorldServer().unregisterMountHunger(owner);
this.owner = null;
}
}

View File

@@ -0,0 +1,278 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import server.quest.MapleQuest;
import tools.StringUtil;
/**
*
* @author Matze
*/
public class MapleQuestStatus {
public enum Status {
UNDEFINED(-1),
NOT_STARTED(0),
STARTED(1),
COMPLETED(2);
final int status;
private Status(int id) {
status = id;
}
public int getId() {
return status;
}
public static Status getById(int id) {
for (Status l : Status.values()) {
if (l.getId() == id) {
return l;
}
}
return null;
}
}
private short questID;
private Status status;
//private boolean updated; //maybe this can be of use for someone?
private final Map<Integer, String> progress = new LinkedHashMap<Integer, String>();
private final List<Integer> medalProgress = new LinkedList<Integer>();
private int npc;
private long completionTime, expirationTime;
private int forfeited = 0, completed = 0;
private String customData;
public MapleQuestStatus(MapleQuest quest, Status status) {
this.questID = quest.getId();
this.setStatus(status);
this.completionTime = System.currentTimeMillis();
this.expirationTime = 0;
//this.updated = true;
if (status == Status.STARTED)
registerMobs();
}
public MapleQuestStatus(MapleQuest quest, Status status, int npc) {
this.questID = quest.getId();
this.setStatus(status);
this.setNpc(npc);
this.completionTime = System.currentTimeMillis();
this.expirationTime = 0;
//this.updated = true;
if (status == Status.STARTED) {
registerMobs();
}
}
public MapleQuest getQuest() {
return MapleQuest.getInstance(questID);
}
public short getQuestID() {
return questID;
}
public Status getStatus() {
return status;
}
public final void setStatus(Status status) {
this.status = status;
}
/*
public boolean wasUpdated() {
return updated;
}
private void setUpdated() {
this.updated = true;
}
public void resetUpdated() {
this.updated = false;
}
*/
public int getNpc() {
return npc;
}
public final void setNpc(int npc) {
this.npc = npc;
}
private void registerMobs() {
for (int i : MapleQuest.getInstance(questID).getRelevantMobs()) {
progress.put(i, "000");
}
//this.setUpdated();
}
public boolean addMedalMap(int mapid) {
if (medalProgress.contains(mapid)) return false;
medalProgress.add(mapid);
//this.setUpdated();
return true;
}
public int getMedalProgress() {
return medalProgress.size();
}
public List<Integer> getMedalMaps() {
return medalProgress;
}
public boolean progress(int id) {
String currentStr = progress.get(id);
if (currentStr == null) {
return false;
}
int current = Integer.parseInt(currentStr);
if (current >= this.getQuest().getMobAmountNeeded(id)) {
return false;
}
String str = StringUtil.getLeftPaddedStr(Integer.toString(++current), '0', 3);
progress.put(id, str);
//this.setUpdated();
return true;
}
public void setProgress(int id, String pr) {
progress.put(id, pr);
//this.setUpdated();
}
public boolean madeProgress() {
return progress.size() > 0;
}
public String getProgress(int id) {
String ret = progress.get(id);
if (ret == null) {
return "";
} else {
return ret;
}
}
public void resetProgress(int id) {
setProgress(id, "000");
}
public void resetAllProgress() {
for(Map.Entry<Integer, String> entry : progress.entrySet()) {
setProgress(entry.getKey(), "000");
}
}
public Map<Integer, String> getProgress() {
return Collections.unmodifiableMap(progress);
}
public short getInfoNumber() {
MapleQuest q = this.getQuest();
Status s = this.getStatus();
return q.getInfoNumber(s);
}
public String getInfoEx(int index) {
MapleQuest q = this.getQuest();
Status s = this.getStatus();
return q.getInfoEx(s, index);
}
public List<String> getInfoEx() {
MapleQuest q = this.getQuest();
Status s = this.getStatus();
return q.getInfoEx(s);
}
public long getCompletionTime() {
return completionTime;
}
public void setCompletionTime(long completionTime) {
this.completionTime = completionTime;
}
public long getExpirationTime() {
return expirationTime;
}
public void setExpirationTime(long expirationTime) {
this.expirationTime = expirationTime;
}
public int getForfeited() {
return forfeited;
}
public int getCompleted() {
return completed;
}
public void setForfeited(int forfeited) {
if (forfeited >= this.forfeited) {
this.forfeited = forfeited;
} else {
throw new IllegalArgumentException("Can't set forfeits to something lower than before.");
}
}
public void setCompleted(int completed) {
if (completed >= this.completed) {
this.completed = completed;
} else {
throw new IllegalArgumentException("Can't set completes to something lower than before.");
}
}
public final void setCustomData(final String customData) {
this.customData = customData;
}
public final String getCustomData() {
return customData;
}
public String getProgressData() {
StringBuilder str = new StringBuilder();
for (String ps : progress.values()) {
str.append(ps);
}
return str.toString();
}
}

View File

@@ -0,0 +1,206 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import tools.Pair;
import tools.DatabaseConnection;
import client.inventory.manipulator.MapleCashidGenerator;
/**
*
* @author Danny
*/
public class MapleRing implements Comparable<MapleRing> {
private int ringId;
private int ringId2;
private int partnerId;
private int itemId;
private String partnerName;
private boolean equipped = false;
public MapleRing(int id, int id2, int partnerId, int itemid, String partnername) {
this.ringId = id;
this.ringId2 = id2;
this.partnerId = partnerId;
this.itemId = itemid;
this.partnerName = partnername;
}
public static MapleRing loadFromDb(int ringId) {
try {
MapleRing ret = null;
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM rings WHERE id = ?"); // Get ring details..
ps.setInt(1, ringId);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
ret = new MapleRing(ringId, rs.getInt("partnerRingId"), rs.getInt("partnerChrId"), rs.getInt("itemid"), rs.getString("partnerName"));
}
rs.close();
ps.close();
con.close();
return ret;
} catch (SQLException ex) {
ex.printStackTrace();
return null;
}
}
public static void removeRing(final MapleRing ring) {
try {
if (ring == null) {
return;
}
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM rings WHERE id=?");
ps.setInt(1, ring.getRingId());
ps.addBatch();
ps.setInt(1, ring.getPartnerRingId());
ps.addBatch();
ps.executeBatch();
ps.close();
MapleCashidGenerator.freeCashId(ring.getRingId());
MapleCashidGenerator.freeCashId(ring.getPartnerRingId());
ps = con.prepareStatement("UPDATE inventoryequipment SET ringid=-1 WHERE ringid=?");
ps.setInt(1, ring.getRingId());
ps.addBatch();
ps.setInt(1, ring.getPartnerRingId());
ps.addBatch();
ps.executeBatch();
ps.close();
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public static Pair<Integer, Integer> createRing(int itemid, final MapleCharacter partner1, final MapleCharacter partner2) {
try {
if (partner1 == null) {
return new Pair<>(-3, -3);
} else if (partner2 == null) {
return new Pair<>(-2, -2);
}
int[] ringID = new int[2];
ringID[0] = MapleCashidGenerator.generateCashId();
ringID[1] = MapleCashidGenerator.generateCashId();
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO rings (id, itemid, partnerRingId, partnerChrId, partnername) VALUES (?, ?, ?, ?, ?)");
ps.setInt(1, ringID[0]);
ps.setInt(2, itemid);
ps.setInt(3, ringID[1]);
ps.setInt(4, partner2.getId());
ps.setString(5, partner2.getName());
ps.executeUpdate();
ps.close();
ps = con.prepareStatement("INSERT INTO rings (id, itemid, partnerRingId, partnerChrId, partnername) VALUES (?, ?, ?, ?, ?)");
ps.setInt(1, ringID[1]);
ps.setInt(2, itemid);
ps.setInt(3, ringID[0]);
ps.setInt(4, partner1.getId());
ps.setString(5, partner1.getName());
ps.executeUpdate();
ps.close();
con.close();
return new Pair<>(ringID[0], ringID[1]);
} catch (SQLException ex) {
ex.printStackTrace();
return new Pair<>(-1, -1);
}
}
public int getRingId() {
return ringId;
}
public int getPartnerRingId() {
return ringId2;
}
public int getPartnerChrId() {
return partnerId;
}
public int getItemId() {
return itemId;
}
public String getPartnerName() {
return partnerName;
}
public boolean equipped() {
return equipped;
}
public void equip() {
this.equipped = true;
}
public void unequip() {
this.equipped = false;
}
@Override
public boolean equals(Object o) {
if (o instanceof MapleRing) {
if (((MapleRing) o).getRingId() == getRingId()) {
return true;
} else {
return false;
}
}
return false;
}
@Override
public int hashCode() {
int hash = 5;
hash = 53 * hash + this.ringId;
return hash;
}
@Override
public int compareTo(MapleRing other) {
if (ringId < other.getRingId()) {
return -1;
} else if (ringId == other.getRingId()) {
return 0;
}
return 1;
}
}

View File

@@ -0,0 +1,44 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
public enum MapleSkinColor {
NORMAL(0), DARK(1), BLACK(2), PALE(3), BLUE(4), GREEN(5), WHITE(9), PINK(10);
final int id;
private MapleSkinColor(int id) {
this.id = id;
}
public int getId() {
return id;
}
public static MapleSkinColor getById(int id) {
for (MapleSkinColor l : MapleSkinColor.values()) {
if (l.getId() == id) {
return l;
}
}
return null;
}
}

View File

@@ -0,0 +1,121 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
public enum MapleStat {
SKIN(0x1),
FACE(0x2),
HAIR(0x4),
LEVEL(0x10),
JOB(0x20),
STR(0x40),
DEX(0x80),
INT(0x100),
LUK(0x200),
HP(0x400),
MAXHP(0x800),
MP(0x1000),
MAXMP(0x2000),
AVAILABLEAP(0x4000),
AVAILABLESP(0x8000),
EXP(0x10000),
FAME(0x20000),
MESO(0x40000),
PET(0x180008),
GACHAEXP(0x200000);
private final int i;
private MapleStat(int i) {
this.i = i;
}
public int getValue() {
return i;
}
public static MapleStat getByValue(int value) {
for (MapleStat stat : MapleStat.values()) {
if (stat.getValue() == value) {
return stat;
}
}
return null;
}
public static MapleStat getBy5ByteEncoding(int encoded) {
switch (encoded) {
case 64:
return STR;
case 128:
return DEX;
case 256:
return INT;
case 512:
return LUK;
}
return null;
}
public static MapleStat getByString(String type) {
if (type.equals("SKIN")) {
return SKIN;
} else if (type.equals("FACE")) {
return FACE;
} else if (type.equals("HAIR")) {
return HAIR;
} else if (type.equals("LEVEL")) {
return LEVEL;
} else if (type.equals("JOB")) {
return JOB;
} else if (type.equals("STR")) {
return STR;
} else if (type.equals("DEX")) {
return DEX;
} else if (type.equals("INT")) {
return INT;
} else if (type.equals("LUK")) {
return LUK;
} else if (type.equals("HP")) {
return HP;
} else if (type.equals("MAXHP")) {
return MAXHP;
} else if (type.equals("MP")) {
return MP;
} else if (type.equals("MAXMP")) {
return MAXMP;
} else if (type.equals("AVAILABLEAP")) {
return AVAILABLEAP;
} else if (type.equals("AVAILABLESP")) {
return AVAILABLESP;
} else if (type.equals("EXP")) {
return EXP;
} else if (type.equals("FAME")) {
return FAME;
} else if (type.equals("MESO")) {
return MESO;
} else if (type.equals("PET")) {
return PET;
}
return null;
}
}

View File

@@ -0,0 +1,271 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.Semaphore;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import net.server.audit.locks.MonitoredLockType;
import net.server.audit.locks.factory.MonitoredReentrantLockFactory;
public final class MonsterBook {
private static final Semaphore semaphore = new Semaphore(10);
private int specialCard = 0;
private int normalCard = 0;
private int bookLevel = 1;
private Map<Integer, Integer> cards = new LinkedHashMap<>();
private Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.BOOK);
public Set<Entry<Integer, Integer>> getCardSet() {
lock.lock();
try {
return new HashSet<>(cards.entrySet());
} finally {
lock.unlock();
}
}
public void addCard(final MapleClient c, final int cardid) {
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignCardEffect(c.getPlayer().getId()), false);
Integer qty;
lock.lock();
try {
qty = cards.get(cardid);
if(qty != null) {
if(qty < 5) {
cards.put(cardid, qty + 1);
}
} else {
cards.put(cardid, 1);
qty = 0;
if (cardid / 1000 >= 2388) {
specialCard++;
} else {
normalCard++;
}
}
} finally {
lock.unlock();
}
if(qty < 5) {
if (qty == 0) { // leveling system only accounts unique cards
calculateLevel();
}
c.announce(MaplePacketCreator.addCard(false, cardid, qty + 1));
c.announce(MaplePacketCreator.showGainCard());
} else {
c.announce(MaplePacketCreator.addCard(true, cardid, 5));
}
}
private void calculateLevel() {
lock.lock();
try {
int collectionExp = (normalCard + specialCard);
int level = 0, expToNextlevel = 1;
do {
level++;
expToNextlevel += level * 10;
} while (collectionExp >= expToNextlevel);
bookLevel = level; // thanks IxianMace for noticing book level differing between book UI and character info UI
} finally {
lock.unlock();
}
}
public int getBookLevel() {
lock.lock();
try {
return bookLevel;
} finally {
lock.unlock();
}
}
public Map<Integer, Integer> getCards() {
lock.lock();
try {
return Collections.unmodifiableMap(cards);
} finally {
lock.unlock();
}
}
public int getTotalCards() {
lock.lock();
try {
return specialCard + normalCard;
} finally {
lock.unlock();
}
}
public int getNormalCard() {
lock.lock();
try {
return normalCard;
} finally {
lock.unlock();
}
}
public int getSpecialCard() {
lock.lock();
try {
return specialCard;
} finally {
lock.unlock();
}
}
public void loadCards(final int charid) throws SQLException {
lock.lock();
try {
Connection con = DatabaseConnection.getConnection();
try (PreparedStatement ps = con.prepareStatement("SELECT cardid, level FROM monsterbook WHERE charid = ? ORDER BY cardid ASC")) {
ps.setInt(1, charid);
try (ResultSet rs = ps.executeQuery()) {
int cardid, level;
while (rs.next()) {
cardid = rs.getInt("cardid");
level = rs.getInt("level");
if (cardid / 1000 >= 2388) {
specialCard++;
} else {
normalCard++;
}
cards.put(cardid, level);
}
}
}
con.close();
} finally {
lock.unlock();
}
calculateLevel();
}
private static int saveStringConcat(char[] data, int pos, Integer i) {
return saveStringConcat(data, pos, i.toString());
}
private static int saveStringConcat(char[] data, int pos, String s) {
int len = s.length();
for(int j = 0; j < len; j++) {
data[pos + j] = s.charAt(j);
}
return pos + len;
}
private static String getSaveString(Integer charid, Set<Entry<Integer, Integer>> cardSet) {
semaphore.acquireUninterruptibly();
try {
char[] save = new char[400000]; // 500 * 10 * 10 * 8
int i = 0;
i = saveStringConcat(save, i, "INSERT INTO monsterbook VALUES ");
for (Entry<Integer, Integer> all : cardSet) { // assuming maxsize 500 unique cards
i = saveStringConcat(save, i, "(");
i = saveStringConcat(save, i, charid); //10 chars
i = saveStringConcat(save, i, ", ");
i = saveStringConcat(save, i, all.getKey()); //10 chars
i = saveStringConcat(save, i, ", ");
i = saveStringConcat(save, i, all.getValue()); //1 char due to being 0 ~ 5
i = saveStringConcat(save, i, "),");
}
return new String(save, 0, i - 1);
} finally {
semaphore.release();
}
}
public void saveCards(final int charid) {
Set<Entry<Integer, Integer>> cardSet = getCardSet();
if (cardSet.isEmpty()) {
return;
}
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("DELETE FROM monsterbook WHERE charid = ?");
ps.setInt(1, charid);
ps.execute();
ps.close();
ps = con.prepareStatement(getSaveString(charid, cardSet));
ps.execute();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static int[] getCardTierSize() {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT COUNT(*) FROM monstercarddata GROUP BY floor(cardid / 1000);");
ResultSet rs = ps.executeQuery();
rs.last();
int[] tierSizes = new int[rs.getRow()];
rs.beforeFirst();
while (rs.next()) {
tierSizes[rs.getRow() - 1] = rs.getInt(1);
}
rs.close();
ps.close();
con.close();
return tierSizes;
} catch (SQLException e) {
e.printStackTrace();
return new int[0];
}
}
}

View File

@@ -0,0 +1,99 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import java.util.ArrayList;
import java.util.List;
import server.MapleStatEffect;
import server.life.Element;
public class Skill {
private int id;
private List<MapleStatEffect> effects = new ArrayList<>();
private Element element;
private int animationTime;
private int job;
private boolean action;
public Skill(int id) {
this.id = id;
this.job = id / 10000;
}
public int getId() {
return id;
}
public MapleStatEffect getEffect(int level) {
return effects.get(level - 1);
}
public int getMaxLevel() {
return effects.size();
}
public boolean isFourthJob() {
if (job == 2212) {
return false;
}
if (id == 22170001 || id == 22171003 || id == 22171004 || id == 22181002 || id == 22181003) {
return true;
}
return job % 10 == 2;
}
public void setElement(Element elem) {
element = elem;
}
public Element getElement() {
return element;
}
public int getAnimationTime() {
return animationTime;
}
public void setAnimationTime(int time) {
animationTime = time;
}
public void incAnimationTime(int time) {
animationTime += time;
}
public boolean isBeginnerSkill() {
return id % 10000000 < 10000;
}
public void setAction(boolean act) {
action = act;
}
public boolean getAction() {
return action;
}
public void addLevelEffect(MapleStatEffect effect) {
effects.add(effect);
}
}

View File

@@ -0,0 +1,406 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
import constants.skills.Aran;
import constants.skills.Archer;
import constants.skills.Assassin;
import constants.skills.Bandit;
import constants.skills.Beginner;
import constants.skills.Bishop;
import constants.skills.BlazeWizard;
import constants.skills.Bowmaster;
import constants.skills.Buccaneer;
import constants.skills.ChiefBandit;
import constants.skills.Cleric;
import constants.skills.Corsair;
import constants.skills.Crossbowman;
import constants.skills.Crusader;
import constants.skills.DarkKnight;
import constants.skills.DawnWarrior;
import constants.skills.DragonKnight;
import constants.skills.Evan;
import constants.skills.FPArchMage;
import constants.skills.FPMage;
import constants.skills.FPWizard;
import constants.skills.Fighter;
import constants.skills.GM;
import constants.skills.Gunslinger;
import constants.skills.Hermit;
import constants.skills.Hero;
import constants.skills.Hunter;
import constants.skills.ILArchMage;
import constants.skills.ILMage;
import constants.skills.ILWizard;
import constants.skills.Legend;
import constants.skills.Magician;
import constants.skills.Marauder;
import constants.skills.Marksman;
import constants.skills.NightLord;
import constants.skills.NightWalker;
import constants.skills.Noblesse;
import constants.skills.Page;
import constants.skills.Paladin;
import constants.skills.Pirate;
import constants.skills.Priest;
import constants.skills.Ranger;
import constants.skills.Rogue;
import constants.skills.Shadower;
import constants.skills.Sniper;
import constants.skills.Spearman;
import constants.skills.SuperGM;
import constants.skills.Warrior;
import constants.skills.ThunderBreaker;
import constants.skills.WhiteKnight;
import constants.skills.WindArcher;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataDirectoryEntry;
import provider.MapleDataFileEntry;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import server.MapleStatEffect;
import server.life.Element;
public class SkillFactory {
private static Map<Integer, Skill> skills = new HashMap<>();
private static MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Skill.wz"));
public static Skill getSkill(int id) {
if (!skills.isEmpty()) {
return skills.get(Integer.valueOf(id));
}
return null;
}
public static void loadAllSkills() {
final MapleDataDirectoryEntry root = datasource.getRoot();
int skillid;
for (MapleDataFileEntry topDir : root.getFiles()) { // Loop thru jobs
if (topDir.getName().length() <= 8) {
for (MapleData data : datasource.getData(topDir.getName())) { // Loop thru each jobs
if (data.getName().equals("skill")) {
for (MapleData data2 : data) { // Loop thru each jobs
if (data2 != null) {
skillid = Integer.parseInt(data2.getName());
skills.put(skillid, loadFromData(skillid, data2));
}
}
}
}
}
}
}
private static Skill loadFromData(int id, MapleData data) {
Skill ret = new Skill(id);
boolean isBuff = false;
int skillType = MapleDataTool.getInt("skillType", data, -1);
String elem = MapleDataTool.getString("elemAttr", data, null);
if (elem != null) {
ret.setElement(Element.getFromChar(elem.charAt(0)));
} else {
ret.setElement(Element.NEUTRAL);
}
MapleData effect = data.getChildByPath("effect");
if (skillType != -1) {
if (skillType == 2) {
isBuff = true;
}
} else {
MapleData action_ = data.getChildByPath("action");
boolean action = false;
if (action_ == null) {
if (data.getChildByPath("prepare/action") != null) {
action = true;
} else {
switch (id) {
case Gunslinger.INVISIBLE_SHOT:
case Corsair.HYPNOTIZE:
action = true;
break;
}
}
} else {
action = true;
}
ret.setAction(action);
MapleData hit = data.getChildByPath("hit");
MapleData ball = data.getChildByPath("ball");
isBuff = effect != null && hit == null && ball == null;
isBuff |= action_ != null && MapleDataTool.getString("0", action_, "").equals("alert2");
switch (id) {
case Hero.RUSH:
case Paladin.RUSH:
case DarkKnight.RUSH:
case DragonKnight.SACRIFICE:
case FPMage.EXPLOSION:
case FPMage.POISON_MIST:
case Cleric.HEAL:
case Ranger.MORTAL_BLOW:
case Sniper.MORTAL_BLOW:
case Assassin.DRAIN:
case Hermit.SHADOW_WEB:
case Bandit.STEAL:
case Shadower.SMOKE_SCREEN:
case SuperGM.HEAL_PLUS_DISPEL:
case Hero.MONSTER_MAGNET:
case Paladin.MONSTER_MAGNET:
case DarkKnight.MONSTER_MAGNET:
case Evan.ICE_BREATH:
case Evan.FIRE_BREATH:
case Gunslinger.RECOIL_SHOT:
case Marauder.ENERGY_DRAIN:
case BlazeWizard.FLAME_GEAR:
case NightWalker.SHADOW_WEB:
case NightWalker.POISON_BOMB:
case NightWalker.VAMPIRE:
case ChiefBandit.CHAKRA:
case Aran.COMBAT_STEP:
case Evan.RECOVERY_AURA:
isBuff = false;
break;
case Beginner.RECOVERY:
case Beginner.NIMBLE_FEET:
case Beginner.MONSTER_RIDER:
case Beginner.ECHO_OF_HERO:
case Beginner.MAP_CHAIR:
case Warrior.IRON_BODY:
case Fighter.AXE_BOOSTER:
case Fighter.POWER_GUARD:
case Fighter.RAGE:
case Fighter.SWORD_BOOSTER:
case Crusader.ARMOR_CRASH:
case Crusader.COMBO:
case Hero.ENRAGE:
case Hero.HEROS_WILL:
case Hero.MAPLE_WARRIOR:
case Hero.STANCE:
case Page.BW_BOOSTER:
case Page.POWER_GUARD:
case Page.SWORD_BOOSTER:
case Page.THREATEN:
case WhiteKnight.BW_FIRE_CHARGE:
case WhiteKnight.BW_ICE_CHARGE:
case WhiteKnight.BW_LIT_CHARGE:
case WhiteKnight.MAGIC_CRASH:
case WhiteKnight.SWORD_FIRE_CHARGE:
case WhiteKnight.SWORD_ICE_CHARGE:
case WhiteKnight.SWORD_LIT_CHARGE:
case Paladin.BW_HOLY_CHARGE:
case Paladin.HEROS_WILL:
case Paladin.MAPLE_WARRIOR:
case Paladin.STANCE:
case Paladin.SWORD_HOLY_CHARGE:
case Spearman.HYPER_BODY:
case Spearman.IRON_WILL:
case Spearman.POLEARM_BOOSTER:
case Spearman.SPEAR_BOOSTER:
case DragonKnight.DRAGON_BLOOD:
case DragonKnight.POWER_CRASH:
case DarkKnight.AURA_OF_BEHOLDER:
case DarkKnight.BEHOLDER:
case DarkKnight.HEROS_WILL:
case DarkKnight.HEX_OF_BEHOLDER:
case DarkKnight.MAPLE_WARRIOR:
case DarkKnight.STANCE:
case Magician.MAGIC_GUARD:
case Magician.MAGIC_ARMOR:
case FPWizard.MEDITATION:
case FPWizard.SLOW:
case FPMage.SEAL:
case FPMage.SPELL_BOOSTER:
case FPArchMage.HEROS_WILL:
case FPArchMage.INFINITY:
case FPArchMage.MANA_REFLECTION:
case FPArchMage.MAPLE_WARRIOR:
case ILWizard.MEDITATION:
case ILMage.SEAL:
case ILWizard.SLOW:
case ILMage.SPELL_BOOSTER:
case ILArchMage.HEROS_WILL:
case ILArchMage.INFINITY:
case ILArchMage.MANA_REFLECTION:
case ILArchMage.MAPLE_WARRIOR:
case Cleric.INVINCIBLE:
case Cleric.BLESS:
case Priest.DISPEL:
case Priest.DOOM:
case Priest.HOLY_SYMBOL:
case Priest.MYSTIC_DOOR:
case Bishop.HEROS_WILL:
case Bishop.HOLY_SHIELD:
case Bishop.INFINITY:
case Bishop.MANA_REFLECTION:
case Bishop.MAPLE_WARRIOR:
case Archer.FOCUS:
case Hunter.BOW_BOOSTER:
case Hunter.SOUL_ARROW:
case Ranger.PUPPET:
case Bowmaster.CONCENTRATE:
case Bowmaster.HEROS_WILL:
case Bowmaster.MAPLE_WARRIOR:
case Bowmaster.SHARP_EYES:
case Crossbowman.CROSSBOW_BOOSTER:
case Crossbowman.SOUL_ARROW:
case Sniper.PUPPET:
case Marksman.BLIND:
case Marksman.HEROS_WILL:
case Marksman.MAPLE_WARRIOR:
case Marksman.SHARP_EYES:
case Rogue.DARK_SIGHT:
case Assassin.CLAW_BOOSTER:
case Assassin.HASTE:
case Hermit.MESO_UP:
case Hermit.SHADOW_PARTNER:
case NightLord.HEROS_WILL:
case NightLord.MAPLE_WARRIOR:
case NightLord.NINJA_AMBUSH:
case NightLord.SHADOW_STARS:
case Bandit.DAGGER_BOOSTER:
case Bandit.HASTE:
case ChiefBandit.MESO_GUARD:
case ChiefBandit.PICKPOCKET:
case Shadower.HEROS_WILL:
case Shadower.MAPLE_WARRIOR:
case Shadower.NINJA_AMBUSH:
case Pirate.DASH:
case Marauder.TRANSFORMATION:
case Buccaneer.SUPER_TRANSFORMATION:
case Corsair.BATTLE_SHIP:
case GM.HIDE:
case SuperGM.HASTE:
case SuperGM.HOLY_SYMBOL:
case SuperGM.BLESS:
case SuperGM.HIDE:
case SuperGM.HYPER_BODY:
case Noblesse.BLESSING_OF_THE_FAIRY:
case Noblesse.ECHO_OF_HERO:
case Noblesse.MONSTER_RIDER:
case Noblesse.NIMBLE_FEET:
case Noblesse.RECOVERY:
case Noblesse.MAP_CHAIR:
case DawnWarrior.COMBO:
case DawnWarrior.FINAL_ATTACK:
case DawnWarrior.IRON_BODY:
case DawnWarrior.RAGE:
case DawnWarrior.SOUL:
case DawnWarrior.SOUL_CHARGE:
case DawnWarrior.SWORD_BOOSTER:
case BlazeWizard.ELEMENTAL_RESET:
case BlazeWizard.FLAME:
case BlazeWizard.IFRIT:
case BlazeWizard.MAGIC_ARMOR:
case BlazeWizard.MAGIC_GUARD:
case BlazeWizard.MEDITATION:
case BlazeWizard.SEAL:
case BlazeWizard.SLOW:
case BlazeWizard.SPELL_BOOSTER:
case WindArcher.BOW_BOOSTER:
case WindArcher.EAGLE_EYE:
case WindArcher.FINAL_ATTACK:
case WindArcher.FOCUS:
case WindArcher.PUPPET:
case WindArcher.SOUL_ARROW:
case WindArcher.STORM:
case WindArcher.WIND_WALK:
case NightWalker.CLAW_BOOSTER:
case NightWalker.DARKNESS:
case NightWalker.DARK_SIGHT:
case NightWalker.HASTE:
case NightWalker.SHADOW_PARTNER:
case ThunderBreaker.DASH:
case ThunderBreaker.ENERGY_CHARGE:
case ThunderBreaker.ENERGY_DRAIN:
case ThunderBreaker.KNUCKLER_BOOSTER:
case ThunderBreaker.LIGHTNING:
case ThunderBreaker.SPARK:
case ThunderBreaker.LIGHTNING_CHARGE:
case ThunderBreaker.SPEED_INFUSION:
case ThunderBreaker.TRANSFORMATION:
case Legend.BLESSING_OF_THE_FAIRY:
case Legend.AGILE_BODY:
case Legend.ECHO_OF_HERO:
case Legend.RECOVERY:
case Legend.MONSTER_RIDER:
case Legend.MAP_CHAIR:
case Aran.MAPLE_WARRIOR:
case Aran.HEROS_WILL:
case Aran.POLEARM_BOOSTER:
case Aran.COMBO_DRAIN:
case Aran.SNOW_CHARGE:
case Aran.BODY_PRESSURE:
case Aran.SMART_KNOCKBACK:
case Aran.COMBO_BARRIER:
case Aran.COMBO_ABILITY:
case Evan.BLESSING_OF_THE_FAIRY:
case Evan.RECOVERY:
case Evan.NIMBLE_FEET:
case Evan.HEROS_WILL:
case Evan.ECHO_OF_HERO:
case Evan.MAGIC_BOOSTER:
case Evan.MAGIC_GUARD:
case Evan.ELEMENTAL_RESET:
case Evan.MAPLE_WARRIOR:
case Evan.MAGIC_RESISTANCE:
case Evan.MAGIC_SHIELD:
case Evan.SLOW:
isBuff = true;
break;
}
}
for (MapleData level : data.getChildByPath("level")) {
ret.addLevelEffect(MapleStatEffect.loadSkillEffectFromData(level, id, isBuff));
}
ret.setAnimationTime(0);
if (effect != null) {
for (MapleData effectEntry : effect) {
ret.incAnimationTime(MapleDataTool.getIntConvert("delay", effectEntry, 0));
}
}
return ret;
}
public static String getSkillName(int skillid) {
MapleData data = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img");
StringBuilder skill = new StringBuilder();
skill.append(String.valueOf(skillid));
if (skill.length() == 4) {
skill.delete(0, 4);
skill.append("000").append(String.valueOf(skillid));
}
if (data.getChildByPath(skill.toString()) != null) {
for (MapleData skilldata : data.getChildByPath(skill.toString()).getChildren()) {
if (skilldata.getName().equals("name"))
return MapleDataTool.getString(skilldata, null);
}
}
return null;
}
}

View File

@@ -0,0 +1,76 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client;
public class SkillMacro {
private int skill1;
private int skill2;
private int skill3;
private String name;
private int shout;
private int position;
public SkillMacro(int skill1, int skill2, int skill3, String name, int shout, int position) {
this.skill1 = skill1;
this.skill2 = skill2;
this.skill3 = skill3;
this.name = name;
this.shout = shout;
this.position = position;
}
public int getSkill1() {
return skill1;
}
public int getSkill2() {
return skill2;
}
public int getSkill3() {
return skill3;
}
public void setSkill1(int skill) {
skill1 = skill;
}
public void setSkill2(int skill) {
skill2 = skill;
}
public void setSkill3(int skill) {
skill3 = skill;
}
public String getName() {
return name;
}
public int getShout() {
return shout;
}
public int getPosition() {
return position;
}
}

View File

@@ -0,0 +1,104 @@
/*
This file is part of the OdinMS Maple Story Server
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.autoban;
import client.MapleCharacter;
import config.YamlConfig;
import net.server.Server;
import tools.FilePrinter;
import tools.MapleLogger;
import tools.MaplePacketCreator;
/**
*
* @author kevintjuh93
*/
public enum AutobanFactory {
MOB_COUNT,
GENERAL,
FIX_DAMAGE,
DAMAGE_HACK(15, 60 * 1000),
DISTANCE_HACK(10, 120 * 1000),
PORTAL_DISTANCE(5, 30000),
PACKET_EDIT,
ACC_HACK,
CREATION_GENERATOR,
HIGH_HP_HEALING,
FAST_HP_HEALING(15),
FAST_MP_HEALING(20, 30000),
GACHA_EXP,
TUBI(20, 15000),
SHORT_ITEM_VAC,
ITEM_VAC,
FAST_ITEM_PICKUP(5, 30000),
FAST_ATTACK(10, 30000),
MPCON(25, 30000);
private int points;
private long expiretime;
private AutobanFactory() {
this(1, -1);
}
private AutobanFactory(int points) {
this.points = points;
this.expiretime = -1;
}
private AutobanFactory(int points, long expire) {
this.points = points;
this.expiretime = expire;
}
public int getMaximum() {
return points;
}
public long getExpire() {
return expiretime;
}
public void addPoint(AutobanManager ban, String reason) {
ban.addPoint(this, reason);
}
public void alert(MapleCharacter chr, String reason) {
if(YamlConfig.config.server.USE_AUTOBAN == true) {
if (chr != null && MapleLogger.ignored.contains(chr.getId())){
return;
}
Server.getInstance().broadcastGMMessage((chr != null ? chr.getWorld() : 0), MaplePacketCreator.sendYellowTip((chr != null ? MapleCharacter.makeMapleReadable(chr.getName()) : "") + " caused " + this.name() + " " + reason));
}
if (YamlConfig.config.server.USE_AUTOBAN_LOG) {
FilePrinter.print(FilePrinter.AUTOBAN_WARNING, (chr != null ? MapleCharacter.makeMapleReadable(chr.getName()) : "") + " caused " + this.name() + " " + reason);
}
}
public void autoban(MapleCharacter chr, String value) {
if(YamlConfig.config.server.USE_AUTOBAN == true) {
chr.autoban("Autobanned for (" + this.name() + ": " + value + ")");
//chr.sendPolice("You will be disconnected for (" + this.name() + ": " + value + ")");
}
}
}

View File

@@ -0,0 +1,126 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package client.autoban;
import client.MapleCharacter;
import config.YamlConfig;
import java.util.HashMap;
import java.util.Map;
import net.server.Server;
import tools.FilePrinter;
/**
*
* @author kevintjuh93
*/
public class AutobanManager {
private MapleCharacter chr;
private Map<AutobanFactory, Integer> points = new HashMap<>();
private Map<AutobanFactory, Long> lastTime = new HashMap<>();
private int misses = 0;
private int lastmisses = 0;
private int samemisscount = 0;
private long spam[] = new long[20];
private int timestamp[] = new int[20];
private byte timestampcounter[] = new byte[20];
public AutobanManager(MapleCharacter chr) {
this.chr = chr;
}
public void addPoint(AutobanFactory fac, String reason) {
if (YamlConfig.config.server.USE_AUTOBAN) {
if (chr.isGM() || chr.isBanned()){
return;
}
if (lastTime.containsKey(fac)) {
if (lastTime.get(fac) < (Server.getInstance().getCurrentTime() - fac.getExpire())) {
points.put(fac, points.get(fac) / 2); //So the points are not completely gone.
}
}
if (fac.getExpire() != -1)
lastTime.put(fac, Server.getInstance().getCurrentTime());
if (points.containsKey(fac)) {
points.put(fac, points.get(fac) + 1);
} else
points.put(fac, 1);
if (points.get(fac) >= fac.getMaximum()) {
chr.autoban(reason);
}
}
if (YamlConfig.config.server.USE_AUTOBAN_LOG) {
// Lets log every single point too.
FilePrinter.print(FilePrinter.AUTOBAN_WARNING, MapleCharacter.makeMapleReadable(chr.getName()) + " caused " + fac.name() + " " + reason);
}
}
public void addMiss() {
this.misses++;
}
public void resetMisses() {
if (lastmisses == misses && misses > 6) {
samemisscount++;
}
if (samemisscount > 4)
chr.sendPolice("You will be disconnected for miss godmode.");
//chr.autoban("Autobanned for : " + misses + " Miss godmode", 1);
else if (samemisscount > 0)
this.lastmisses = misses;
this.misses = 0;
}
//Don't use the same type for more than 1 thing
public void spam(int type) {
this.spam[type] = Server.getInstance().getCurrentTime();
}
public void spam(int type, int timestamp) {
this.spam[type] = timestamp;
}
public long getLastSpam(int type) {
return spam[type];
}
/**
* Timestamp checker
*
* <code>type</code>:<br>
* 1: Pet Food<br>
* 2: InventoryMerge<br>
* 3: InventorySort<br>
* 4: SpecialMove<br>
* 5: UseCatchItem<br>
* 6: Item Drop<br>
* 7: Chat<br>
* 8: HealOverTimeHP<br>
* 9: HealOverTimeMP<br>
*
* @param type type
* @return Timestamp checker
*/
public void setTimestamp(int type, int time, int times) {
if (this.timestamp[type] == time) {
this.timestampcounter[type]++;
if (this.timestampcounter[type] >= times) {
if (YamlConfig.config.server.USE_AUTOBAN) {
chr.getClient().disconnect(false, false);
}
FilePrinter.print(FilePrinter.EXPLOITS, "Player " + chr + " was caught spamming TYPE " + type + " and has been disconnected.");
}
} else {
this.timestamp[type] = time;
this.timestampcounter[type] = 0;
}
}
}

View File

@@ -0,0 +1,62 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command;
import client.MapleClient;
public abstract class Command {
protected int rank;
protected String description;
public abstract void execute(MapleClient client, String[] params);
public String getDescription() {
return description;
}
protected void setDescription(String description) {
this.description = description;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
protected String joinStringFrom(String arr[], int start) {
StringBuilder builder = new StringBuilder();
for (int i = start; i < arr.length; i++) {
builder.append(arr[i]);
if (i != arr.length - 1) {
builder.append(" ");
}
}
return builder.toString();
}
}

View File

@@ -0,0 +1,407 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command;
import client.command.commands.gm0.*;
import client.command.commands.gm1.*;
import client.command.commands.gm2.*;
import client.command.commands.gm3.*;
import client.command.commands.gm4.*;
import client.command.commands.gm5.*;
import client.command.commands.gm6.*;
import client.MapleClient;
import tools.FilePrinter;
import tools.Pair;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
public class CommandsExecutor {
public static CommandsExecutor instance = new CommandsExecutor();
public static CommandsExecutor getInstance() {
return instance;
}
private static final char USER_HEADING = '@';
private static final char GM_HEADING = '!';
public static boolean isCommand(MapleClient client, String content){
char heading = content.charAt(0);
if (client.getPlayer().isGM()){
return heading == USER_HEADING || heading == GM_HEADING;
}
return heading == USER_HEADING;
}
private HashMap<String, Command> registeredCommands = new HashMap<>();
private Pair<List<String>, List<String>> levelCommandsCursor;
private List<Pair<List<String>, List<String>>> commandsNameDesc = new ArrayList<>();
private CommandsExecutor(){
registerLv0Commands();
registerLv1Commands();
registerLv2Commands();
registerLv3Commands();
registerLv4Commands();
registerLv5Commands();
registerLv6Commands();
}
public List<Pair<List<String>, List<String>>> getGmCommands() {
return commandsNameDesc;
}
public void handle(MapleClient client, String message){
if (client.tryacquireClient()) {
try {
handleInternal(client, message);
} finally {
client.releaseClient();
}
} else {
client.getPlayer().dropMessage(5, "Try again in a while... Latest commands are currently being processed.");
}
}
private void handleInternal(MapleClient client, String message){
if (client.getPlayer().getMapId() == 300000012) {
client.getPlayer().yellowMessage("You do not have permission to use commands while in jail.");
return;
}
final String splitRegex = "[ ]";
String[] splitedMessage = message.substring(1).split(splitRegex, 2);
if (splitedMessage.length < 2) {
splitedMessage = new String[]{splitedMessage[0], ""};
}
client.getPlayer().setLastCommandMessage(splitedMessage[1]); // thanks Tochi & Nulliphite for noticing string messages being marshalled lowercase
final String commandName = splitedMessage[0].toLowerCase();
final String[] lowercaseParams = splitedMessage[1].toLowerCase().split(splitRegex);
final Command command = registeredCommands.get(commandName);
if (command == null){
client.getPlayer().yellowMessage("Command '" + commandName + "' is not available. See @commands for a list of available commands.");
return;
}
if (client.getPlayer().gmLevel() < command.getRank()){
client.getPlayer().yellowMessage("You do not have permission to use this command.");
return;
}
String[] params;
if (lowercaseParams.length > 0 && !lowercaseParams[0].isEmpty()) {
params = Arrays.copyOfRange(lowercaseParams, 0, lowercaseParams.length);
} else {
params = new String[]{};
}
command.execute(client, params);
writeLog(client, message);
}
private void writeLog(MapleClient client, String command){
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm");
FilePrinter.print(FilePrinter.USED_COMMANDS, client.getPlayer().getName() + " used: " + command + " on "
+ sdf.format(Calendar.getInstance().getTime()));
}
private void addCommandInfo(String name, Class<? extends Command> commandClass) {
try {
levelCommandsCursor.getRight().add(commandClass.newInstance().getDescription());
levelCommandsCursor.getLeft().add(name);
} catch(Exception e) {
e.printStackTrace();
}
}
private void addCommand(String[] syntaxs, Class<? extends Command> commandClass){
for (String syntax : syntaxs){
addCommand(syntax, 0, commandClass);
}
}
private void addCommand(String syntax, Class<? extends Command> commandClass){
//for (String syntax : syntaxs){
addCommand(syntax, 0, commandClass);
//}
}
private void addCommand(String[] surtaxes, int rank, Class<? extends Command> commandClass){
for (String syntax : surtaxes){
addCommand(syntax, rank, commandClass);
}
}
private void addCommand(String syntax, int rank, Class<? extends Command> commandClass){
if (registeredCommands.containsKey(syntax.toLowerCase())){
System.out.println("Error on register command with name: " + syntax + ". Already exists.");
return;
}
String commandName = syntax.toLowerCase();
addCommandInfo(commandName, commandClass);
try {
Command commandInstance = commandClass.newInstance(); // thanks Halcyon for noticing commands getting reinstanced every call
commandInstance.setRank(rank);
registeredCommands.put(commandName, commandInstance);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void registerLv0Commands(){
levelCommandsCursor = new Pair<>((List<String>) new ArrayList<String>(), (List<String>) new ArrayList<String>());
addCommand(new String[]{"help", "commands"}, HelpCommand.class);
addCommand("droplimit", DropLimitCommand.class);
addCommand("time", TimeCommand.class);
addCommand("credits", StaffCommand.class);
addCommand("buyback", BuyBackCommand.class);
addCommand("uptime", UptimeCommand.class);
addCommand("gacha", GachaCommand.class);
addCommand("dispose", DisposeCommand.class);
addCommand("changel", ChangeLanguageCommand.class);
addCommand("equiplv", EquipLvCommand.class);
addCommand("showrates", ShowRatesCommand.class);
addCommand("rates", RatesCommand.class);
addCommand("online", OnlineCommand.class);
addCommand("gm", GmCommand.class);
addCommand("reportbug", ReportBugCommand.class);
addCommand("points", ReadPointsCommand.class);
addCommand("joinevent", JoinEventCommand.class);
addCommand("leaveevent", LeaveEventCommand.class);
addCommand("ranks", RanksCommand.class);
addCommand("str", StatStrCommand.class);
addCommand("dex", StatDexCommand.class);
addCommand("int", StatIntCommand.class);
addCommand("luk", StatLukCommand.class);
addCommand("enableauth", EnableAuthCommand.class);
addCommand("toggleexp", ToggleExpCommand.class);
addCommand("mylawn", MapOwnerClaimCommand.class);
addCommand("bosshp", BossHpCommand.class);
addCommand("mobhp", MobHpCommand.class);
commandsNameDesc.add(levelCommandsCursor);
}
private void registerLv1Commands() {
levelCommandsCursor = new Pair<>((List<String>) new ArrayList<String>(), (List<String>) new ArrayList<String>());
addCommand("whatdropsfrom", 1, WhatDropsFromCommand.class);
addCommand("whodrops", 1, WhoDropsCommand.class);
addCommand("buffme", 1, BuffMeCommand.class);
addCommand("goto", 1, GotoCommand.class);
commandsNameDesc.add(levelCommandsCursor);
}
private void registerLv2Commands(){
levelCommandsCursor = new Pair<>((List<String>) new ArrayList<String>(), (List<String>) new ArrayList<String>());
addCommand("recharge", 2, RechargeCommand.class);
addCommand("whereami", 2, WhereaMiCommand.class);
addCommand("hide", 2, HideCommand.class);
addCommand("unhide", 2, UnHideCommand.class);
addCommand("sp", 2, SpCommand.class);
addCommand("ap", 2, ApCommand.class);
addCommand("empowerme", 2, EmpowerMeCommand.class);
addCommand("buffmap", 2, BuffMapCommand.class);
addCommand("buff", 2, BuffCommand.class);
addCommand("bomb", 2, BombCommand.class);
addCommand("dc", 2, DcCommand.class);
addCommand("cleardrops", 2, ClearDropsCommand.class);
addCommand("clearslot", 2, ClearSlotCommand.class);
addCommand("clearsavelocs", 2, ClearSavedLocationsCommand.class);
addCommand("warp", 2, WarpCommand.class);
addCommand(new String[]{"warphere", "summon"}, 2, SummonCommand.class);
addCommand(new String[]{"warpto", "reach", "follow"}, 2, ReachCommand.class);
addCommand("gmshop", 2, GmShopCommand.class);
addCommand("heal", 2, HealCommand.class);
addCommand("item", 2, ItemCommand.class);
addCommand("drop", 2, ItemDropCommand.class);
addCommand("level", 2, LevelCommand.class);
addCommand("levelpro", 2, LevelProCommand.class);
addCommand("setslot", 2, SetSlotCommand.class);
addCommand("setstat", 2, SetStatCommand.class);
addCommand("maxstat", 2, MaxStatCommand.class);
addCommand("maxskill", 2, MaxSkillCommand.class);
addCommand("resetskill", 2, ResetSkillCommand.class);
addCommand("search", 2, SearchCommand.class);
addCommand("jail", 2, JailCommand.class);
addCommand("unjail", 2, UnJailCommand.class);
addCommand("job", 2, JobCommand.class);
addCommand("unbug", 2, UnBugCommand.class);
addCommand("id", 2, IdCommand.class);
addCommand("gachalist", GachaListCommand.class);
addCommand("loot", LootCommand.class);
commandsNameDesc.add(levelCommandsCursor);
}
private void registerLv3Commands() {
levelCommandsCursor = new Pair<>((List<String>) new ArrayList<String>(), (List<String>) new ArrayList<String>());
addCommand("debuff", 3, DebuffCommand.class);
addCommand("fly", 3, FlyCommand.class);
addCommand("spawn", 3, SpawnCommand.class);
addCommand("mutemap", 3, MuteMapCommand.class);
addCommand("checkdmg", 3, CheckDmgCommand.class);
addCommand("inmap", 3, InMapCommand.class);
addCommand("reloadevents", 3, ReloadEventsCommand.class);
addCommand("reloaddrops", 3, ReloadDropsCommand.class);
addCommand("reloadportals", 3, ReloadPortalsCommand.class);
addCommand("reloadmap", 3, ReloadMapCommand.class);
addCommand("reloadshops", 3, ReloadShopsCommand.class);
addCommand("hpmp", 3, HpMpCommand.class);
addCommand("maxhpmp", 3, MaxHpMpCommand.class);
addCommand("music", 3, MusicCommand.class);
addCommand("monitor", 3, MonitorCommand.class);
addCommand("monitors", 3, MonitorsCommand.class);
addCommand("ignore", 3, IgnoreCommand.class);
addCommand("ignored", 3, IgnoredCommand.class);
addCommand("pos", 3, PosCommand.class);
addCommand("togglecoupon", 3, ToggleCouponCommand.class);
addCommand("togglewhitechat", 3, ChatCommand.class);
addCommand("fame", 3, FameCommand.class);
addCommand("givenx", 3, GiveNxCommand.class);
addCommand("givevp", 3, GiveVpCommand.class);
addCommand("givems", 3, GiveMesosCommand.class);
addCommand("giverp", 3, GiveRpCommand.class);
addCommand("expeds", 3, ExpedsCommand.class);
addCommand("kill", 3, KillCommand.class);
addCommand("seed", 3, SeedCommand.class);
addCommand("maxenergy", 3, MaxEnergyCommand.class);
addCommand("killall", 3, KillAllCommand.class);
addCommand("notice", 3, NoticeCommand.class);
addCommand("rip", 3, RipCommand.class);
addCommand("openportal", 3, OpenPortalCommand.class);
addCommand("closeportal", 3, ClosePortalCommand.class);
addCommand("pe", 3, PeCommand.class);
addCommand("startevent", 3, StartEventCommand.class);
addCommand("endevent", 3, EndEventCommand.class);
addCommand("startmapevent", 3, StartMapEventCommand.class);
addCommand("stopmapevent", 3, StopMapEventCommand.class);
addCommand("online2", 3, OnlineTwoCommand.class);
addCommand("ban", 3, BanCommand.class);
addCommand("unban", 3, UnBanCommand.class);
addCommand("healmap", 3, HealMapCommand.class);
addCommand("healperson", 3, HealPersonCommand.class);
addCommand("hurt", 3, HurtCommand.class);
addCommand("killmap", 3, KillMapCommand.class);
addCommand("night", 3, NightCommand.class);
addCommand("npc", 3, NpcCommand.class);
addCommand("face", 3, FaceCommand.class);
addCommand("hair", 3, HairCommand.class);
addCommand("startquest", 3, QuestStartCommand.class);
addCommand("completequest", 3, QuestCompleteCommand.class);
addCommand("resetquest", 3, QuestResetCommand.class);
addCommand("timer", 3, TimerCommand.class);
addCommand("timermap", 3, TimerMapCommand.class);
addCommand("timerall", 3, TimerAllCommand.class);
addCommand("warpmap", 3, WarpMapCommand.class);
addCommand("warparea", 3, WarpAreaCommand.class);
commandsNameDesc.add(levelCommandsCursor);
}
private void registerLv4Commands(){
levelCommandsCursor = new Pair<>((List<String>) new ArrayList<String>(), (List<String>) new ArrayList<String>());
addCommand("servermessage", 4, ServerMessageCommand.class);
addCommand("proitem", 4, ProItemCommand.class);
addCommand("seteqstat", 4, SetEqStatCommand.class);
addCommand("exprate", 4, ExpRateCommand.class);
addCommand("mesorate", 4, MesoRateCommand.class);
addCommand("droprate", 4, DropRateCommand.class);
addCommand("bossdroprate", 4, BossDropRateCommand.class);
addCommand("questrate", 4, QuestRateCommand.class);
addCommand("travelrate", 4, TravelRateCommand.class);
addCommand("fishrate", 4, FishingRateCommand.class);
addCommand("itemvac", 4, ItemVacCommand.class);
addCommand("forcevac", 4, ForceVacCommand.class);
addCommand("zakum", 4, ZakumCommand.class);
addCommand("horntail", 4, HorntailCommand.class);
addCommand("pinkbean", 4, PinkbeanCommand.class);
addCommand("pap", 4, PapCommand.class);
addCommand("pianus", 4, PianusCommand.class);
addCommand("cake", 4, CakeCommand.class);
addCommand("playernpc", 4, PlayerNpcCommand.class);
addCommand("playernpcremove", 4, PlayerNpcRemoveCommand.class);
addCommand("pnpc", 4, PnpcCommand.class);
addCommand("pnpcremove", 4, PnpcRemoveCommand.class);
addCommand("pmob", 4, PmobCommand.class);
addCommand("pmobremove", 4, PmobRemoveCommand.class);
commandsNameDesc.add(levelCommandsCursor);
}
private void registerLv5Commands(){
levelCommandsCursor = new Pair<>((List<String>) new ArrayList<String>(), (List<String>) new ArrayList<String>());
addCommand("debug", 5, DebugCommand.class);
addCommand("set", 5, SetCommand.class);
addCommand("showpackets", 5, ShowPacketsCommand.class);
addCommand("showmovelife", 5, ShowMoveLifeCommand.class);
addCommand("showsessions", 5, ShowSessionsCommand.class);
addCommand("iplist", 5, IpListCommand.class);
commandsNameDesc.add(levelCommandsCursor);
}
private void registerLv6Commands(){
levelCommandsCursor = new Pair<>((List<String>) new ArrayList<String>(), (List<String>) new ArrayList<String>());
addCommand("setgmlevel", 6, SetGmLevelCommand.class);
addCommand("warpworld", 6, WarpWorldCommand.class);
addCommand("saveall", 6, SaveAllCommand.class);
addCommand("dcall", 6, DCAllCommand.class);
addCommand("mapplayers", 6, MapPlayersCommand.class);
addCommand("getacc", 6, GetAccCommand.class);
addCommand("shutdown", 6, ShutdownCommand.class);
addCommand("clearquestcache", 6, ClearQuestCacheCommand.class);
addCommand("clearquest", 6, ClearQuestCommand.class);
addCommand("supplyratecoupon", 6, SupplyRateCouponCommand.class);
addCommand("spawnallpnpcs", 6, SpawnAllPNpcsCommand.class);
addCommand("eraseallpnpcs", 6, EraseAllPNpcsCommand.class);
addCommand("addchannel", 6, ServerAddChannelCommand.class);
addCommand("addworld", 6, ServerAddWorldCommand.class);
addCommand("removechannel", 6, ServerRemoveChannelCommand.class);
addCommand("removeworld", 6, ServerRemoveWorldCommand.class);
commandsNameDesc.add(levelCommandsCursor);
}
}

View File

@@ -0,0 +1,48 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleClient;
import client.command.Command;
import client.processor.action.BuybackProcessor;
public class BuyBackCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
if (params.length < 1) {
c.getPlayer().yellowMessage("Syntax: @buyback <info|now>");
return;
}
if (params[0].contentEquals("now")) {
BuybackProcessor.processBuyback(c);
} else {
c.getPlayer().showBuybackInfo();
}
}
}

View File

@@ -0,0 +1,42 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
public class ChangeLanguageCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
if (params.length < 1) {
c.getPlayer().yellowMessage("Syntax: !changel <0=ptb, 1=esp, 2=eng>");
return;
}
c.setLanguage(Integer.parseInt(params[0]));
}
}

View File

@@ -0,0 +1,45 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
import scripting.npc.NPCScriptManager;
import scripting.quest.QuestScriptManager;
import tools.MaplePacketCreator;
public class DisposeCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
NPCScriptManager.getInstance().dispose(c);
QuestScriptManager.getInstance().dispose(c);
c.announce(MaplePacketCreator.enableActions());
c.removeClickedNPC();
c.getPlayer().message("You've been disposed.");
}
}

View File

@@ -0,0 +1,45 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleClient;
import client.command.Command;
import config.YamlConfig;
public class DropLimitCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
int dropCount = c.getPlayer().getMap().getDroppedItemCount();
if(((float) dropCount) / YamlConfig.config.server.ITEM_LIMIT_ON_MAP < 0.75f) {
c.getPlayer().showHint("Current drop count: #b" + dropCount + "#k / #e" + YamlConfig.config.server.ITEM_LIMIT_ON_MAP + "#n", 300);
} else {
c.getPlayer().showHint("Current drop count: #r" + dropCount + "#k / #e" + YamlConfig.config.server.ITEM_LIMIT_ON_MAP + "#n", 300);
}
}
}

View File

@@ -0,0 +1,45 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
import net.server.coordinator.login.MapleLoginBypassCoordinator;
public class EnableAuthCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
if (c.tryacquireClient()) {
try {
MapleLoginBypassCoordinator.getInstance().unregisterLoginBypassEntry(c.getNibbleHWID(), c.getAccID());
} finally {
c.releaseClient();
}
}
}
}

View File

@@ -0,0 +1,38 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
public class EquipLvCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
c.getPlayer().showAllEquipFeatures();
}
}

View File

@@ -0,0 +1,66 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
import server.MapleItemInformationProvider;
import server.gachapon.MapleGachapon;
public class GachaCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleGachapon.Gachapon gacha = null;
String search = c.getPlayer().getLastCommandMessage();
String gachaName = "";
String [] names = {"Henesys", "Ellinia", "Perion", "Kerning City", "Sleepywood", "Mushroom Shrine", "Showa Spa Male", "Showa Spa Female", "New Leaf City", "Nautilus Harbor"};
int [] ids = {9100100, 9100101, 9100102, 9100103, 9100104, 9100105, 9100106, 9100107, 9100109, 9100117};
for (int i = 0; i < names.length; i++){
if (search.equalsIgnoreCase(names[i])){
gachaName = names[i];
gacha = MapleGachapon.Gachapon.getByNpcId(ids[i]);
}
}
if (gacha == null){
c.getPlayer().yellowMessage("Please use @gacha <name> where name corresponds to one of the below:");
for (String name : names){
c.getPlayer().yellowMessage(name);
}
return;
}
String talkStr = "The #b" + gachaName + "#k Gachapon contains the following items.\r\n\r\n";
for (int i = 0; i < 2; i++){
for (int id : gacha.getItems(i)){
talkStr += "-" + MapleItemInformationProvider.getInstance().getName(id) + "\r\n";
}
}
talkStr += "\r\nPlease keep in mind that there are items that are in all gachapons and are not listed here.";
c.getAbstractPlayerInteraction().npcTalk(9010000, talkStr);
}
}

View File

@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import net.server.Server;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Randomizer;
public class GmCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
String[] tips = {
"Please only use @gm in emergencies or to report somebody.",
"To report a bug or make a suggestion, use the forum.",
"Please do not use @gm to ask if a GM is online.",
"Do not ask if you can receive help, just state your issue.",
"Do not say 'I have a bug to report', just state it.",
};
MapleCharacter player = c.getPlayer();
if (params.length < 1 || params[0].length() < 3) { // #goodbye 'hi'
player.dropMessage(5, "Your message was too short. Please provide as much detail as possible.");
return;
}
String message = player.getLastCommandMessage();
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.sendYellowTip("[GM Message]:" + MapleCharacter.makeMapleReadable(player.getName()) + ": " + message));
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.serverNotice(1, message));
FilePrinter.printError(FilePrinter.COMMAND_GM, MapleCharacter.makeMapleReadable(player.getName()) + ": " + message);
player.dropMessage(5, "Your message '" + message + "' was sent to GMs.");
player.dropMessage(5, tips[Randomizer.nextInt(tips.length)]);
}
}

View File

@@ -0,0 +1,38 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleClient;
import client.command.Command;
public class HelpCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient client, String[] params) {
client.getAbstractPlayerInteraction().openNpc(9201143, "commands");
}
}

View File

@@ -0,0 +1,67 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import server.events.gm.MapleEvent;
import server.maps.FieldLimit;
public class JoinEventCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if(!FieldLimit.CANNOTMIGRATE.check(player.getMap().getFieldLimit())) {
MapleEvent event = c.getChannelServer().getEvent();
if(event != null) {
if(event.getMapId() != player.getMapId()) {
if(event.getLimit() > 0) {
player.saveLocation("EVENT");
if(event.getMapId() == 109080000 || event.getMapId() == 109060001)
player.setTeam(event.getLimit() % 2);
event.minusLimit();
player.saveLocationOnWarp();
player.changeMap(event.getMapId());
} else {
player.dropMessage(5, "The limit of players for the event has already been reached.");
}
} else {
player.dropMessage(5, "You are already in the event.");
}
} else {
player.dropMessage(5, "There is currently no event in progress.");
}
} else {
player.dropMessage(5, "You are currently in a map where you can't join an event.");
}
}
}

View File

@@ -0,0 +1,59 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
public class LeaveEventCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
int returnMap = player.getSavedLocation("EVENT");
if(returnMap != -1) {
if(player.getOla() != null) {
player.getOla().resetTimes();
player.setOla(null);
}
if(player.getFitness() != null) {
player.getFitness().resetTimes();
player.setFitness(null);
}
player.saveLocationOnWarp();
player.changeMap(returnMap);
if(c.getChannelServer().getEvent() != null) {
c.getChannelServer().getEvent().addLimit();
}
} else {
player.dropMessage(5, "You are not currently in an event.");
}
}
}

View File

@@ -0,0 +1,76 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Ronan
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleCharacter;
import client.MapleClient;
import config.YamlConfig;
import server.maps.MapleMap;
public class MapOwnerClaimCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
if (c.tryacquireClient()) {
try {
MapleCharacter chr = c.getPlayer();
if (YamlConfig.config.server.USE_MAP_OWNERSHIP_SYSTEM) {
if (chr.getEventInstance() == null) {
MapleMap map = chr.getMap();
if (map.countBosses() == 0) { // thanks Conrad for suggesting bosses prevent map leasing
MapleMap ownedMap = chr.getOwnedMap(); // thanks Conrad for suggesting not unlease a map as soon as player exits it
if (ownedMap != null) {
ownedMap.unclaimOwnership(chr);
if (map == ownedMap) {
chr.dropMessage(5, "This lawn is now free real estate.");
return;
}
}
if (map.claimOwnership(chr)) {
chr.dropMessage(5, "You have leased this lawn for a while, until you leave here or after 1 minute of inactivity.");
} else {
chr.dropMessage(5, "This lawn has already been leased by a player.");
}
} else {
chr.dropMessage(5, "This lawn is currently under a boss siege.");
}
} else {
chr.dropMessage(5, "This lawn cannot be leased.");
}
} else {
chr.dropMessage(5, "Feature unavailable.");
}
} finally {
c.releaseClient();
}
}
}
}

View File

@@ -0,0 +1,49 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import net.server.Server;
import net.server.channel.Channel;
public class OnlineCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
for (Channel ch : Server.getInstance().getChannelsFromWorld(player.getWorld())) {
player.yellowMessage("Players in Channel " + ch.getId() + ":");
for (MapleCharacter chr : ch.getPlayerStorage().getAllCharacters()) {
if (!chr.isGM()) {
player.message(" >> " + MapleCharacter.makeMapleReadable(chr.getName()) + " is at " + chr.getMap().getMapName() + ".");
}
}
}
}
}

View File

@@ -0,0 +1,47 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import net.server.Server;
import tools.MaplePacketCreator;
import java.util.List;
import tools.Pair;
public class RanksCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
List<Pair<String, Integer>> worldRanking = Server.getInstance().getWorldPlayerRanking(player.getWorld());
player.announce(MaplePacketCreator.showPlayerRanks(9010000, worldRanking));
}
}

View File

@@ -0,0 +1,50 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import config.YamlConfig;
public class RatesCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
// travel rates not applicable since it's intrinsically a server/environment rate rather than a character rate
String showMsg_ = "#eCHARACTER RATES#n" + "\r\n\r\n";
showMsg_ += "EXP Rate: #e#b" + player.getExpRate() + "x#k#n" + (player.hasNoviceExpRate() ? " - novice rate" : "") + "\r\n";
showMsg_ += "MESO Rate: #e#b" + player.getMesoRate() + "x#k#n" + "\r\n";
showMsg_ += "DROP Rate: #e#b" + player.getDropRate() + "x#k#n" + "\r\n";
showMsg_ += "BOSS DROP Rate: #e#b" + player.getBossDropRate() + "x#k#n" + "\r\n";
if(YamlConfig.config.server.USE_QUEST_RATE) showMsg_ += "QUEST Rate: #e#b" + c.getWorldServer().getQuestRate() + "x#k#n" + "\r\n";
player.showHint(showMsg_, 300);
}
}

View File

@@ -0,0 +1,38 @@
package client.command.commands.gm0;
import client.MapleCharacter;
import client.MapleClient;
import client.command.Command;
public class ReadPointsCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient client, String[] params) {
MapleCharacter player = client.getPlayer();
if (params.length > 2) {
player.yellowMessage("Syntax: @points (rp|vp|all)");
return;
} else if (params.length == 0) {
player.yellowMessage("RewardPoints: " + player.getRewardPoints() + " | "
+ "VotePoints: " + player.getClient().getVotePoints());
return;
}
switch (params[0]) {
case "rp":
player.yellowMessage("RewardPoints: " + player.getRewardPoints());
break;
case "vp":
player.yellowMessage("VotePoints: " + player.getClient().getVotePoints());
break;
default:
player.yellowMessage("RewardPoints: " + player.getRewardPoints() + " | "
+ "VotePoints: " + player.getClient().getVotePoints());
break;
}
}
}

View File

@@ -0,0 +1,53 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import net.server.Server;
import tools.FilePrinter;
import tools.MaplePacketCreator;
public class ReportBugCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.dropMessage(5, "Message too short and not sent. Please do @bug <bug>");
return;
}
String message = player.getLastCommandMessage();
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.sendYellowTip("[Bug]:" + MapleCharacter.makeMapleReadable(player.getName()) + ": " + message));
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.serverNotice(1, message));
FilePrinter.printError(FilePrinter.COMMAND_BUG, MapleCharacter.makeMapleReadable(player.getName()) + ": " + message);
player.dropMessage(5, "Your bug '" + message + "' was submitted successfully to our developers. Thank you!");
}
}

View File

@@ -0,0 +1,73 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import config.YamlConfig;
public class ShowRatesCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
String showMsg = "#eEXP RATE#n" + "\r\n";
showMsg += "World EXP Rate: #k" + c.getWorldServer().getExpRate() + "x#k" + "\r\n";
showMsg += "Player EXP Rate: #k" + player.getRawExpRate() + "x#k" + "\r\n";
if(player.getCouponExpRate() != 1) showMsg += "Coupon EXP Rate: #k" + player.getCouponExpRate() + "x#k" + "\r\n";
showMsg += "EXP Rate: #e#b" + player.getExpRate() + "x#k#n" + (player.hasNoviceExpRate() ? " - novice rate" : "") + "\r\n";
showMsg += "\r\n" + "#eMESO RATE#n" + "\r\n";
showMsg += "World MESO Rate: #k" + c.getWorldServer().getMesoRate() + "x#k" + "\r\n";
showMsg += "Player MESO Rate: #k" + player.getRawMesoRate() + "x#k" + "\r\n";
if(player.getCouponMesoRate() != 1) showMsg += "Coupon MESO Rate: #k" + player.getCouponMesoRate() + "x#k" + "\r\n";
showMsg += "MESO Rate: #e#b" + player.getMesoRate() + "x#k#n" + "\r\n";
showMsg += "\r\n" + "#eDROP RATE#n" + "\r\n";
showMsg += "World DROP Rate: #k" + c.getWorldServer().getDropRate() + "x#k" + "\r\n";
showMsg += "Player DROP Rate: #k" + player.getRawDropRate() + "x#k" + "\r\n";
if(player.getCouponDropRate() != 1) showMsg += "Coupon DROP Rate: #k" + player.getCouponDropRate() + "x#k" + "\r\n";
showMsg += "DROP Rate: #e#b" + player.getDropRate() + "x#k#n" + "\r\n";
showMsg += "\r\n" + "#eBOSS DROP RATE#n" + "\r\n";
showMsg += "World BOSS DROP Rate: #k" + c.getWorldServer().getBossDropRate() + "x#k" + "\r\n";
showMsg += "Player DROP Rate: #k" + player.getRawDropRate() + "x#k" + "\r\n";
if(player.getCouponDropRate() != 1) showMsg += "Coupon DROP Rate: #k" + player.getCouponDropRate() + "x#k" + "\r\n";
showMsg += "BOSS DROP Rate: #e#b" + player.getBossDropRate() + "x#k#n" + "\r\n";
if(YamlConfig.config.server.USE_QUEST_RATE) {
showMsg += "\r\n" + "#eQUEST RATE#n" + "\r\n";
showMsg += "World QUEST Rate: #e#b" + c.getWorldServer().getQuestRate() + "x#k#n" + "\r\n";
}
showMsg += "\r\n";
showMsg += "World TRAVEL Rate: #e#b" + c.getWorldServer().getTravelRate() + "x#k#n" + "\r\n";
player.showHint(showMsg, 300);
}
}

View File

@@ -0,0 +1,38 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleClient;
import client.command.Command;
public class StaffCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
c.getAbstractPlayerInteraction().openNpc(2010007, "credits");
}
}

View File

@@ -0,0 +1,56 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.MapleClient;
import client.command.Command;
import config.YamlConfig;
public class StatDexCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
int remainingAp = player.getRemainingAp();
int amount;
if (params.length > 0) {
try {
amount = Math.min(Integer.parseInt(params[0]), remainingAp);
} catch (NumberFormatException e) {
player.dropMessage("That is not a valid number!");
return;
}
} else {
amount = Math.min(remainingAp, YamlConfig.config.server.MAX_AP - player.getDex());
}
if (!player.assignDex(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + YamlConfig.config.server.MAX_AP + " and you have enough to distribute.");
}
}
}

View File

@@ -0,0 +1,56 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import config.YamlConfig;
public class StatIntCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
int remainingAp = player.getRemainingAp();
int amount;
if (params.length > 0) {
try {
amount = Math.min(Integer.parseInt(params[0]), remainingAp);
} catch (NumberFormatException e) {
player.dropMessage("That is not a valid number!");
return;
}
} else {
amount = Math.min(remainingAp, YamlConfig.config.server.MAX_AP - player.getInt());
}
if (!player.assignInt(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + YamlConfig.config.server.MAX_AP + " and you have enough to distribute.");
}
}
}

View File

@@ -0,0 +1,56 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleCharacter;
import client.MapleClient;
import client.command.Command;
import config.YamlConfig;
public class StatLukCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
int remainingAp = player.getRemainingAp();
int amount;
if (params.length > 0) {
try {
amount = Math.min(Integer.parseInt(params[0]), remainingAp);
} catch (NumberFormatException e) {
player.dropMessage("That is not a valid number!");
return;
}
} else {
amount = Math.min(remainingAp, YamlConfig.config.server.MAX_AP - player.getLuk());
}
if (!player.assignLuk(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + YamlConfig.config.server.MAX_AP + " and you have enough to distribute.");
}
}
}

View File

@@ -0,0 +1,56 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import config.YamlConfig;
public class StatStrCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
int remainingAp = player.getRemainingAp();
int amount;
if (params.length > 0) {
try {
amount = Math.min(Integer.parseInt(params[0]), remainingAp);
} catch (NumberFormatException e) {
player.dropMessage("That is not a valid number!");
return;
}
} else {
amount = Math.min(remainingAp, YamlConfig.config.server.MAX_AP - player.getStr());
}
if (!player.assignStr(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + YamlConfig.config.server.MAX_AP + " and you have enough to distribute.");
}
}
}

View File

@@ -0,0 +1,45 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.MapleClient;
import client.command.Command;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class TimeCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient client, String[] params) {
DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getDefault());
client.getPlayer().yellowMessage("Cosmic Server Time: " + dateFormat.format(new Date()));
}
}

View File

@@ -0,0 +1,44 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Ronan
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
public class ToggleExpCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
if (c.tryacquireClient()) {
try {
c.getPlayer().toggleExpGain(); // Vcoc's idea
} finally {
c.releaseClient();
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm0;
import client.command.Command;
import client.MapleClient;
import net.server.Server;
public class UptimeCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
long milliseconds = System.currentTimeMillis() - Server.uptime;
int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours = (int) ((milliseconds / (1000*60*60)) % 24);
int days = (int) ((milliseconds / (1000*60*60*24)));
c.getPlayer().yellowMessage("Server has been online for " + days + " days " + hours + " hours " + minutes + " minutes and " + seconds + " seconds.");
}
}

View File

@@ -0,0 +1,52 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm1;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import server.life.MapleMonster;
public class BossHpCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
for(MapleMonster monster : player.getMap().getAllMonsters()) {
if(monster != null && monster.isBoss() && monster.getHp() > 0) {
long percent = monster.getHp() * 100L / monster.getMaxHp();
String bar = "[";
for (int i = 0; i < 100; i++){
bar += i < percent ? "|" : ".";
}
bar += "]";
player.yellowMessage(monster.getName() + " (" + monster.getId() + ") has " + percent + "% HP left.");
player.yellowMessage("HP: " + bar);
}
}
}
}

View File

@@ -0,0 +1,46 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm1;
import client.MapleCharacter;
import client.SkillFactory;
import client.command.Command;
import client.MapleClient;
public class BuffMeCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
SkillFactory.getSkill(4101004).getEffect(SkillFactory.getSkill(4101004).getMaxLevel()).applyTo(player);
SkillFactory.getSkill(2311003).getEffect(SkillFactory.getSkill(2311003).getMaxLevel()).applyTo(player);
SkillFactory.getSkill(1301007).getEffect(SkillFactory.getSkill(1301007).getMaxLevel()).applyTo(player);
SkillFactory.getSkill(2301004).getEffect(SkillFactory.getSkill(2301004).getMaxLevel()).applyTo(player);
SkillFactory.getSkill(1005).getEffect(SkillFactory.getSkill(1005).getMaxLevel()).applyTo(player);
player.healHpMp();
}
}

View File

@@ -0,0 +1,136 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm1;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import constants.game.GameConstants;
import java.util.ArrayList;
import java.util.Collections;
import server.maps.MaplePortal;
import server.maps.FieldLimit;
import server.maps.MapleMap;
import server.maps.MapleMapFactory;
import server.maps.MapleMiniDungeonInfo;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class GotoCommand extends Command {
{
setDescription("");
List<Entry<String, Integer>> towns = new ArrayList<>(GameConstants.GOTO_TOWNS.entrySet());
sortGotoEntries(towns);
try {
// thanks shavit for noticing goto areas getting loaded from wz needlessly only for the name retrieval
for (Map.Entry<String, Integer> e : towns) {
GOTO_TOWNS_INFO += ("'" + e.getKey() + "' - #b" + (MapleMapFactory.loadPlaceName(e.getValue())) + "#k\r\n");
}
List<Entry<String, Integer>> areas = new ArrayList<>(GameConstants.GOTO_AREAS.entrySet());
sortGotoEntries(areas);
for (Map.Entry<String, Integer> e : areas) {
GOTO_AREAS_INFO += ("'" + e.getKey() + "' - #b" + (MapleMapFactory.loadPlaceName(e.getValue())) + "#k\r\n");
}
} catch (Exception e) {
e.printStackTrace();
GOTO_TOWNS_INFO = "(none)";
GOTO_AREAS_INFO = "(none)";
}
}
public static String GOTO_TOWNS_INFO = "";
public static String GOTO_AREAS_INFO = "";
private static void sortGotoEntries(List<Entry<String, Integer>> listEntries) {
Collections.sort(listEntries, new Comparator<Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2)
{
return e1.getValue().compareTo(e2.getValue());
}
});
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1){
String sendStr = "Syntax: #b@goto <map name>#k. Available areas:\r\n\r\n#rTowns:#k\r\n" + GOTO_TOWNS_INFO;
if (player.isGM()) {
sendStr += ("\r\n#rAreas:#k\r\n" + GOTO_AREAS_INFO);
}
player.getAbstractPlayerInteraction().npcTalk(9000020, sendStr);
return;
}
if (!player.isAlive()) {
player.dropMessage(1, "This command cannot be used when you're dead.");
return;
}
if (!player.isGM()) {
if (player.getEventInstance() != null || MapleMiniDungeonInfo.isDungeonMap(player.getMapId()) || FieldLimit.CANNOTMIGRATE.check(player.getMap().getFieldLimit())) {
player.dropMessage(1, "This command can not be used in this map.");
return;
}
}
HashMap<String, Integer> gotomaps;
if (player.isGM()) {
gotomaps = new HashMap<>(GameConstants.GOTO_AREAS); // distinct map registry for GM/users suggested thanks to Vcoc
gotomaps.putAll(GameConstants.GOTO_TOWNS); // thanks Halcyon (UltimateMors) for pointing out duplicates on listed entries functionality
} else {
gotomaps = GameConstants.GOTO_TOWNS;
}
if (gotomaps.containsKey(params[0])) {
MapleMap target = c.getChannelServer().getMapFactory().getMap(gotomaps.get(params[0]));
// expedition issue with this command detected thanks to Masterrulax
MaplePortal targetPortal = target.getRandomPlayerSpawnpoint();
player.saveLocationOnWarp();
player.changeMap(target, targetPortal);
} else {
// detailed info on goto available areas suggested thanks to Vcoc
String sendStr = "Area '#r" + params[0] + "#k' is not available. Available areas:\r\n\r\n#rTowns:#k" + GOTO_TOWNS_INFO;
if (player.isGM()) {
sendStr += ("\r\n#rAreas:#k\r\n" + GOTO_AREAS_INFO);
}
player.getAbstractPlayerInteraction().npcTalk(9000020, sendStr);
}
}
}

View File

@@ -0,0 +1,46 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm1;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import server.life.MapleMonster;
public class MobHpCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
for(MapleMonster monster : player.getMap().getAllMonsters()) {
if (monster != null && monster.getHp() > 0) {
player.yellowMessage(monster.getName() + " (" + monster.getId() + ") has " + monster.getHp() + " / " + monster.getMaxHp() + " HP.");
}
}
}
}

View File

@@ -0,0 +1,77 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm1;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import server.MapleItemInformationProvider;
import server.life.MapleMonsterInformationProvider;
import server.life.MonsterDropEntry;
import tools.Pair;
import java.util.Iterator;
public class WhatDropsFromCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.dropMessage(5, "Please do @whatdropsfrom <monster name>");
return;
}
String monsterName = player.getLastCommandMessage();
String output = "";
int limit = 3;
Iterator<Pair<Integer, String>> listIterator = MapleMonsterInformationProvider.getMobsIDsFromName(monsterName).iterator();
for (int i = 0; i < limit; i++) {
if(listIterator.hasNext()) {
Pair<Integer, String> data = listIterator.next();
int mobId = data.getLeft();
String mobName = data.getRight();
output += mobName + " drops the following items:\r\n\r\n";
for (MonsterDropEntry drop : MapleMonsterInformationProvider.getInstance().retrieveDrop(mobId)){
try {
String name = MapleItemInformationProvider.getInstance().getName(drop.itemId);
if (name == null || name.equals("null") || drop.chance == 0){
continue;
}
float chance = Math.max(1000000 / drop.chance / (!MapleMonsterInformationProvider.getInstance().isBoss(mobId) ? player.getDropRate() : player.getBossDropRate()), 1);
output += "- " + name + " (1/" + (int) chance + ")\r\n";
} catch (Exception ex){
ex.printStackTrace();
continue;
}
}
output += "\r\n";
}
}
c.getAbstractPlayerInteraction().npcTalk(9010000, output);
}
}

View File

@@ -0,0 +1,97 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm1;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import server.MapleItemInformationProvider;
import server.life.MapleMonsterInformationProvider;
import tools.DatabaseConnection;
import tools.Pair;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Iterator;
public class WhoDropsCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.dropMessage(5, "Please do @whodrops <item name>");
return;
}
if (c.tryacquireClient()) {
try {
String searchString = player.getLastCommandMessage();
String output = "";
Iterator<Pair<Integer, String>> listIterator = MapleItemInformationProvider.getInstance().getItemDataByName(searchString).iterator();
if(listIterator.hasNext()) {
int count = 1;
while(listIterator.hasNext() && count <= 3) {
Pair<Integer, String> data = listIterator.next();
output += "#b" + data.getRight() + "#k is dropped by:\r\n";
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT dropperid FROM drop_data WHERE itemid = ? LIMIT 50");
ps.setInt(1, data.getLeft());
ResultSet rs = ps.executeQuery();
while(rs.next()) {
String resultName = MapleMonsterInformationProvider.getInstance().getMobNameFromId(rs.getInt("dropperid"));
if (resultName != null) {
output += resultName + ", ";
}
}
rs.close();
ps.close();
con.close();
} catch (Exception e) {
player.dropMessage(6, "There was a problem retrieving the required data. Please try again.");
e.printStackTrace();
return;
}
output += "\r\n\r\n";
count++;
}
} else {
player.dropMessage(5, "The item you searched for doesn't exist.");
return;
}
c.getAbstractPlayerInteraction().npcTalk(9010000, output);
} finally {
c.releaseClient();
}
} else {
player.dropMessage(5, "Please wait a while for your request to be processed.");
}
}
}

View File

@@ -0,0 +1,63 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import config.YamlConfig;
public class ApCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !ap [<playername>] <newap>");
return;
}
if (params.length < 2) {
int newAp = Integer.parseInt(params[0]);
if (newAp < 0) newAp = 0;
else if (newAp > YamlConfig.config.server.MAX_AP) newAp = YamlConfig.config.server.MAX_AP;
player.changeRemainingAp(newAp, false);
} else {
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
int newAp = Integer.parseInt(params[1]);
if (newAp < 0) newAp = 0;
else if (newAp > YamlConfig.config.server.MAX_AP) newAp = YamlConfig.config.server.MAX_AP;
victim.changeRemainingAp(newAp, false);
} else {
player.message("Player '" + params[0] + "' could not be found.");
}
}
}
}

View File

@@ -0,0 +1,53 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import net.server.Server;
import server.life.MapleLifeFactory;
import tools.MaplePacketCreator;
public class BombCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length > 0) {
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
victim.getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(9300166), victim.getPosition());
Server.getInstance().broadcastGMMessage(c.getWorld(), MaplePacketCreator.serverNotice(5, player.getName() + " used !bomb on " + victim.getName()));
} else {
player.message("Player '" + params[0] + "' could not be found on this world.");
}
} else {
player.getMap().spawnMonsterOnGroundBelow(MapleLifeFactory.getMonster(9300166), player.getPosition());
}
}
}

View File

@@ -0,0 +1,49 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.Skill;
import client.SkillFactory;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class BuffCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !buff <buffid>");
return;
}
int skillid = Integer.parseInt(params[0]);
Skill skill = SkillFactory.getSkill(skillid);
if (skill != null) skill.getEffect(skill.getMaxLevel()).applyTo(player);
}
}

View File

@@ -0,0 +1,46 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.SkillFactory;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class BuffMapCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
SkillFactory.getSkill(9101001).getEffect(SkillFactory.getSkill(9101001).getMaxLevel()).applyTo(player, true);
SkillFactory.getSkill(9101002).getEffect(SkillFactory.getSkill(9101002).getMaxLevel()).applyTo(player, true);
SkillFactory.getSkill(9101003).getEffect(SkillFactory.getSkill(9101003).getMaxLevel()).applyTo(player, true);
SkillFactory.getSkill(9101008).getEffect(SkillFactory.getSkill(9101008).getMaxLevel()).applyTo(player, true);
SkillFactory.getSkill(1005).getEffect(SkillFactory.getSkill(1005).getMaxLevel()).applyTo(player, true);
}
}

View File

@@ -0,0 +1,41 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class ClearDropsCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
player.getMap().clearDrops(player);
player.dropMessage(5, "Cleared dropped items");
}
}

View File

@@ -0,0 +1,56 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.maps.SavedLocationType;
public class ClearSavedLocationsCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer(), victim;
if (params.length > 0) {
victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim == null) {
player.message("Player '" + params[0] + "' could not be found.");
return;
}
} else {
victim = c.getPlayer();
}
for (SavedLocationType type : SavedLocationType.values()) {
victim.clearSavedLocation(type);
}
player.message("Cleared " + params[0] + "'s saved locations.");
}
}

View File

@@ -0,0 +1,130 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import client.inventory.manipulator.MapleInventoryManipulator;
public class ClearSlotCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !clearslot <all, equip, use, setup, etc or cash.>");
return;
}
String type = params[0];
switch (type) {
case "all":
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (byte) i, tempItem.getQuantity(), false, false);
}
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.USE).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, (byte) i, tempItem.getQuantity(), false, false);
}
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.ETC).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.ETC, (byte) i, tempItem.getQuantity(), false, false);
}
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.SETUP).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.SETUP, (byte) i, tempItem.getQuantity(), false, false);
}
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.CASH).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.CASH, (byte) i, tempItem.getQuantity(), false, false);
}
player.yellowMessage("All Slots Cleared.");
break;
case "equip":
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (byte) i, tempItem.getQuantity(), false, false);
}
player.yellowMessage("Equipment Slot Cleared.");
break;
case "use":
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.USE).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, (byte) i, tempItem.getQuantity(), false, false);
}
player.yellowMessage("Use Slot Cleared.");
break;
case "setup":
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.SETUP).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.SETUP, (byte) i, tempItem.getQuantity(), false, false);
}
player.yellowMessage("Set-Up Slot Cleared.");
break;
case "etc":
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.ETC).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.ETC, (byte) i, tempItem.getQuantity(), false, false);
}
player.yellowMessage("ETC Slot Cleared.");
break;
case "cash":
for (int i = 0; i < 101; i++) {
Item tempItem = c.getPlayer().getInventory(MapleInventoryType.CASH).getItem((byte) i);
if (tempItem == null)
continue;
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.CASH, (byte) i, tempItem.getQuantity(), false, false);
}
player.yellowMessage("Cash Slot Cleared.");
break;
default:
player.yellowMessage("Slot" + type + " does not exist!");
break;
}
}
}

View File

@@ -0,0 +1,65 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class DcCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !dc <playername>");
return;
}
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim == null) {
victim = c.getChannelServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim == null) {
victim = player.getMap().getCharacterByName(params[0]);
if (victim != null) {
try {//sometimes bugged because the map = null
victim.getClient().disconnect(true, false);
player.getMap().removePlayer(victim);
} catch (Exception e) {
e.printStackTrace();
}
} else {
return;
}
}
}
if (player.gmLevel() < victim.gmLevel()) {
victim = player;
}
victim.getClient().disconnect(false, false);
}
}

View File

@@ -0,0 +1,44 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.SkillFactory;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class EmpowerMeCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
final int[] array = {2311003, 2301004, 1301007, 4101004, 2001002, 1101007, 1005, 2301003, 5121009, 1111002, 4111001, 4111002, 4211003, 4211005, 1321000, 2321004, 3121002};
for (int i : array) {
SkillFactory.getSkill(i).getEffect(SkillFactory.getSkill(i).getMaxLevel()).applyTo(player);
}
}
}

View File

@@ -0,0 +1,38 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package client.command.commands.gm2;
import client.MapleClient;
import client.command.Command;
/**
*
* @author Ronan
*/
public class GachaListCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
c.getAbstractPlayerInteraction().openNpc(10000, "gachaponInfo");
}
}

View File

@@ -0,0 +1,40 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.MapleShopFactory;
public class GmShopCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleShopFactory.getInstance().getShop(1337).sendShop(c);
}
}

View File

@@ -0,0 +1,41 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class HealCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
player.healHpMp();
}
}

View File

@@ -0,0 +1,42 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.SkillFactory;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class HideCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
SkillFactory.getSkill(9101004).getEffect(SkillFactory.getSkill(9101004).getMaxLevel()).applyTo(player);
}
}

View File

@@ -0,0 +1,105 @@
package client.command.commands.gm2;
import client.MapleCharacter;
import client.MapleClient;
import client.command.Command;
import tools.exceptions.IdTypeNotSupportedException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import server.ThreadManager;
public class IdCommand extends Command {
{
setDescription("");
}
private final Map<String, String> handbookDirectory = new HashMap<>();
private final Map<String, HashMap<String, String>> itemMap = new HashMap<>();
public IdCommand() {
handbookDirectory.put("map", "handbook/Map.txt");
handbookDirectory.put("etc", "handbook/Etc.txt");
handbookDirectory.put("npc", "handbook/NPC.txt");
handbookDirectory.put("use", "handbook/Use.txt");
handbookDirectory.put("weapon", "handbook/Equip/Weapon.txt"); // TODO add more into this
}
@Override
public void execute(MapleClient client, final String[] params) {
final MapleCharacter player = client.getPlayer();
if (params.length < 2) {
player.yellowMessage("Syntax: !id <type> <query>");
return;
}
final String queryItem = joinStringArr(Arrays.copyOfRange(params, 1, params.length), " ");
player.yellowMessage("Querying for entry... May take some time... Please try to refine your search.");
Runnable queryRunnable = new Runnable() {
@Override
public void run() {
try {
populateIdMap(params[0].toLowerCase());
Map<String, String> resultList = fetchResults(itemMap.get(params[0]), queryItem);
StringBuilder sb = new StringBuilder();
if (resultList.size() > 0) {
int count = 0;
for (Map.Entry<String, String> entry: resultList.entrySet()) {
sb.append(String.format("Id for %s is: #b%s#k", entry.getKey(), entry.getValue()) + "\r\n");
if (++count > 100) {
break;
}
}
sb.append(String.format("Results found: #r%d#k | Returned: #b%d#k/100 | Refine search query to improve time.", resultList.size(), count) + "\r\n");
player.getAbstractPlayerInteraction().npcTalk(9010000, sb.toString());
} else {
player.yellowMessage(String.format("Id not found for item: %s, of type: %s.", queryItem, params[0]));
}
} catch (IdTypeNotSupportedException e) {
player.yellowMessage("Your query type is not supported.");
} catch (IOException e) {
player.yellowMessage("Error reading file, please contact your administrator.");
}
}
};
ThreadManager.getInstance().newTask(queryRunnable);
}
private void populateIdMap(String type) throws IdTypeNotSupportedException, IOException {
if (!handbookDirectory.containsKey(type)) {
throw new IdTypeNotSupportedException();
}
itemMap.put(type, new HashMap<String, String>());
BufferedReader reader = new BufferedReader(new FileReader(handbookDirectory.get(type)));
String line;
while ((line = reader.readLine()) != null) {
String[] row = line.split(" - ", 2);
if (row.length == 2) {
itemMap.get(type).put(row[1].toLowerCase(), row[0]);
}
}
}
private String joinStringArr(String[] arr, String separator) {
if (null == arr || 0 == arr.length) return "";
StringBuilder sb = new StringBuilder(256);
sb.append(arr[0]);
for (int i = 1; i < arr.length; i++) sb.append(separator).append(arr[i]);
return sb.toString();
}
private Map<String, String> fetchResults(Map<String, String> queryMap, String queryItem) {
Map<String, String> results = new HashMap<>();
for (String item: queryMap.keySet()) {
if (item.indexOf(queryItem) != -1) {
results.put(item, queryMap.get(item));
}
}
return results;
}
}

View File

@@ -0,0 +1,88 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import client.inventory.MaplePet;
import client.inventory.manipulator.MapleInventoryManipulator;
import config.YamlConfig;
import constants.inventory.ItemConstants;
import server.MapleItemInformationProvider;
public class ItemCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !item <itemid> <quantity>");
return;
}
int itemId = Integer.parseInt(params[0]);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if(ii.getName(itemId) == null) {
player.yellowMessage("Item id '" + params[0] + "' does not exist.");
return;
}
short quantity = 1;
if(params.length >= 2) quantity = Short.parseShort(params[1]);
if (YamlConfig.config.server.BLOCK_GENERATE_CASH_ITEM && ii.isCash(itemId)) {
player.yellowMessage("You cannot create a cash item with this command.");
return;
}
if (ItemConstants.isPet(itemId)) {
if (params.length >= 2){ // thanks to istreety & TacoBell
quantity = 1;
long days = Math.max(1, Integer.parseInt(params[1]));
long expiration = System.currentTimeMillis() + (days * 24 * 60 * 60 * 1000);
int petid = MaplePet.createPet(itemId);
MapleInventoryManipulator.addById(c, itemId, quantity, player.getName(), petid, expiration);
return;
} else {
player.yellowMessage("Pet Syntax: !item <itemid> <expiration>");
return;
}
}
short flag = 0;
if(player.gmLevel() < 3) {
flag |= ItemConstants.ACCOUNT_SHARING;
flag |= ItemConstants.UNTRADEABLE;
}
MapleInventoryManipulator.addById(c, itemId, quantity, player.getName(), -1, flag, -1);
}
}

View File

@@ -0,0 +1,116 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import config.YamlConfig;
import constants.inventory.ItemConstants;
import server.MapleItemInformationProvider;
public class ItemDropCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !drop <itemid> <quantity>");
return;
}
int itemId = Integer.parseInt(params[0]);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
if(ii.getName(itemId) == null) {
player.yellowMessage("Item id '" + params[0] + "' does not exist.");
return;
}
short quantity = 1;
if(params.length >= 2) quantity = Short.parseShort(params[1]);
if (YamlConfig.config.server.BLOCK_GENERATE_CASH_ITEM && ii.isCash(itemId)) {
player.yellowMessage("You cannot create a cash item with this command.");
return;
}
if (ItemConstants.isPet(itemId)) {
if (params.length >= 2){ // thanks to istreety & TacoBell
quantity = 1;
long days = Math.max(1, Integer.parseInt(params[1]));
long expiration = System.currentTimeMillis() + (days * 24 * 60 * 60 * 1000);
int petid = MaplePet.createPet(itemId);
Item toDrop = new Item(itemId, (short) 0, quantity, petid);
toDrop.setExpiration(expiration);
toDrop.setOwner("");
if(player.gmLevel() < 3) {
short f = toDrop.getFlag();
f |= ItemConstants.ACCOUNT_SHARING;
f |= ItemConstants.UNTRADEABLE;
f |= ItemConstants.SANDBOX;
toDrop.setFlag(f);
toDrop.setOwner("TRIAL-MODE");
}
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), toDrop, c.getPlayer().getPosition(), true, true);
return;
} else {
player.yellowMessage("Pet Syntax: !drop <itemid> <expiration>");
return;
}
}
Item toDrop;
if (ItemConstants.getInventoryType(itemId) == MapleInventoryType.EQUIP) {
toDrop = ii.getEquipById(itemId);
} else {
toDrop = new Item(itemId, (short) 0, quantity);
}
toDrop.setOwner(player.getName());
if(player.gmLevel() < 3) {
short f = toDrop.getFlag();
f |= ItemConstants.ACCOUNT_SHARING;
f |= ItemConstants.UNTRADEABLE;
f |= ItemConstants.SANDBOX;
toDrop.setFlag(f);
toDrop.setOwner("TRIAL-MODE");
}
c.getPlayer().getMap().spawnItemDrop(c.getPlayer(), c.getPlayer(), toDrop, c.getPlayer().getPosition(), true, true);
}
}

View File

@@ -0,0 +1,74 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.maps.MaplePortal;
import server.maps.MapleMap;
public class JailCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !jail <playername> [<minutes>]");
return;
}
int minutesJailed = 5;
if (params.length >= 2) {
minutesJailed = Integer.valueOf(params[1]);
if (minutesJailed <= 0) {
player.yellowMessage("Syntax: !jail <playername> [<minutes>]");
return;
}
}
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
victim.addJailExpirationTime(minutesJailed * 60 * 1000);
int mapid = 300000012;
if (victim.getMapId() != mapid) { // those gone to jail won't be changing map anyway
MapleMap target = c.getChannelServer().getMapFactory().getMap(mapid);
MaplePortal targetPortal = target.getPortal(0);
victim.saveLocationOnWarp();
victim.changeMap(target, targetPortal);
player.message(victim.getName() + " was jailed for " + minutesJailed + " minutes.");
} else {
player.message(victim.getName() + "'s time in jail has been extended for " + minutesJailed + " minutes.");
}
} else {
player.message("Player '" + params[0] + "' could not be found.");
}
}
}

View File

@@ -0,0 +1,67 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.MapleJob;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class JobCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length == 1) {
int jobid = Integer.parseInt(params[0]);
if (jobid < 0 || jobid >= 2200) {
player.message("Jobid " + jobid + " is not available.");
return;
}
player.changeJob(MapleJob.getById(jobid));
player.equipChanged();
} else if (params.length == 2) {
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
int jobid = Integer.parseInt(params[1]);
if (jobid < 0 || jobid >= 2200) {
player.message("Jobid " + jobid + " is not available.");
return;
}
victim.changeJob(MapleJob.getById(jobid));
player.equipChanged();
} else {
player.message("Player '" + params[0] + "' could not be found.");
}
} else {
player.message("Syntax: !job <job id> <opt: IGN of another person>");
}
}
}

View File

@@ -0,0 +1,53 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import config.YamlConfig;
public class LevelCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !level <newlevel>");
return;
}
player.loseExp(player.getExp(), false, false);
player.setLevel(Math.min(Integer.parseInt(params[0]), player.getMaxClassLevel()) - 1);
player.resetPlayerRates();
if (YamlConfig.config.server.USE_ADD_RATES_BY_LEVEL) player.setPlayerRates();
player.setWorldRates();
player.levelUp(false);
}
}

View File

@@ -0,0 +1,46 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class LevelProCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !levelpro <newlevel>");
return;
}
while (player.getLevel() < Math.min(player.getMaxClassLevel(), Integer.parseInt(params[0]))) {
player.levelUp(false);
}
}
}

View File

@@ -0,0 +1,51 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Resinate
*/
package client.command.commands.gm2;
import client.MapleClient;
import client.command.Command;
import java.util.Arrays;
import java.util.List;
import server.maps.MapleMapItem;
import server.maps.MapleMapObject;
import server.maps.MapleMapObjectType;
public class LootCommand extends Command {
{
setDescription("Loots all items that belong to you.");
}
@Override
public void execute(MapleClient c, String[] params) {
List<MapleMapObject> items = c.getPlayer().getMap().getMapObjectsInRange(c.getPlayer().getPosition(), Double.POSITIVE_INFINITY, Arrays.asList(MapleMapObjectType.ITEM));
for (MapleMapObject item : items) {
MapleMapItem mapItem = (MapleMapItem) item;
if (mapItem.getOwnerId() == c.getPlayer().getId() || mapItem.getOwnerId() == c.getPlayer().getPartyId()) {
c.getPlayer().pickupItem(mapItem);
}
}
}
}

View File

@@ -0,0 +1,61 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.*;
import client.command.Command;
import provider.MapleData;
import provider.MapleDataProviderFactory;
import java.io.File;
public class MaxSkillCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {
try {
Skill skill = SkillFactory.getSkill(Integer.parseInt(skill_.getName()));
player.changeSkillLevel(skill, (byte) skill.getMaxLevel(), skill.getMaxLevel(), -1);
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
break;
} catch (NullPointerException npe) { }
}
if (player.getJob().isA(MapleJob.ARAN1) || player.getJob().isA(MapleJob.LEGEND)) {
Skill skill = SkillFactory.getSkill(5001005);
player.changeSkillLevel(skill, (byte) -1, -1, -1);
} else {
Skill skill = SkillFactory.getSkill(21001001);
player.changeSkillLevel(skill, (byte) -1, -1, -1);
}
player.yellowMessage("Skills maxed out.");
}
}

View File

@@ -0,0 +1,52 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.MapleStat;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import config.YamlConfig;
public class MaxStatCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
player.loseExp(player.getExp(), false, false);
player.setLevel(255);
player.resetPlayerRates();
if (YamlConfig.config.server.USE_ADD_RATES_BY_LEVEL) player.setPlayerRates();
player.setWorldRates();
player.updateStrDexIntLuk(Short.MAX_VALUE);
player.setFame(13337);
player.updateMaxHpMaxMp(30000, 30000);
player.updateSingleStat(MapleStat.LEVEL, 255);
player.updateSingleStat(MapleStat.FAME, 13337);
player.yellowMessage("Stats maxed out.");
}
}

View File

@@ -0,0 +1,57 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.maps.MapleMap;
public class ReachCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !reach <playername>");
return;
}
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null && victim.isLoggedin()) {
if (player.getClient().getChannel() != victim.getClient().getChannel()) {
player.dropMessage(5, "Player '" + victim.getName() + "' is at channel " + victim.getClient().getChannel() + ".");
} else {
MapleMap map = victim.getMap();
player.saveLocationOnWarp();
player.forceChangeMap(map, map.findClosestPortal(victim.getPosition()));
}
} else {
player.dropMessage(6, "Unknown player.");
}
}
}

View File

@@ -0,0 +1,60 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.MapleCharacter;
import client.command.Command;
import client.MapleClient;
import client.inventory.Item;
import client.inventory.MapleInventoryType;
import constants.inventory.ItemConstants;
import server.MapleItemInformationProvider;
public class RechargeCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
for (Item torecharge : c.getPlayer().getInventory(MapleInventoryType.USE).list()) {
if (ItemConstants.isThrowingStar(torecharge.getItemId())){
torecharge.setQuantity(ii.getSlotMax(c, torecharge.getItemId()));
c.getPlayer().forceUpdateItem(torecharge);
} else if (ItemConstants.isArrow(torecharge.getItemId())){
torecharge.setQuantity(ii.getSlotMax(c, torecharge.getItemId()));
c.getPlayer().forceUpdateItem(torecharge);
} else if (ItemConstants.isBullet(torecharge.getItemId())){
torecharge.setQuantity(ii.getSlotMax(c, torecharge.getItemId()));
c.getPlayer().forceUpdateItem(torecharge);
} else if (ItemConstants.isConsumable(torecharge.getItemId())){
torecharge.setQuantity(ii.getSlotMax(c, torecharge.getItemId()));
c.getPlayer().forceUpdateItem(torecharge);
}
}
player.dropMessage(5, "USE Recharged.");
}
}

View File

@@ -0,0 +1,62 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.*;
import client.command.Command;
import provider.MapleData;
import provider.MapleDataProviderFactory;
import java.io.File;
public class ResetSkillCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
for (MapleData skill_ : MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz")).getData("Skill.img").getChildren()) {
try {
Skill skill = SkillFactory.getSkill(Integer.parseInt(skill_.getName()));
player.changeSkillLevel(skill, (byte) 0, skill.getMaxLevel(), -1);
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
break;
} catch (NullPointerException npe) {
}
}
if (player.getJob().isA(MapleJob.ARAN1) || player.getJob().isA(MapleJob.LEGEND)) {
Skill skill = SkillFactory.getSkill(5001005);
player.changeSkillLevel(skill, (byte) -1, -1, -1);
} else {
Skill skill = SkillFactory.getSkill(21001001);
player.changeSkillLevel(skill, (byte) -1, -1, -1);
}
player.yellowMessage("Skills reseted.");
}
}

View File

@@ -0,0 +1,141 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import provider.MapleData;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import server.MapleItemInformationProvider;
import server.quest.MapleQuest;
import tools.MaplePacketCreator;
import tools.Pair;
import java.io.File;
import java.util.List;
public class SearchCommand extends Command {
private static MapleData npcStringData;
private static MapleData mobStringData;
private static MapleData skillStringData;
private static MapleData mapStringData;
{
setDescription("");
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File("wz/String.wz"));
npcStringData = dataProvider.getData("Npc.img");
mobStringData = dataProvider.getData("Mob.img");
skillStringData = dataProvider.getData("Skill.img");
mapStringData = dataProvider.getData("Map.img");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 2) {
player.yellowMessage("Syntax: !search <type> <name>");
return;
}
StringBuilder sb = new StringBuilder();
String search = joinStringFrom(params,1);
long start = System.currentTimeMillis();//for the lulz
MapleData data = null;
if (!params[0].equalsIgnoreCase("ITEM")) {
int searchType = 0;
if (params[0].equalsIgnoreCase("NPC")) {
data = npcStringData;
} else if (params[0].equalsIgnoreCase("MOB") || params[0].equalsIgnoreCase("MONSTER")) {
data = mobStringData;
} else if (params[0].equalsIgnoreCase("SKILL")) {
data = skillStringData;
} else if (params[0].equalsIgnoreCase("MAP")) {
data = mapStringData;
searchType = 1;
} else if (params[0].equalsIgnoreCase("QUEST")) {
data = mapStringData;
searchType = 2;
} else {
sb.append("#bInvalid search.\r\nSyntax: '!search [type] [name]', where [type] is MAP, QUEST, NPC, ITEM, MOB, or SKILL.");
}
if (data != null) {
String name;
if (searchType == 0) {
for (MapleData searchData : data.getChildren()) {
name = MapleDataTool.getString(searchData.getChildByPath("name"), "NO-NAME");
if (name.toLowerCase().contains(search.toLowerCase())) {
sb.append("#b").append(Integer.parseInt(searchData.getName())).append("#k - #r").append(name).append("\r\n");
}
}
} else if (searchType == 1) {
String mapName, streetName;
for (MapleData searchDataDir : data.getChildren()) {
for (MapleData searchData : searchDataDir.getChildren()) {
mapName = MapleDataTool.getString(searchData.getChildByPath("mapName"), "NO-NAME");
streetName = MapleDataTool.getString(searchData.getChildByPath("streetName"), "NO-NAME");
if (mapName.toLowerCase().contains(search.toLowerCase()) || streetName.toLowerCase().contains(search.toLowerCase())) {
sb.append("#b").append(Integer.parseInt(searchData.getName())).append("#k - #r").append(streetName).append(" - ").append(mapName).append("\r\n");
}
}
}
} else {
for (MapleQuest mq : MapleQuest.getMatchedQuests(search)) {
sb.append("#b").append(mq.getId()).append("#k - #r");
String parentName = mq.getParentName();
if (!parentName.isEmpty()) {
sb.append(parentName).append(" - ");
}
sb.append(mq.getName()).append("\r\n");
}
}
}
} else {
for (Pair<Integer, String> itemPair : MapleItemInformationProvider.getInstance().getAllItems()) {
if (sb.length() < 32654) {//ohlol
if (itemPair.getRight().toLowerCase().contains(search.toLowerCase())) {
sb.append("#b").append(itemPair.getLeft()).append("#k - #r").append(itemPair.getRight()).append("\r\n");
}
} else {
sb.append("#bCouldn't load all items, there are too many results.\r\n");
break;
}
}
}
if (sb.length() == 0) {
sb.append("#bNo ").append(params[0].toLowerCase()).append("s found.\r\n");
}
sb.append("\r\n#kLoaded within ").append((double) (System.currentTimeMillis() - start) / 1000).append(" seconds.");//because I can, and it's free
c.getAbstractPlayerInteraction().npcTalk(9010000, sb.toString());
}
}

View File

@@ -0,0 +1,54 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Ronan
*/
package client.command.commands.gm2;
import client.*;
import client.command.Command;
public class SetSlotCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !setslot <newlevel>");
return;
}
int slots = (Integer.parseInt(params[0]) / 4) * 4;
for (int i = 1; i < 5; i++) {
int curSlots = player.getSlots(i);
if (slots <= -curSlots) {
continue;
}
player.gainSlots(i, slots - curSlots, true);
}
player.yellowMessage("Slots updated.");
}
}

View File

@@ -0,0 +1,52 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class SetStatCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !setstat <newstat>");
return;
}
try {
int x = Integer.parseInt(params[0]);
if (x > Short.MAX_VALUE) x = Short.MAX_VALUE;
else if (x < 4) x = 4; // thanks Vcoc for pointing the minimal allowed stat value here
player.updateStrDexIntLuk(x);
} catch (NumberFormatException nfe) {}
}
}

View File

@@ -0,0 +1,65 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import config.YamlConfig;
public class SpCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !sp [<playername>] <newsp>");
return;
}
if (params.length == 1) {
int newSp = Integer.parseInt(params[0]);
if (newSp < 0) newSp = 0;
else if (newSp > YamlConfig.config.server.MAX_AP) newSp = YamlConfig.config.server.MAX_AP;
player.updateRemainingSp(newSp);
} else {
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
int newSp = Integer.parseInt(params[1]);
if (newSp < 0) newSp = 0;
else if (newSp > YamlConfig.config.server.MAX_AP) newSp = YamlConfig.config.server.MAX_AP;
victim.updateRemainingSp(newSp);
player.dropMessage(5, "SP given.");
} else {
player.message("Player '" + params[0] + "' could not be found.");
}
}
}
}

View File

@@ -0,0 +1,82 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.maps.MapleMap;
import net.server.Server;
import net.server.channel.Channel;
public class SummonCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !warphere <playername>");
return;
}
MapleCharacter victim = c.getChannelServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim == null) {
//If victim isn't on current channel, loop all channels on current world.
for (Channel ch : Server.getInstance().getChannelsFromWorld(c.getWorld())) {
victim = ch.getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
break;//We found the person, no need to continue the loop.
}
}
}
if (victim != null) {
if (!victim.isLoggedinWorld()) {
player.dropMessage(6, "Player currently not logged in or unreachable.");
return;
}
if (player.getClient().getChannel() != victim.getClient().getChannel()) {//And then change channel if needed.
victim.dropMessage("Changing channel, please wait a moment.");
victim.getClient().changeChannel(player.getClient().getChannel());
}
try {
for (int i = 0; i < 7; i++) { // poll for a while until the player reconnects
if (victim.isLoggedinWorld()) break;
Thread.sleep(1777);
}
} catch (InterruptedException e) {}
MapleMap map = player.getMap();
victim.saveLocationOnWarp();
victim.forceChangeMap(map, map.findClosestPortal(player.getPosition()));
} else {
player.dropMessage(6, "Unknown player.");
}
}
}

View File

@@ -0,0 +1,40 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import tools.MaplePacketCreator;
public class UnBugCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.enableActions());
}
}

View File

@@ -0,0 +1,42 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.SkillFactory;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class UnHideCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
SkillFactory.getSkill(9101004).getEffect(SkillFactory.getSkill(9101004).getMaxLevel()).applyTo(player);
}
}

View File

@@ -0,0 +1,56 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class UnJailCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !unjail <playername>");
return;
}
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
if (victim.getJailExpirationTimeLeft() <= 0) {
player.message("This player is already free.");
return;
}
victim.removeJailExpirationTime();
victim.message("By lack of concrete proof you are now unjailed. Enjoy freedom!");
player.message(victim.getName() + " was unjailed.");
} else {
player.message("Player '" + params[0] + "' could not be found.");
}
}
}

View File

@@ -0,0 +1,68 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: MedicOP - Add warparea command
*/
package client.command.commands.gm2;
import client.MapleCharacter;
import client.MapleClient;
import client.command.Command;
import server.maps.MapleMap;
import java.awt.*;
import java.util.Collection;
public class WarpAreaCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !warparea <mapid>");
return;
}
try {
MapleMap target = c.getChannelServer().getMapFactory().getMap(Integer.parseInt(params[0]));
if (target == null) {
player.yellowMessage("Map ID " + params[0] + " is invalid.");
return;
}
Point pos = player.getPosition();
Collection<MapleCharacter> characters = player.getMap().getAllPlayers();
for (MapleCharacter victim : characters) {
if (victim.getPosition().distanceSq(pos) <= 50000) {
victim.saveLocationOnWarp();
victim.changeMap(target, target.getRandomPlayerSpawnpoint());
}
}
} catch (Exception ex) {
player.yellowMessage("Map ID " + params[0] + " is invalid.");
}
}
}

View File

@@ -0,0 +1,72 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.maps.FieldLimit;
import server.maps.MapleMap;
import server.maps.MapleMiniDungeonInfo;
public class WarpCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !warp <mapid>");
return;
}
try {
MapleMap target = c.getChannelServer().getMapFactory().getMap(Integer.parseInt(params[0]));
if (target == null) {
player.yellowMessage("Map ID " + params[0] + " is invalid.");
return;
}
if (!player.isAlive()) {
player.dropMessage(1, "This command cannot be used when you're dead.");
return;
}
if (!player.isGM()) {
if (player.getEventInstance() != null || MapleMiniDungeonInfo.isDungeonMap(player.getMapId()) || FieldLimit.CANNOTMIGRATE.check(player.getMap().getFieldLimit())) {
player.dropMessage(1, "This command cannot be used in this map.");
return;
}
}
// expedition issue with this command detected thanks to Masterrulax
player.saveLocationOnWarp();
player.changeMap(target, target.getRandomPlayerSpawnpoint());
} catch (Exception ex) {
player.yellowMessage("Map ID " + params[0] + " is invalid.");
}
}
}

View File

@@ -0,0 +1,63 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: MedicOP - Add warpmap command
*/
package client.command.commands.gm2;
import client.MapleCharacter;
import client.MapleClient;
import client.command.Command;
import server.maps.MapleMap;
import java.util.Collection;
public class WarpMapCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.yellowMessage("Syntax: !warpmap <mapid>");
return;
}
try {
MapleMap target = c.getChannelServer().getMapFactory().getMap(Integer.parseInt(params[0]));
if (target == null) {
player.yellowMessage("Map ID " + params[0] + " is invalid.");
return;
}
Collection<MapleCharacter> characters = player.getMap().getAllPlayers();
for (MapleCharacter victim : characters) {
victim.saveLocationOnWarp();
victim.changeMap(target, target.getRandomPlayerSpawnpoint());
}
} catch (Exception ex) {
player.yellowMessage("Map ID " + params[0] + " is invalid.");
}
}
}

View File

@@ -0,0 +1,97 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm2;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import server.life.MapleMonster;
import server.life.MapleNPC;
import server.life.MaplePlayerNPC;
import server.maps.MapleMapObject;
import java.util.HashSet;
public class WhereaMiCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
HashSet<MapleCharacter> chars = new HashSet<>();
HashSet<MapleNPC> npcs = new HashSet<>();
HashSet<MaplePlayerNPC> playernpcs = new HashSet<>();
HashSet<MapleMonster> mobs = new HashSet<>();
for (MapleMapObject mmo : player.getMap().getMapObjects()) {
if (mmo instanceof MapleNPC) {
MapleNPC npc = (MapleNPC) mmo;
npcs.add(npc);
} else if (mmo instanceof MapleCharacter) {
MapleCharacter mc = (MapleCharacter) mmo;
chars.add(mc);
} else if (mmo instanceof MapleMonster) {
MapleMonster mob = (MapleMonster) mmo;
if (mob.isAlive()) {
mobs.add(mob);
}
} else if (mmo instanceof MaplePlayerNPC) {
MaplePlayerNPC npc = (MaplePlayerNPC) mmo;
playernpcs.add(npc);
}
}
player.yellowMessage("Map ID: " + player.getMap().getId());
player.yellowMessage("Players on this map:");
for (MapleCharacter chr : chars) {
player.dropMessage(5, ">> " + chr.getName() + " - " + chr.getId() + " - Oid: " + chr.getObjectId());
}
if (!playernpcs.isEmpty()) {
player.yellowMessage("PlayerNPCs on this map:");
for (MaplePlayerNPC pnpc : playernpcs) {
player.dropMessage(5, ">> " + pnpc.getName() + " - Scriptid: " + pnpc.getScriptId() + " - Oid: " + pnpc.getObjectId());
}
}
if (!npcs.isEmpty()) {
player.yellowMessage("NPCs on this map:");
for (MapleNPC npc : npcs) {
player.dropMessage(5, ">> " + npc.getName() + " - " + npc.getId() + " - Oid: " + npc.getObjectId());
}
}
if (!mobs.isEmpty()) {
player.yellowMessage("Monsters on this map:");
for (MapleMonster mob : mobs) {
if (mob.isAlive()) {
player.dropMessage(5, ">> " + mob.getName() + " - " + mob.getId() + " - Oid: " + mob.getObjectId());
}
}
}
}
}

View File

@@ -0,0 +1,96 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm3;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import net.server.Server;
import server.TimerManager;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class BanCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
if (params.length < 2) {
player.yellowMessage("Syntax: !ban <IGN> <Reason> (Please be descriptive)");
return;
}
String ign = params[0];
String reason = joinStringFrom(params, 1);
MapleCharacter target = c.getChannelServer().getPlayerStorage().getCharacterByName(ign);
if (target != null) {
String readableTargetName = MapleCharacter.makeMapleReadable(target.getName());
String ip = target.getClient().getSession().getRemoteAddress().toString().split(":")[0];
//Ban ip
PreparedStatement ps = null;
try {
Connection con = DatabaseConnection.getConnection();
if (ip.matches("/[0-9]{1,3}\\..*")) {
ps = con.prepareStatement("INSERT INTO ipbans VALUES (DEFAULT, ?, ?)");
ps.setString(1, ip);
ps.setString(2, String.valueOf(target.getClient().getAccID()));
ps.executeUpdate();
ps.close();
}
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
c.getPlayer().message("Error occured while banning IP address");
c.getPlayer().message(target.getName() + "'s IP was not banned: " + ip);
}
target.getClient().banMacs();
reason = c.getPlayer().getName() + " banned " + readableTargetName + " for " + reason + " (IP: " + ip + ") " + "(MAC: " + c.getMacs() + ")";
target.ban(reason);
target.yellowMessage("You have been banned by #b" + c.getPlayer().getName() + " #k.");
target.yellowMessage("Reason: " + reason);
c.announce(MaplePacketCreator.getGMEffect(4, (byte) 0));
final MapleCharacter rip = target;
TimerManager.getInstance().schedule(new Runnable() {
@Override
public void run() {
rip.getClient().disconnect(false, false);
}
}, 5000); //5 Seconds
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.serverNotice(6, "[RIP]: " + ign + " has been banned."));
} else if (MapleCharacter.ban(ign, reason, false)) {
c.announce(MaplePacketCreator.getGMEffect(4, (byte) 0));
Server.getInstance().broadcastMessage(c.getWorld(), MaplePacketCreator.serverNotice(6, "[RIP]: " + ign + " has been banned."));
} else {
c.announce(MaplePacketCreator.getGMEffect(6, (byte) 1));
}
}
}

View File

@@ -0,0 +1,41 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm3;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class ChatCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
player.toggleWhiteChat();
player.message("Your chat is now " + (player.getWhiteChat() ? " white" : "normal") + ".");
}
}

View File

@@ -0,0 +1,56 @@
/*
This file is part of the HeavenMS MapleStory Server, commands OdinMS-based
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
@Author: Arthur L - Refactored command content into modules
*/
package client.command.commands.gm3;
import client.MapleBuffStat;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
public class CheckDmgCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
MapleCharacter player = c.getPlayer();
MapleCharacter victim = c.getWorldServer().getPlayerStorage().getCharacterByName(params[0]);
if (victim != null) {
int maxBase = victim.calculateMaxBaseDamage(victim.getTotalWatk());
Integer watkBuff = victim.getBuffedValue(MapleBuffStat.WATK);
Integer matkBuff = victim.getBuffedValue(MapleBuffStat.MATK);
Integer blessing = victim.getSkillLevel(10000000 * player.getJobType() + 12);
if (watkBuff == null) watkBuff = 0;
if (matkBuff == null) matkBuff = 0;
player.dropMessage(5, "Cur Str: " + victim.getTotalStr() + " Cur Dex: " + victim.getTotalDex() + " Cur Int: " + victim.getTotalInt() + " Cur Luk: " + victim.getTotalLuk());
player.dropMessage(5, "Cur WATK: " + victim.getTotalWatk() + " Cur MATK: " + victim.getTotalMagic());
player.dropMessage(5, "Cur WATK Buff: " + watkBuff + " Cur MATK Buff: " + matkBuff + " Cur Blessing Level: " + blessing);
player.dropMessage(5, victim.getName() + "'s maximum base damage (before skills) is " + maxBase);
} else {
player.message("Player '" + params[0] + "' could not be found on this world.");
}
}
}

Some files were not shown because too many files have changed in this diff Show More