Code Coupons + Worldmap update + Mini-games + Player Interaction wrap

Fixed several cases on the Cash Shop that would freeze some player actions when triggered, requiring exit Cash Shop to unstuck.
Implemented Code Coupons, supporting several items bundled on the same code, and also devised a way to automate code generation.
Added a current status on-demand option on the Buyback command. Info such as "current fee" or "time remaining" are available now.
Reviewed several cases where non-owned items would get stacked with owner-tagged items.
Added Door support for Happyville, Crimsonwood Keep.
Added worldmap tooltip support for some maps in Masteria's C. Keep and H. House.
Added Masteria region to the world map.
C. Keep interiors no longer relocates players to entrance after actions such as logout.
Overhauled minigame mechanics: from player boxes tooltip and in-match improvements to deploy different minigame types, accordingly with item description or player choice.
Fixed Amoria outskirts not relocating players to city after getting KO'ed.
Fixed issues with pets, rings and cash items being assigned the same cash unique ids leading to some quirks on the cash shop inventory.
Fixed an issue with the recently added HP/MP ratio update, arbitrarily taking off 1 point in certain cases.
Answer positions on the explorer's 3rd job quiz are now randomed.
Fixed several issues that showed up when the bcrypt system is disabled.
DOT from maps such as El Nath and Aqua Road now procs at a 5sec interval, GMS-like.
Improved performance of Whodrops and Search commands.
Concurrently protected player interaction handlers, thus mitigating several exploits on these lines.
Adjusted several expedition timers, such as Horntail, now having a more sane deadline.
Concurrently protected chair modules.
Fixed "seduce" debuff not working on chairs.
This commit is contained in:
ronancpl
2018-10-09 22:39:36 -03:00
parent 3a8377c283
commit 2b44b4baa2
213 changed files with 16547 additions and 11031 deletions

View File

@@ -42,6 +42,7 @@ public abstract class AbstractMapleCharacterObject extends AbstractAnimatedMaple
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<>();
@@ -222,6 +223,8 @@ public abstract class AbstractMapleCharacterObject extends AbstractAnimatedMaple
} else if (thp > localmaxhp) {
thp = localmaxhp;
}
if (this.hp != thp) this.transienthp = Float.NEGATIVE_INFINITY;
this.hp = thp;
dispatchHpChanged(oldHp);
@@ -234,6 +237,8 @@ public abstract class AbstractMapleCharacterObject extends AbstractAnimatedMaple
} else if (tmp > localmaxmp) {
tmp = localmaxmp;
}
if (this.mp != tmp) this.transientmp = Float.NEGATIVE_INFINITY;
this.mp = tmp;
}
@@ -246,11 +251,13 @@ public abstract class AbstractMapleCharacterObject extends AbstractAnimatedMaple
}
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_);
}

View File

@@ -118,6 +118,7 @@ import client.inventory.MaplePet;
import client.inventory.MapleWeaponType;
import client.inventory.ModifyInventory;
import client.inventory.PetDataFactory;
import client.inventory.manipulator.MapleCashidGenerator;
import client.inventory.manipulator.MapleInventoryManipulator;
import client.newyear.NewYearCardRecord;
import constants.ExpTable;
@@ -945,7 +946,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public void setMasteries(int jobId) {
int[] skills = new int[4];
for (int i = 0; i > skills.length; i++) {
skills[i] = 0; //that initialization meng
skills[i] = 0; //that initialization meng
}
if (jobId == 112) {
skills[0] = Hero.ACHILLES;
@@ -1002,11 +1003,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
skills[1] = Aran.HIGH_MASTERY;
skills[2] = Aran.FREEZE_STANDING;
} else if (jobId == 2217) {
skills[0] = Evan.MAPLE_WARRIOR;
skills[1] = Evan.ILLUSION;
skills[0] = Evan.MAPLE_WARRIOR;
skills[1] = Evan.ILLUSION;
} else if (jobId == 2218) {
skills[0] = Evan.BLESSING_OF_THE_ONYX;
skills[1] = Evan.BLAZE;
skills[0] = Evan.BLESSING_OF_THE_ONYX;
skills[1] = Evan.BLAZE;
}
for (Integer skillId : skills) {
if (skillId != 0) {
@@ -1341,12 +1342,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
private boolean buffMapProtection() {
effLock.lock();
chrLock.lock();
int thisMapid = mapid;
int returnMapid = client.getChannelServer().getMapFactory().getMap(thisMapid).getReturnMapId();
effLock.lock();
chrLock.lock();
try {
for(Entry<MapleBuffStat, MapleBuffStatValueHolder> mbs : effects.entrySet()) {
if(mbs.getKey() == MapleBuffStat.MAP_PROTECTION) {
@@ -1884,7 +1884,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
if(hold + quantity <= ii.getSlotMax(client, itemid))
return true;
}
return getInventory(ItemConstants.getInventoryType(itemid)).getNextFreeSlot() > -1;
}
@@ -1903,7 +1903,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
Skill battleship = SkillFactory.getSkill(Corsair.BATTLE_SHIP);
int cooldown = battleship.getEffect(getSkillLevel(battleship)).getCooldown();
announce(MaplePacketCreator.skillCooldown(Corsair.BATTLE_SHIP, cooldown));
addCooldown(Corsair.BATTLE_SHIP, System.currentTimeMillis(), (long)(cooldown * 1000));
addCooldown(Corsair.BATTLE_SHIP, Server.getInstance().getCurrentTime(), (long)(cooldown * 1000));
removeCooldown(5221999);
cancelEffectFromBuffStat(MapleBuffStat.MONSTER_RIDING);
} else {
@@ -2080,6 +2080,8 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
ps3.setInt(1, ringid);
ps3.executeUpdate();
}
MapleCashidGenerator.freeCashId(ringid);
}
}
}
@@ -2090,11 +2092,13 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
ps2.executeUpdate();
}
if(rs.getInt("petid") > -1) {
int petid = rs.getInt("petid");
if(petid > -1) {
try (PreparedStatement ps2 = con.prepareStatement("DELETE FROM pets WHERE petid = ?")) {
ps2.setInt(1, rs.getInt("petid"));
ps2.setInt(1, petid);
ps2.executeUpdate();
}
MapleCashidGenerator.freeCashId(petid);
}
}
}
@@ -2453,6 +2457,10 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
chrLock.unlock();
}
if (disease == MapleDisease.SEDUCE && chair.get() != 0) {
sitChair(0);
}
final List<Pair<MapleDisease, Integer>> debuff = Collections.singletonList(new Pair<>(disease, Integer.valueOf(skill.getX())));
client.announce(MaplePacketCreator.giveDebuff(debuff, skill));
@@ -2550,7 +2558,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public void run() {
doHurtHp();
}
}, 10000, 10000 - lastHpTask);
}, ServerConstants.MAP_DAMAGE_OVERTIME_INTERVAL, ServerConstants.MAP_DAMAGE_OVERTIME_INTERVAL - lastHpTask);
}
public void resetHpDecreaseTask() {
@@ -2559,7 +2567,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
long lastHpTask = Server.getInstance().getCurrentTime() - lastHpDec;
startHpDecreaseTask((lastHpTask > 10000) ? 10000 : lastHpTask);
startHpDecreaseTask((lastHpTask > ServerConstants.MAP_DAMAGE_OVERTIME_INTERVAL) ? ServerConstants.MAP_DAMAGE_OVERTIME_INTERVAL : lastHpTask);
}
public void dropMessage(String message) {
@@ -2682,7 +2690,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
effLock.unlock();
}
long curTime = System.currentTimeMillis();
long curTime = Server.getInstance().getCurrentTime();
for(Entry<Integer, MapleCoolDownValueHolder> bel : es) {
MapleCoolDownValueHolder mcdvh = bel.getValue();
if(curTime >= mcdvh.startTime + mcdvh.length) {
@@ -5247,8 +5255,9 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
this.battleshipHp = (int) length;
addCooldown(skillid, 0, length);
} else {
int time = (int) ((length + starttime) - System.currentTimeMillis());
addCooldown(skillid, System.currentTimeMillis(), time);
long timeNow = Server.getInstance().getCurrentTime();
int time = (int) ((length + starttime) - timeNow);
addCooldown(skillid, timeNow, time);
}
}
@@ -5433,9 +5442,43 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
int grade = Math.min(Math.max(level, 30), 120) - 30;
fee += (grade * ServerConstants.BUYBACK_LEVEL_STACK_FEE);
if (ServerConstants.USE_BUYBACK_WITH_MESOS) fee *= ServerConstants.BUYBACK_MESO_MULTIPLIER;
return (int) Math.floor(fee);
}
public void showBuybackInfo() {
String s = "#eBUYBACK STATUS#n\r\n\r\nCurrent buyback fee: #b" + getBuybackFee() + " " + (ServerConstants.USE_BUYBACK_WITH_MESOS ? "mesos" : "NX") + "#k\r\n\r\n";
long timeNow = Server.getInstance().getCurrentTime();
boolean avail = true;
if (!isAlive()) {
long timeLapsed = timeNow - lastDeathtime;
long timeRemaining = ServerConstants.BUYBACK_RETURN_MINUTES * 60 * 1000 - (timeLapsed + Math.max(0, getNextBuybackTime() - timeNow));
if (timeRemaining < 1) {
s += "Buyback #e#rUNAVAILABLE#k#n";
avail = false;
} else {
s += "Buyback countdown: #e#b" + getTimeRemaining(ServerConstants.BUYBACK_RETURN_MINUTES * 60 * 1000 - timeLapsed) + "#k#n";
}
s += "\r\n";
}
if (timeNow < getNextBuybackTime() && avail) {
s += "Buyback available in #r" + getTimeRemaining(getNextBuybackTime() - timeNow) + "#k";
s += "\r\n";
}
this.showHint(s);
}
private static String getTimeRemaining(long timeLeft) {
int seconds = (int) Math.floor(timeLeft / 1000) % 60;
int minutes = (int) Math.floor(timeLeft / (1000*60)) % 60;
return (minutes > 0 ? (String.format("%02d", minutes) + " minutes, ") : "") + String.format("%02d", seconds) + " seconds";
}
public boolean couldBuyback() { // Ronan's buyback system
long timeNow = Server.getInstance().getCurrentTime();
@@ -5447,16 +5490,12 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
long nextBuybacktime = getNextBuybackTime();
if (timeNow < nextBuybacktime) {
long timeLeft = nextBuybacktime - timeNow;
int seconds = (int) Math.floor(timeLeft / 1000) % 60;
int minutes = (int) Math.floor(timeLeft / (1000*60)) % 60;
this.dropMessage(5, "Next buyback available in " + (minutes > 0 ? (String.format("%02d", minutes) + " minutes, ") : "") + String.format("%02d", seconds) + " seconds.");
this.dropMessage(5, "Next buyback available in " + getTimeRemaining(timeLeft) + ".");
return false;
}
boolean usingMesos = ServerConstants.USE_BUYBACK_WITH_MESOS;
int fee = getBuybackFee();
if (usingMesos) fee *= ServerConstants.BUYBACK_MESO_MULTIPLIER;
if (!canBuyback(fee, usingMesos)) {
this.dropMessage(5, "You don't have " + fee + " " + (usingMesos ? "mesos" : "NX") + " to buyback.");
@@ -5528,7 +5567,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
public void leaveMap() {
controlled.clear();
visibleMapObjects.clear();
chair.set(0);
setChair(0);
if (hpDecreaseTask != null) {
hpDecreaseTask.cancel(false);
}
@@ -5710,7 +5749,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
if (ServerConstants.USE_PERFECT_PITCH && level >= 30) {
//milestones?
if (MapleInventoryManipulator.checkSpace(client, 4310000, (short) 1, "")) {
MapleInventoryManipulator.addById(client, 4310000, (short) 1);
MapleInventoryManipulator.addById(client, 4310000, (short) 1, "", -1);
}
} else if (level == 10) {
Runnable r = new Runnable() {
@@ -6452,7 +6491,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
ps = con.prepareStatement("SELECT SkillID,StartTime,length FROM cooldowns WHERE charid = ?");
ps.setInt(1, ret.getId());
rs = ps.executeQuery();
long curTime = System.currentTimeMillis();
long curTime = Server.getInstance().getCurrentTime();
while (rs.next()) {
final int skillid = rs.getInt("SkillID");
final long length = rs.getLong("length"), startTime = rs.getLong("StartTime");
@@ -6534,7 +6573,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
ret.storage = MapleStorage.loadOrCreateFromDB(ret.accountid, ret.world);
int startHp = ret.hp, startMp = ret.mp;
ret.recalcLocalStats();
ret.reapplyLocalStats();
ret.changeHpMp(startHp, startMp, true);
//ret.resetBattleshipHp();
}
@@ -6651,7 +6690,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
private void playerDead() {
cancelAllBuffs(false);
dispelDebuffs();
lastDeathtime = System.currentTimeMillis();
lastDeathtime = Server.getInstance().getCurrentTime();
EventInstanceManager eim = getEventInstance();
if (eim != null) {
@@ -6702,14 +6741,53 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
cancelEffectFromBuffStat(MapleBuffStat.MONSTER_RIDING);
}
if (getChair() != 0) {
setChair(0);
client.announce(MaplePacketCreator.cancelChair(-1));
getMap().broadcastMessage(this, MaplePacketCreator.showChair(getId(), 0), false);
}
unsitChairInternal();
client.announce(MaplePacketCreator.enableActions());
}
private void unsitChairInternal() {
if (chair.get() != 0) {
setChair(0);
if (unregisterChairBuff()) {
getMap().broadcastMessage(this, MaplePacketCreator.cancelForeignChairSkillEffect(this.getId()), false);
}
getMap().broadcastMessage(this, MaplePacketCreator.showChair(this.getId(), 0), false);
}
announce(MaplePacketCreator.cancelChair(-1));
}
public void sitChair(int itemId) {
if (client.tryacquireClient()) {
try {
if (itemId >= 1000000) { // sit on item chair
if (chair.get() == 0) {
setChair(itemId);
getMap().broadcastMessage(this, MaplePacketCreator.showChair(this.getId(), itemId), false);
}
announce(MaplePacketCreator.enableActions());
} else if (itemId != 0) { // sit on map chair
if (chair.get() == 0) {
setChair(itemId);
if (registerChairBuff()) {
getMap().broadcastMessage(this, MaplePacketCreator.giveForeignChairSkillEffect(this.getId()), false);
}
announce(MaplePacketCreator.cancelChair(itemId));
}
} else { // stand up
unsitChairInternal();
}
} finally {
client.releaseClient();
}
}
}
private void setChair(int chair) {
this.chair.set(chair);
}
public void respawn(int returnMap) {
respawn(null, returnMap); // unspecified EIM, don't force EIM unregister in this case
}
@@ -6780,15 +6858,11 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
localwatk += equipwatk;
}
private List<Pair<MapleStat, Integer>> recalcLocalStats() {
private void reapplyLocalStats() {
effLock.lock();
chrLock.lock();
statWlock.lock();
try {
List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<>(2);
int oldlocalmaxhp = localmaxhp;
int oldlocalmaxmp = localmaxmp;
localmaxhp = getMaxHp();
localmaxmp = getMaxMp();
localdex = getDex();
@@ -6815,11 +6889,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
localmaxhp = Math.min(30000, localmaxhp);
localmaxmp = Math.min(30000, localmaxmp);
if (ServerConstants.USE_FIXED_RATIO_HPMP_UPDATE) {
if (localmaxhp != oldlocalmaxhp) hpmpupdate.add(calcHpRatioUpdate(localmaxhp, oldlocalmaxhp));
if (localmaxmp != oldlocalmaxmp) hpmpupdate.add(calcMpRatioUpdate(localmaxmp, oldlocalmaxmp));
}
MapleStatEffect combo = getBuffEffect(MapleBuffStat.ARAN_COMBO);
if (combo != null) {
localwatk += combo.getX();
@@ -6906,10 +6975,54 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
// Add throwing stars to dmg.
}
} finally {
statWlock.unlock();
chrLock.unlock();
effLock.unlock();
}
}
private List<Pair<MapleStat, Integer>> recalcLocalStats() {
effLock.lock();
chrLock.lock();
statWlock.lock();
try {
List<Pair<MapleStat, Integer>> hpmpupdate = new ArrayList<>(2);
int oldlocalmaxhp = localmaxhp;
int oldlocalmaxmp = localmaxmp;
reapplyLocalStats();
if (ServerConstants.USE_FIXED_RATIO_HPMP_UPDATE) {
if (localmaxhp != oldlocalmaxhp) {
Pair<MapleStat, Integer> hpUpdate;
if (transienthp == Float.NEGATIVE_INFINITY) {
hpUpdate = calcHpRatioUpdate(localmaxhp, oldlocalmaxhp);
} else {
hpUpdate = calcHpRatioTransient();
}
hpmpupdate.add(hpUpdate);
}
if (localmaxmp != oldlocalmaxmp) {
Pair<MapleStat, Integer> mpUpdate;
if (transientmp == Float.NEGATIVE_INFINITY) {
mpUpdate = calcMpRatioUpdate(localmaxmp, oldlocalmaxmp);
} else {
mpUpdate = calcMpRatioTransient();
}
hpmpupdate.add(mpUpdate);
}
}
return hpmpupdate;
} finally {
statWlock.unlock();
chrLock.unlock();
effLock.unlock();
}
}
@@ -7789,10 +7902,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
}
public void setChair(int chair) {
this.chair.set(chair);
}
public void setChalkboard(String text) {
this.chalktext = text;
}
@@ -7968,7 +8077,7 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
private Pair<MapleStat, Integer> calcHpRatioUpdate(int newHp, int oldHp) {
int delta = newHp - oldHp;
this.hp = calcHpMpRatioUpdate(hp, oldHp, delta);
this.hp = calcHpRatioUpdate(hp, oldHp, delta);
hpChangeAction(Short.MIN_VALUE);
return new Pair<>(MapleStat.HP, hp);
@@ -7976,19 +8085,47 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
private Pair<MapleStat, Integer> calcMpRatioUpdate(int newMp, int oldMp) {
int delta = newMp - oldMp;
this.mp = calcHpMpRatioUpdate(mp, oldMp, delta);
this.mp = calcMpRatioUpdate(mp, oldMp, delta);
return new Pair<>(MapleStat.MP, mp);
}
private static int calcHpMpRatioUpdate(int curpoint, int maxpoint, int diffpoint) {
private static int calcTransientRatio(float transientpoint) {
int ret = (int) transientpoint;
return !(ret <= 0 && transientpoint > 0.0f) ? ret : 1;
}
private Pair<MapleStat, Integer> calcHpRatioTransient() {
this.hp = calcTransientRatio(transienthp * localmaxhp);
hpChangeAction(Short.MIN_VALUE);
return new Pair<>(MapleStat.HP, hp);
}
private Pair<MapleStat, Integer> calcMpRatioTransient() {
this.mp = calcTransientRatio(transientmp * localmaxmp);
return new Pair<>(MapleStat.MP, mp);
}
private int calcHpRatioUpdate(int curpoint, int maxpoint, int diffpoint) {
int curMax = maxpoint;
int nextMax = Math.min(30000, maxpoint + diffpoint);
float temp = curpoint * nextMax;
int ret = (int) Math.round(temp / curMax);
int ret = (int) Math.ceil(temp / curMax);
//System.out.println("cur: " + curpoint + " next: " + ret + " max: " + curMax + " nextmax:" + nextMax + " diff: " + diffpoint);
return !(ret <= 0 && curpoint > 0) ? ret : 1;
transienthp = (maxpoint > nextMax) ? ((float) curpoint) / maxpoint : ((float) ret) / nextMax;
return ret;
}
private int calcMpRatioUpdate(int curpoint, int maxpoint, int diffpoint) {
int curMax = maxpoint;
int nextMax = Math.min(30000, maxpoint + diffpoint);
float temp = curpoint * nextMax;
int ret = (int) Math.ceil(temp / curMax);
transientmp = (maxpoint > nextMax) ? ((float) curpoint) / maxpoint : ((float) ret) / nextMax;
return ret;
}
public boolean applyHpMpChange(int hpCon, int hpchange, int mpchange) {
@@ -8137,7 +8274,6 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
doorSlot = -1;
party = null;
//cancelMagicDoor(); // cancel magic doors if kicked out / quitted from party.
} else {
party = p;
}
@@ -9082,11 +9218,27 @@ public class MapleCharacter extends AbstractMapleCharacterObject {
}
pendantExp = 0;
}
private Collection<Item> getUpgradeableEquipList() {
Collection<Item> fullList = getInventory(MapleInventoryType.EQUIPPED).list();
if (ServerConstants.USE_EQUIPMNT_LVLUP_CASH) {
return fullList;
}
Collection<Item> eqpList = new LinkedHashSet<>();
for (Item it : fullList) {
if (!ii.isCash(it.getItemId())) {
eqpList.add(it);
}
}
return eqpList;
}
public void increaseEquipExp(int expGain) {
if(expGain < 0) expGain = Integer.MAX_VALUE;
for (Item item : getInventory(MapleInventoryType.EQUIPPED).list()) {
for (Item item : getUpgradeableEquipList()) {
Equip nEquip = (Equip) item;
String itemName = ii.getName(nEquip.getItemId());
if (itemName == null) {

View File

@@ -41,6 +41,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import tools.*;
@@ -109,8 +110,10 @@ public class MapleClient {
private String pic = null;
private String hwid = null;
private int picattempt = 0;
private byte csattempt = 0;
private byte gender = -1;
private boolean disconnecting = false;
private final Semaphore actionsSemaphore = new Semaphore(7);
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true);
private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true);
private static final Lock loginLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_LOGIN, true);
@@ -532,7 +535,6 @@ public class MapleClient {
gender = rs.getByte("gender");
characterSlots = rs.getByte("characterslots");
String passhash = rs.getString("password");
String salt = rs.getString("salt");
byte tos = rs.getByte("tos");
ps.close();
@@ -547,8 +549,9 @@ public class MapleClient {
loginok = 7;
} else if (passhash.charAt(0) == '$' && passhash.charAt(1) == '2' && BCrypt.checkpw(pwd, passhash)) {
loginok = (tos == 0) ? 23 : 0;
} else if (pwd.equals(passhash) || checkHash(passhash, "SHA-1", pwd) || checkHash(passhash, "SHA-512", pwd + salt)) {
loginok = (tos == 0) ? -23 : -10; // migrate to bcrypt
} else if (pwd.equals(passhash) || checkHash(passhash, "SHA-1", pwd) || checkHash(passhash, "SHA-512", pwd)) {
// thanks GabrielSin for detecting some no-bcrypt inconsistencies here
loginok = (tos == 0) ? (!ServerConstants.BCRYPT_MIGRATION ? 23 : -23) : (!ServerConstants.BCRYPT_MIGRATION ? 0 : -10); // migrate to bcrypt
} else {
loggedIn = false;
loginok = 4;
@@ -775,7 +778,7 @@ public class MapleClient {
if (!rs.next()) {
rs.close();
ps.close();
throw new RuntimeException("getLoginState - MapleClient");
throw new RuntimeException("getLoginState - MapleClient AccID: " + getAccID());
}
birthday = Calendar.getInstance();
@@ -1170,10 +1173,20 @@ public class MapleClient {
lock.unlock();
}
public boolean trylockClient() {
return lock.tryLock();
public boolean tryacquireClient() {
if (actionsSemaphore.tryAcquire()) {
lockClient();
return true;
} else {
return false;
}
}
public void releaseClient() {
unlockClient();
actionsSemaphore.release();
}
public void lockEncoder() {
encoderLock.lock();
}
@@ -1198,7 +1211,7 @@ public class MapleClient {
try {
MessageDigest digester = MessageDigest.getInstance(type);
digester.update(password.getBytes("UTF-8"), 0, password.length());
return HexTool.toString(digester.digest()).replace(" ", "").toLowerCase().equals(hash);
return HexTool.toString(digester.digest()).replace(" ", "").toLowerCase().equals(hash);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
throw new RuntimeException("Encoding the string failed", e);
}
@@ -1431,4 +1444,22 @@ public class MapleClient {
this.removeClickedNPC();
NPCScriptManager.getInstance().dispose(this);
}
public boolean attemptCsCoupon() {
if (csattempt > 2) {
resetCsCoupon();
return false;
}
csattempt++;
return true;
}
public void resetCsCoupon() {
csattempt = 0;
}
public void enableCSActions() {
announce(MaplePacketCreator.enableCSUse(player));
}
}

View File

@@ -25,8 +25,9 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import tools.Pair;
import tools.DatabaseConnection;
import client.inventory.manipulator.MapleCashidGenerator;
/**
*
@@ -86,6 +87,9 @@ public class MapleRing implements Comparable<MapleRing> {
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();
@@ -102,46 +106,40 @@ public class MapleRing implements Comparable<MapleRing> {
}
}
public static int createRing(int itemid, final MapleCharacter partner1, final MapleCharacter partner2) {
public static Pair<Integer, Integer> createRing(int itemid, final MapleCharacter partner1, final MapleCharacter partner2) {
try {
if (partner1 == null) {
return -2;
return new Pair<>(-3, -3);
} else if (partner2 == null) {
return -1;
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 (itemid, partnerChrId, partnername) VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, itemid);
ps.setInt(2, partner2.getId());
ps.setString(3, partner2.getName());
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();
ResultSet rs = ps.getGeneratedKeys();
rs.next();
ringID[0] = rs.getInt(1); // ID.
rs.close();
ps.close();
ps = con.prepareStatement("INSERT INTO rings (itemid, partnerRingId, partnerChrId, partnername) VALUES (?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, itemid);
ps.setInt(2, ringID[0]);
ps.setInt(3, partner1.getId());
ps.setString(4, partner1.getName());
ps.executeUpdate();
rs = ps.getGeneratedKeys();
rs.next();
ringID[1] = rs.getInt(1);
rs.close();
ps.close();
ps = con.prepareStatement("UPDATE rings SET partnerRingId = ? WHERE id = ?");
ps = con.prepareStatement("INSERT INTO rings (id, itemid, partnerRingId, partnerChrId, partnername) VALUES (?, ?, ?, ?, ?)");
ps.setInt(1, ringID[1]);
ps.setInt(2, ringID[0]);
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 ringID[0];
return new Pair<>(ringID[0], ringID[1]);
} catch (SQLException ex) {
ex.printStackTrace();
return -1;
return new Pair<>(-1, -1);
}
}

View File

@@ -8,6 +8,7 @@ package client.autoban;
import client.MapleCharacter;
import java.util.HashMap;
import java.util.Map;
import net.server.Server;
import tools.FilePrinter;
/**
@@ -35,12 +36,12 @@ public class AutobanManager {
return;
}
if (lastTime.containsKey(fac)) {
if (lastTime.get(fac) < (System.currentTimeMillis() - fac.getExpire())) {
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, System.currentTimeMillis());
lastTime.put(fac, Server.getInstance().getCurrentTime());
if (points.containsKey(fac)) {
points.put(fac, points.get(fac) + 1);
@@ -76,7 +77,7 @@ public class AutobanManager {
//Don't use the same type for more than 1 thing
public void spam(int type) {
this.spam[type] = System.currentTimeMillis();
this.spam[type] = Server.getInstance().getCurrentTime();
}
public void spam(int type, int timestamp) {

View File

@@ -162,6 +162,7 @@ public class CommandsExecutor {
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);
@@ -345,6 +346,7 @@ public class CommandsExecutor {
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);

View File

@@ -30,6 +30,15 @@ import client.processor.BuybackProcessor;
public class BuyBackCommand extends Command {
@Override
public void execute(MapleClient c, String[] params) {
BuybackProcessor.processBuyback(c);
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

@@ -39,7 +39,7 @@ public class StatDexCommand extends Command {
int remainingAp = player.getRemainingAp();
int amount = (params.length > 0) ? Math.min(Integer.parseInt(params[0]), remainingAp) : Math.min(remainingAp, ServerConstants.MAX_AP - player.getDex());
if (!player.assignDex(amount)) {
if (!player.assignDex(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + ServerConstants.MAX_AP + " and you have enough to distribute.");
}
}

View File

@@ -39,7 +39,7 @@ public class StatIntCommand extends Command {
int remainingAp = player.getRemainingAp();
int amount = (params.length > 0) ? Math.min(Integer.parseInt(params[0]), remainingAp) : Math.min(remainingAp, ServerConstants.MAX_AP - player.getInt());
if (!player.assignInt(amount)) {
if (!player.assignInt(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + ServerConstants.MAX_AP + " and you have enough to distribute.");
}
}

View File

@@ -39,7 +39,7 @@ public class StatLukCommand extends Command {
int remainingAp = player.getRemainingAp();
int amount = (params.length > 0) ? Math.min(Integer.parseInt(params[0]), remainingAp) : Math.min(remainingAp, ServerConstants.MAX_AP - player.getLuk());
if (!player.assignLuk(amount)) {
if (!player.assignLuk(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + ServerConstants.MAX_AP + " and you have enough to distribute.");
}
}

View File

@@ -39,7 +39,7 @@ public class StatStrCommand extends Command {
int remainingAp = player.getRemainingAp();
int amount = (params.length > 0) ? Math.min(Integer.parseInt(params[0]), remainingAp) : Math.min(remainingAp, ServerConstants.MAX_AP - player.getStr());
if (!player.assignStr(amount)) {
if (!player.assignStr(Math.max(amount, 0))) {
player.dropMessage("Please make sure your AP is not over " + ServerConstants.MAX_AP + " and you have enough to distribute.");
}
}

View File

@@ -49,40 +49,49 @@ public class WhoDropsCommand extends Command {
player.dropMessage(5, "Please do @whodrops <item name>");
return;
}
String searchString = joinStringFrom(params, 0);
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.getMobNameFromID(rs.getInt("dropperid"));
if (resultName != null) {
output += resultName + ", ";
if (c.tryacquireClient()) {
try {
String searchString = joinStringFrom(params, 0);
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.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++;
}
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();
} else {
player.dropMessage(5, "The item you searched for doesn't exist.");
return;
}
output += "\r\n\r\n";
count++;
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, output, "00 00", (byte) 0));
} finally {
c.releaseClient();
}
} else {
player.dropMessage(5, "The item you searched for doesn't exist.");
return;
player.dropMessage(5, "Please wait a while for your request to be processed.");
}
c.announce(MaplePacketCreator.getNPCTalk(9010000, (byte) 0, output, "00 00", (byte) 0));
}
}

View File

@@ -92,7 +92,6 @@ public class ItemDropCommand extends Command {
return;
}
}
Item toDrop;
if (ItemConstants.getInventoryType(itemId) == MapleInventoryType.EQUIP) {

View File

@@ -37,8 +37,19 @@ import tools.Pair;
import java.io.File;
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
@@ -53,26 +64,43 @@ public class SearchCommand extends Command {
String search = joinStringFrom(params,1);
long start = System.currentTimeMillis();//for the lulz
MapleData data = null;
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File("wz/String.wz"));
if (!params[0].equalsIgnoreCase("ITEM")) {
boolean mapSearch = false;
if (params[0].equalsIgnoreCase("NPC")) {
data = dataProvider.getData("Npc.img");
data = npcStringData;
} else if (params[0].equalsIgnoreCase("MOB") || params[0].equalsIgnoreCase("MONSTER")) {
data = dataProvider.getData("Mob.img");
data = mobStringData;
} else if (params[0].equalsIgnoreCase("SKILL")) {
data = dataProvider.getData("Skill.img");
/*} else if (sub[1].equalsIgnoreCase("MAP")) {
TODO
*/
data = skillStringData;
} else if (params[0].equalsIgnoreCase("MAP")) {
data = mapStringData;
mapSearch = true;
} else {
sb.append("#bInvalid search.\r\nSyntax: '!search [type] [name]', where [type] is NPC, ITEM, MOB, or SKILL.");
sb.append("#bInvalid search.\r\nSyntax: '!search [type] [name]', where [type] is MAP, NPC, ITEM, MOB, or SKILL.");
}
if (data != null) {
String name;
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");
if (!mapSearch) {
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 {
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");
}
}
}
}
}

View File

@@ -17,25 +17,27 @@
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.gm6;
import client.command.Command;
import client.MapleClient;
import client.MapleCharacter;
import tools.MaplePacketCreator;
import client.MapleClient;
import client.command.Command;
import constants.ServerConstants;
public class FredCommand extends Command {
public class SupplyRateCouponCommand extends Command {
{
setDescription("");
}
@Override
public void execute(MapleClient c, String[] params) {
c.announce(MaplePacketCreator.fredrickMessage(Byte.valueOf(params[0])));
MapleCharacter player = c.getPlayer();
if (params.length < 1) {
player.dropMessage(5, "Syntax: !supplyratecoupon <yes|no>");
return;
}
ServerConstants.USE_SUPPLY_RATE_COUPONS = params[0].compareToIgnoreCase("no") != 0;
player.dropMessage(5, "Rate coupons are now " + (ServerConstants.USE_SUPPLY_RATE_COUPONS ? "enabled" : "disabled") + " for purchase at the Cash Shop.");
}
}

View File

@@ -26,10 +26,12 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import client.inventory.manipulator.MapleKarmaManipulator;
import server.MapleItemInformationProvider;
public class Item implements Comparable<Item> {
private static AtomicInteger runningCashId = new AtomicInteger(0);
private static AtomicInteger runningCashId = new AtomicInteger(777000000); // pets & rings shares cashid values
private int id, cashId, sn;
private short position;
@@ -83,7 +85,7 @@ public class Item implements Comparable<Item> {
public int getCashId() {
if (cashId == 0) {
cashId = runningCashId.incrementAndGet();
cashId = runningCashId.getAndIncrement();
}
return cashId;
}
@@ -177,4 +179,8 @@ public class Item implements Comparable<Item> {
public MaplePet getPet() {
return pet;
}
public boolean isUntradeable() {
return ((this.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE) || (MapleItemInformationProvider.getInstance().isDropRestricted(this.getItemId()) && !MapleKarmaManipulator.hasKarmaFlag(this));
}
}

View File

@@ -21,7 +21,6 @@
*/
package client.inventory;
import com.mysql.jdbc.Statement;
import constants.ExpTable;
import java.awt.Point;
import java.sql.PreparedStatement;
@@ -34,6 +33,7 @@ import server.movement.AbsoluteLifeMovement;
import server.movement.LifeMovement;
import server.movement.LifeMovementFragment;
import client.MapleCharacter;
import client.inventory.manipulator.MapleCashidGenerator;
import java.sql.Connection;
import tools.MaplePacketCreator;
import tools.Pair;
@@ -90,6 +90,8 @@ public class MaplePet extends Item {
ps.executeUpdate();
ps.close();
con.close();
MapleCashidGenerator.freeCashId(this.getUniqueId());
} catch (SQLException ex) {
ex.printStackTrace();
}
@@ -116,15 +118,11 @@ public class MaplePet extends Item {
public static int createPet(int itemid) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO pets (name, level, closeness, fullness, summoned) VALUES (?, 1, 0, 100, 0)", Statement.RETURN_GENERATED_KEYS);
ps.setString(1, MapleItemInformationProvider.getInstance().getName(itemid));
PreparedStatement ps = con.prepareStatement("INSERT INTO pets (petid, name, level, closeness, fullness, summoned) VALUES (?, ?, 1, 0, 100, 0)");
int ret = MapleCashidGenerator.generateCashId();
ps.setInt(1, ret);
ps.setString(2, MapleItemInformationProvider.getInstance().getName(itemid));
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
int ret = -1;
if (rs.next()) {
ret = rs.getInt(1);
}
rs.close();
ps.close();
con.close();
return ret;
@@ -137,18 +135,14 @@ public class MaplePet extends Item {
public static int createPet(int itemid, byte level, int closeness, int fullness) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("INSERT INTO pets (name, level, closeness, fullness, summoned) VALUES (?, ?, ?, ?, 0)", Statement.RETURN_GENERATED_KEYS);
ps.setString(1, MapleItemInformationProvider.getInstance().getName(itemid));
ps.setByte(2, level);
ps.setInt(3, closeness);
ps.setInt(4, fullness);
PreparedStatement ps = con.prepareStatement("INSERT INTO pets (petid, name, level, closeness, fullness, summoned) VALUES (?, ?, ?, ?, ?, 0)");
int ret = MapleCashidGenerator.generateCashId();
ps.setInt(1, ret);
ps.setString(2, MapleItemInformationProvider.getInstance().getName(itemid));
ps.setByte(3, level);
ps.setInt(4, closeness);
ps.setInt(5, fullness);
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
int ret = -1;
if (rs.next()) {
ret = rs.getInt(1);
}
rs.close();
ps.close();
con.close();
return ret;

View File

@@ -0,0 +1,104 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2018 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.inventory.manipulator;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import tools.DatabaseConnection;
/**
*
* @author RonanLana
*/
public class MapleCashidGenerator {
private final static Set<Integer> existentCashids = new HashSet<>(10000);
private static Integer runningCashid = 0;
private static void loadExistentCashIdsFromQuery(Connection con, String query) throws SQLException {
PreparedStatement ps = con.prepareStatement(query);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
existentCashids.add(rs.getInt(1));
}
rs.close();
ps.close();
}
public static synchronized void loadExistentCashIdsFromDb() {
Connection con = null;
try {
con = DatabaseConnection.getConnection();
loadExistentCashIdsFromQuery(con, "SELECT id FROM rings");
loadExistentCashIdsFromQuery(con, "SELECT petid FROM pets");
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
try {
if (con != null && !con.isClosed()) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
runningCashid = 0;
do {
runningCashid++; // hopefully the id will never surpass the allotted amount for pets/rings?
} while (existentCashids.contains(runningCashid));
}
private static void getNextAvailableCashId() {
runningCashid++;
if (runningCashid >= 777000000) {
existentCashids.clear();
loadExistentCashIdsFromDb();
}
}
public static synchronized int generateCashId() {
while (true) {
if (!existentCashids.contains(runningCashid)) {
int ret = runningCashid;
getNextAvailableCashId();
// existentCashids.add(ret)... no need to do this since the wrap over already refetches already used cashids from the DB
return ret;
}
getNextAvailableCashId();
}
}
public static synchronized void freeCashId(int cashId) {
existentCashids.remove(cashId);
}
}

View File

@@ -520,16 +520,18 @@ public class MapleInventoryManipulator {
//1112413, 1112414, 1112405 (Lilin's Ring)
source = (Equip) eqpInv.getItem(src);
Equip target = (Equip) eqpdInv.getItem(dst);
eqpInv.removeSlot(src);
if (target != null) {
eqpdInv.lockInventory();
try {
Equip target;
eqpdInv.lockInventory();
try {
target = (Equip) eqpdInv.getItem(dst);
if (target != null) {
chr.unequippedItem(target);
eqpdInv.removeSlot(dst);
} finally {
eqpdInv.unlockInventory();
}
} finally {
eqpdInv.unlockInventory();
}
final List<ModifyInventory> mods = new ArrayList<>();
@@ -705,7 +707,7 @@ public class MapleInventoryManipulator {
}
private static boolean isDroppedItemRestricted(Item it) {
return ServerConstants.USE_ERASE_UNTRADEABLE_DROP && ((it.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE);
return ServerConstants.USE_ERASE_UNTRADEABLE_DROP && it.isUntradeable();
}
public static boolean isSandboxItem(Item it) {

View File

@@ -43,7 +43,7 @@ public class AssignSPProcessor {
c.lockClient();
try {
if (skillid == Aran.HIDDEN_FULL_DOUBLE || skillid == Aran.HIDDEN_FULL_TRIPLE || skillid == Aran.HIDDEN_OVER_DOUBLE || skillid == Aran.HIDDEN_OVER_TRIPLE) {
c.getSession().write(MaplePacketCreator.enableActions());
c.announce(MaplePacketCreator.enableActions());
return;
}

View File

@@ -21,16 +21,13 @@ package client.processor;
import client.MapleClient;
import client.MapleCharacter;
import client.MapleStat;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import server.maps.MapleMap;
import server.movement.AbsoluteLifeMovement;
import server.movement.LifeMovementFragment;
import tools.MaplePacketCreator;
import tools.Pair;
/**
*

View File

@@ -345,167 +345,171 @@ public class DueyProcessor {
}
public static void dueySendItem(MapleClient c, byte inventId, short itemPos, short amount, int mesos, String recipient) {
c.lockClient();
try {
final int fee = 5000;
final long sendMesos = (long) mesos + fee;
if (mesos < 0 || sendMesos > Integer.MAX_VALUE || (amount < 1 && mesos == 0)) {
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with duey.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with mesos " + mesos + " and amount " + amount + "\r\n");
c.disconnect(true, false);
return;
}
int finalcost = mesos + fee;
if (c.getPlayer().getMeso() >= finalcost) {
int accid = getAccIdFromCNAME(recipient, true);
if (accid != -1) {
if (accid == c.getAccID()) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SAMEACC_ERROR.getCode()));
if (c.tryacquireClient()) {
try {
final int fee = 5000;
final long sendMesos = (long) mesos + fee;
if (mesos < 0 || sendMesos > Integer.MAX_VALUE || (amount < 1 && mesos == 0)) {
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with duey.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to use duey with mesos " + mesos + " and amount " + amount + "\r\n");
c.disconnect(true, false);
return;
}
int finalcost = mesos + fee;
if (c.getPlayer().getMeso() >= finalcost) {
int accid = getAccIdFromCNAME(recipient, true);
if (accid != -1) {
if (accid == c.getAccID()) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SAMEACC_ERROR.getCode()));
return;
}
} else {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NAME_DOES_NOT_EXIST.getCode()));
return;
}
} else {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NAME_DOES_NOT_EXIST.getCode()));
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NOT_ENOUGH_MESOS.getCode()));
return;
}
} else {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_NOT_ENOUGH_MESOS.getCode()));
return;
}
MapleClient rClient = null;
int channel = c.getWorldServer().find(recipient);
if (channel > -1) {
Channel rcserv = c.getWorldServer().getChannel(channel);
if(rcserv != null) {
MapleCharacter rChr = rcserv.getPlayerStorage().getCharacterByName(recipient);
if(rChr != null) {
rClient = rChr.getClient();
MapleClient rClient = null;
int channel = c.getWorldServer().find(recipient);
if (channel > -1) {
Channel rcserv = c.getWorldServer().getChannel(channel);
if(rcserv != null) {
MapleCharacter rChr = rcserv.getPlayerStorage().getCharacterByName(recipient);
if(rChr != null) {
rClient = rChr.getClient();
}
}
}
}
if (inventId > 0) {
MapleInventoryType inv = MapleInventoryType.getByType(inventId);
Item item = c.getPlayer().getInventory(inv).getItem(itemPos);
if (item != null && c.getPlayer().getItemQuantity(item.getItemId(), false) >= amount) {
c.getPlayer().gainMeso(-finalcost, false);
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
if (ItemConstants.isRechargeable(item.getItemId())) {
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, item.getQuantity(), true);
if (inventId > 0) {
MapleInventoryType inv = MapleInventoryType.getByType(inventId);
Item item = c.getPlayer().getInventory(inv).getItem(itemPos);
if (item != null && c.getPlayer().getItemQuantity(item.getItemId(), false) >= amount) {
c.getPlayer().gainMeso(-finalcost, false);
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
if (ItemConstants.isRechargeable(item.getItemId())) {
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, item.getQuantity(), true);
} else {
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, amount, true, false);
}
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
addItemToDB(item, amount, mesos - getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
} else {
MapleInventoryManipulator.removeFromSlot(c, inv, itemPos, amount, true, false);
if (item != null) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
}
return;
}
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
addItemToDB(item, amount, mesos - getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
} else {
if (item != null) {
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_INCORRECT_REQUEST.getCode()));
}
return;
c.getPlayer().gainMeso(-finalcost, false);
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
addMesoToDB(mesos - getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
}
} else {
c.getPlayer().gainMeso(-finalcost, false);
c.announce(MaplePacketCreator.sendDueyMSG(DueyProcessor.Actions.TOCLIENT_SEND_SUCCESSFULLY_SENT.getCode()));
addMesoToDB(mesos - getFee(mesos), c.getPlayer().getName(), getAccIdFromCNAME(recipient, false));
if (rClient != null && rClient.isLoggedIn() && !rClient.getPlayer().isAwayFromWorld()) {
showDueyNotification(rClient, rClient.getPlayer());
}
} finally {
c.releaseClient();
}
if (rClient != null && rClient.isLoggedIn() && !rClient.getPlayer().isAwayFromWorld()) {
showDueyNotification(rClient, rClient.getPlayer());
}
} finally {
c.unlockClient();
}
}
public static void dueyRemovePackage(MapleClient c, int packageid) {
c.lockClient();
try {
removeItemFromDB(packageid);
c.announce(MaplePacketCreator.removeItemFromDuey(true, packageid));
} finally {
c.unlockClient();
if (c.tryacquireClient()) {
try {
removeItemFromDB(packageid);
c.announce(MaplePacketCreator.removeItemFromDuey(true, packageid));
} finally {
c.releaseClient();
}
}
}
public static void dueyClaimPackage(MapleClient c, int packageid) {
c.lockClient();
try {
List<DueyPackages> packages = new LinkedList<>();
DueyPackages dp = null;
Connection con = null;
if (c.tryacquireClient()) {
try {
con = DatabaseConnection.getConnection();
DueyPackages dueypack;
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages LEFT JOIN dueyitems USING (PackageId) WHERE PackageId = ?")) {
ps.setInt(1, packageid);
try (ResultSet rs = ps.executeQuery()) {
dueypack = null;
if (rs.next()) {
dueypack = getItemByPID(rs);
dueypack.setSender(rs.getString("SenderName"));
dueypack.setMesos(rs.getInt("Mesos"));
dueypack.setSentTime(rs.getString("TimeStamp"));
List<DueyPackages> packages = new LinkedList<>();
DueyPackages dp = null;
Connection con = null;
try {
con = DatabaseConnection.getConnection();
DueyPackages dueypack;
try (PreparedStatement ps = con.prepareStatement("SELECT * FROM dueypackages LEFT JOIN dueyitems USING (PackageId) WHERE PackageId = ?")) {
ps.setInt(1, packageid);
try (ResultSet rs = ps.executeQuery()) {
dueypack = null;
if (rs.next()) {
dueypack = getItemByPID(rs);
dueypack.setSender(rs.getString("SenderName"));
dueypack.setMesos(rs.getInt("Mesos"));
dueypack.setSentTime(rs.getString("TimeStamp"));
packages.add(dueypack);
packages.add(dueypack);
}
}
}
}
dp = dueypack;
if(dp == null) {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to receive package from duey with id " + packageid + "\r\n");
return;
}
if (dp.getItem() != null) {
if (!MapleInventoryManipulator.checkSpace(c, dp.getItem().getItemId(), dp.getItem().getQuantity(), dp.getItem().getOwner())) {
int itemid = dp.getItem().getItemId();
if(MapleItemInformationProvider.getInstance().isPickupRestricted(itemid) && c.getPlayer().getInventory(ItemConstants.getInventoryType(itemid)).findById(itemid) != null) {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_RECEIVER_WITH_UNIQUE.getCode()));
} else {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_NO_FREE_SLOTS.getCode()));
}
dp = dueypack;
if(dp == null) {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_UNKNOWN_ERROR.getCode()));
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to receive package from duey with id " + packageid + "\r\n");
return;
} else {
MapleInventoryManipulator.addFromDrop(c, dp.getItem(), false);
}
if (dp.getItem() != null) {
if (!MapleInventoryManipulator.checkSpace(c, dp.getItem().getItemId(), dp.getItem().getQuantity(), dp.getItem().getOwner())) {
int itemid = dp.getItem().getItemId();
if(MapleItemInformationProvider.getInstance().isPickupRestricted(itemid) && c.getPlayer().getInventory(ItemConstants.getInventoryType(itemid)).findById(itemid) != null) {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_RECEIVER_WITH_UNIQUE.getCode()));
} else {
c.announce(MaplePacketCreator.sendDueyMSG(Actions.TOCLIENT_RECV_NO_FREE_SLOTS.getCode()));
}
return;
} else {
MapleInventoryManipulator.addFromDrop(c, dp.getItem(), false);
}
}
long gainmesos;
long totalmesos = (long) dp.getMesos() + c.getPlayer().getMeso();
if (totalmesos < 0 || dp.getMesos() < 0) {
gainmesos = 0;
} else {
totalmesos = Math.min(totalmesos, Integer.MAX_VALUE);
gainmesos = totalmesos - c.getPlayer().getMeso();
}
c.getPlayer().gainMeso((int)gainmesos, false);
removeItemFromDB(packageid);
c.announce(MaplePacketCreator.removeItemFromDuey(false, packageid));
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
long gainmesos;
long totalmesos = (long) dp.getMesos() + c.getPlayer().getMeso();
if (totalmesos < 0 || dp.getMesos() < 0) {
gainmesos = 0;
} else {
totalmesos = Math.min(totalmesos, Integer.MAX_VALUE);
gainmesos = totalmesos - c.getPlayer().getMeso();
}
c.getPlayer().gainMeso((int)gainmesos, false);
removeItemFromDB(packageid);
c.announce(MaplePacketCreator.removeItemFromDuey(false, packageid));
con.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
c.releaseClient();
}
} finally {
c.unlockClient();
}
}
public static void dueySendTalk(MapleClient c) {
c.lockClient();
try {
c.announce(MaplePacketCreator.sendDuey((byte) 8, loadItems(c.getPlayer())));
} finally {
c.unlockClient();
if (c.tryacquireClient()) {
try {
c.announce(MaplePacketCreator.sendDuey((byte) 8, loadItems(c.getPlayer())));
} finally {
c.releaseClient();
}
}
}
}

View File

@@ -70,42 +70,43 @@ public class FredrickProcessor {
}
public static void fredrickRetrieveItems(MapleClient c) { // thanks Gustav for pointing out the dupe on Fredrick handling
c.lockClient();
try {
MapleCharacter chr = c.getPlayer();
List<Pair<Item, MapleInventoryType>> items;
if (c.tryacquireClient()) {
try {
items = ItemFactory.MERCHANT.loadItems(chr.getId(), false);
if (!canRetrieveFromFredrick(chr, items)) {
chr.announce(MaplePacketCreator.fredrickMessage((byte) 0x21));
return;
}
MapleCharacter chr = c.getPlayer();
chr.withdrawMerchantMesos();
if (deleteFredrickItems(chr.getId())) {
MapleHiredMerchant merchant = chr.getHiredMerchant();
if(merchant != null)
merchant.clearItems();
for (Pair<Item, MapleInventoryType> it : items) {
Item item = it.getLeft();
MapleInventoryManipulator.addFromDrop(chr.getClient(), item, false);
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.FREDRICK + chr.getName() + ".txt", chr.getName() + " gained " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
List<Pair<Item, MapleInventoryType>> items;
try {
items = ItemFactory.MERCHANT.loadItems(chr.getId(), false);
if (!canRetrieveFromFredrick(chr, items)) {
chr.announce(MaplePacketCreator.fredrickMessage((byte) 0x21));
return;
}
chr.announce(MaplePacketCreator.fredrickMessage((byte) 0x1E));
} else {
chr.message("An unknown error has occured.");
chr.withdrawMerchantMesos();
if (deleteFredrickItems(chr.getId())) {
MapleHiredMerchant merchant = chr.getHiredMerchant();
if(merchant != null)
merchant.clearItems();
for (Pair<Item, MapleInventoryType> it : items) {
Item item = it.getLeft();
MapleInventoryManipulator.addFromDrop(chr.getClient(), item, false);
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.FREDRICK + chr.getName() + ".txt", chr.getName() + " gained " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
}
chr.announce(MaplePacketCreator.fredrickMessage((byte) 0x1E));
} else {
chr.message("An unknown error has occured.");
}
} catch (SQLException ex) {
ex.printStackTrace();
}
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
c.releaseClient();
}
} finally {
c.unlockClient();
}
}
}

View File

@@ -26,7 +26,6 @@ import client.inventory.MapleInventoryType;
import constants.ItemConstants;
import constants.ServerConstants;
import client.inventory.manipulator.MapleInventoryManipulator;
import constants.EquipType;
import constants.GameConstants;
import java.util.LinkedHashMap;
import java.util.LinkedList;
@@ -47,168 +46,169 @@ public class MakerProcessor {
private static MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
public static void makerAction(SeekableLittleEndianAccessor slea, MapleClient c) {
c.lockClient();
try {
int type = slea.readInt();
int toCreate = slea.readInt();
int toDisassemble = -1, pos = -1;
boolean makerSucceeded = true;
if (c.tryacquireClient()) {
try {
int type = slea.readInt();
int toCreate = slea.readInt();
int toDisassemble = -1, pos = -1;
boolean makerSucceeded = true;
MakerItemFactory.MakerItemCreateEntry recipe;
Map<Integer, Short> reagentids = new LinkedHashMap<>();
int stimulantid = -1;
MakerItemFactory.MakerItemCreateEntry recipe;
Map<Integer, Short> reagentids = new LinkedHashMap<>();
int stimulantid = -1;
if(type == 3) { // building monster crystal
int fromLeftover = toCreate;
toCreate = ii.getMakerCrystalFromLeftover(toCreate);
if(toCreate == -1) {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal conversion."));
return;
}
if(type == 3) { // building monster crystal
int fromLeftover = toCreate;
toCreate = ii.getMakerCrystalFromLeftover(toCreate);
if(toCreate == -1) {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal conversion."));
return;
}
recipe = MakerItemFactory.generateLeftoverCrystalEntry(fromLeftover);
} else if(type == 4) { // disassembling
slea.readInt(); // 1... probably inventory type
pos = slea.readInt();
recipe = MakerItemFactory.generateLeftoverCrystalEntry(fromLeftover);
} else if(type == 4) { // disassembling
slea.readInt(); // 1... probably inventory type
pos = slea.readInt();
Item it = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((short) pos);
if(it != null && it.getItemId() == toCreate) {
Pair<Integer, Integer> p;
Item it = c.getPlayer().getInventory(MapleInventoryType.EQUIP).getItem((short) pos);
if(it != null && it.getItemId() == toCreate) {
Pair<Integer, Integer> p;
if((p = generateDisassemblyInfo(toCreate)) != null) {
recipe = MakerItemFactory.generateDisassemblyCrystalEntry(p.getLeft(), p.getRight());
toDisassemble = toCreate;
toCreate = ii.getMakerCrystalFromEquip(toCreate);
if((p = generateDisassemblyInfo(toCreate)) != null) {
recipe = MakerItemFactory.generateDisassemblyCrystalEntry(p.getLeft(), p.getRight());
toDisassemble = toCreate;
toCreate = ii.getMakerCrystalFromEquip(toCreate);
} else {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal disassembly."));
return;
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, ii.getName(toCreate) + " is unavailable for Monster Crystal disassembly."));
c.announce(MaplePacketCreator.serverNotice(1, "An unknown error occurred when trying to apply that item for disassembly."));
return;
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, "An unknown error occurred when trying to apply that item for disassembly."));
return;
}
} else {
if(ItemConstants.isEquipment(toCreate)) { // only equips uses stimulant and reagents
if(slea.readByte() != 0) { // stimulant
stimulantid = ii.getMakerStimulant(toCreate);
if(!c.getAbstractPlayerInteraction().haveItem(stimulantid)) {
stimulantid = -1;
}
}
int reagents = Math.min(slea.readInt(), getMakerReagentSlots(toCreate));
for(int i = 0; i < reagents; i++) { // crystals
int reagentid = slea.readInt();
if(ItemConstants.isMakerReagent(reagentid)) {
Short rs = reagentids.get(reagentid);
if(rs == null) {
reagentids.put(reagentid, (short) 1);
} else {
reagentids.put(reagentid, (short) (rs + 1));
if(ItemConstants.isEquipment(toCreate)) { // only equips uses stimulant and reagents
if(slea.readByte() != 0) { // stimulant
stimulantid = ii.getMakerStimulant(toCreate);
if(!c.getAbstractPlayerInteraction().haveItem(stimulantid)) {
stimulantid = -1;
}
}
}
List<Pair<Integer, Short>> toUpdate = new LinkedList<>();
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
int qty = c.getAbstractPlayerInteraction().getItemQuantity(r.getKey());
if(qty < r.getValue()) {
toUpdate.add(new Pair<>(r.getKey(), (short) qty));
}
}
// remove those not present on player inventory
if(!toUpdate.isEmpty()) {
for(Pair<Integer, Short> rp : toUpdate) {
if(rp.getRight() > 0) {
reagentids.put(rp.getLeft(), rp.getRight());
} else {
reagentids.remove(rp.getLeft());
}
}
}
if(!reagentids.isEmpty()) {
if(!removeOddMakerReagents(toCreate, reagentids)) {
c.announce(MaplePacketCreator.serverNotice(1, "You can only use WATK and MATK Strengthening Gems on weapon items."));
return;
}
}
}
recipe = MakerItemFactory.getItemCreateEntry(toCreate, stimulantid, reagentids);
}
short createStatus = getCreateStatus(c, recipe);
switch(createStatus) {
case -1:// non-available for Maker itemid has been tried to forge
FilePrinter.printError(FilePrinter.EXPLOITS, "Player " + c.getPlayer().getName() + " tried to craft itemid " + toCreate + " using the Maker skill.");
c.announce(MaplePacketCreator.serverNotice(1, "The requested item could not be crafted on this operation."));
break;
case 1: // no items
c.announce(MaplePacketCreator.serverNotice(1, "You don't have all required items in your inventory to make " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
break;
case 2: // no meso
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough mesos (" + GameConstants.numberWithCommas(recipe.getCost()) + ") to complete this operation."));
break;
case 3: // no req level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough level to complete this operation."));
break;
case 4: // no req skill level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough Maker level to complete this operation."));
break;
default:
if (MapleInventoryManipulator.checkSpace(c, toCreate, (short) recipe.getRewardAmount(), "")) {
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), (short) -p.getRight());
}
if(toDisassemble != -1) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (short) pos, (short) 1, false);
c.announce(MaplePacketCreator.getShowItemGain(toDisassemble, (short) -1, true));
}
int cost = recipe.getCost();
if(stimulantid == -1 && reagentids.isEmpty()) {
if(cost > 0) c.getPlayer().gainMeso(-cost);
c.getPlayer().setCS(true);
c.getAbstractPlayerInteraction().gainItem(toCreate, (short) recipe.getRewardAmount());
c.getPlayer().setCS(false);
} else {
if(stimulantid != -1) c.getAbstractPlayerInteraction().gainItem(stimulantid, (short) -1);
if(!reagentids.isEmpty()) {
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
c.getAbstractPlayerInteraction().gainItem(r.getKey(), (short) (-1 * r.getValue()));
int reagents = Math.min(slea.readInt(), getMakerReagentSlots(toCreate));
for(int i = 0; i < reagents; i++) { // crystals
int reagentid = slea.readInt();
if(ItemConstants.isMakerReagent(reagentid)) {
Short rs = reagentids.get(reagentid);
if(rs == null) {
reagentids.put(reagentid, (short) 1);
} else {
reagentids.put(reagentid, (short) (rs + 1));
}
}
if(cost > 0) c.getPlayer().gainMeso(-cost);
makerSucceeded = addBoostedMakerItem(c, toCreate, stimulantid, reagentids);
}
if(makerSucceeded) c.announce(MaplePacketCreator.serverNotice(1, "You have successfully created " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
else c.getPlayer().dropMessage(5, "The Maker skill lights up, but the skill winds up as if nothing happened.");
List<Pair<Integer, Short>> toUpdate = new LinkedList<>();
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
int qty = c.getAbstractPlayerInteraction().getItemQuantity(r.getKey());
c.announce(MaplePacketCreator.showMakerEffect(makerSucceeded));
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignMakerEffect(c.getPlayer().getId(), makerSucceeded), false);
if(toCreate == 4260003 && c.getPlayer().getQuestStatus(6033) == 1) {
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
if(qty < r.getValue()) {
toUpdate.add(new Pair<>(r.getKey(), (short) qty));
}
}
// remove those not present on player inventory
if(!toUpdate.isEmpty()) {
for(Pair<Integer, Short> rp : toUpdate) {
if(rp.getRight() > 0) {
reagentids.put(rp.getLeft(), rp.getRight());
} else {
reagentids.remove(rp.getLeft());
}
}
}
if(!reagentids.isEmpty()) {
if(!removeOddMakerReagents(toCreate, reagentids)) {
c.announce(MaplePacketCreator.serverNotice(1, "You can only use WATK and MATK Strengthening Gems on weapon items."));
return;
}
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
}
recipe = MakerItemFactory.getItemCreateEntry(toCreate, stimulantid, reagentids);
}
short createStatus = getCreateStatus(c, recipe);
switch(createStatus) {
case -1:// non-available for Maker itemid has been tried to forge
FilePrinter.printError(FilePrinter.EXPLOITS, "Player " + c.getPlayer().getName() + " tried to craft itemid " + toCreate + " using the Maker skill.");
c.announce(MaplePacketCreator.serverNotice(1, "The requested item could not be crafted on this operation."));
break;
case 1: // no items
c.announce(MaplePacketCreator.serverNotice(1, "You don't have all required items in your inventory to make " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
break;
case 2: // no meso
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough mesos (" + GameConstants.numberWithCommas(recipe.getCost()) + ") to complete this operation."));
break;
case 3: // no req level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough level to complete this operation."));
break;
case 4: // no req skill level
c.announce(MaplePacketCreator.serverNotice(1, "You don't have enough Maker level to complete this operation."));
break;
default:
if (MapleInventoryManipulator.checkSpace(c, toCreate, (short) recipe.getRewardAmount(), "")) {
for (Pair<Integer, Integer> p : recipe.getReqItems()) {
c.getAbstractPlayerInteraction().gainItem(p.getLeft(), (short) -p.getRight());
}
if(toDisassemble != -1) {
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.EQUIP, (short) pos, (short) 1, false);
c.announce(MaplePacketCreator.getShowItemGain(toDisassemble, (short) -1, true));
}
int cost = recipe.getCost();
if(stimulantid == -1 && reagentids.isEmpty()) {
if(cost > 0) c.getPlayer().gainMeso(-cost);
c.getPlayer().setCS(true);
c.getAbstractPlayerInteraction().gainItem(toCreate, (short) recipe.getRewardAmount());
c.getPlayer().setCS(false);
} else {
if(stimulantid != -1) c.getAbstractPlayerInteraction().gainItem(stimulantid, (short) -1);
if(!reagentids.isEmpty()) {
for(Map.Entry<Integer, Short> r : reagentids.entrySet()) {
c.getAbstractPlayerInteraction().gainItem(r.getKey(), (short) (-1 * r.getValue()));
}
}
if(cost > 0) c.getPlayer().gainMeso(-cost);
makerSucceeded = addBoostedMakerItem(c, toCreate, stimulantid, reagentids);
}
if(makerSucceeded) c.announce(MaplePacketCreator.serverNotice(1, "You have successfully created " + recipe.getRewardAmount() + " " + ii.getName(toCreate) + "."));
else c.getPlayer().dropMessage(5, "The Maker skill lights up, but the skill winds up as if nothing happened.");
c.announce(MaplePacketCreator.showMakerEffect(makerSucceeded));
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showForeignMakerEffect(c.getPlayer().getId(), makerSucceeded), false);
if(toCreate == 4260003 && c.getPlayer().getQuestStatus(6033) == 1) {
c.getAbstractPlayerInteraction().setQuestProgress(6033, 1);
}
} else {
c.announce(MaplePacketCreator.serverNotice(1, "Your inventory is full."));
}
}
} finally {
c.releaseClient();
}
} finally {
c.unlockClient();
}
}

View File

@@ -40,60 +40,61 @@ public class SpawnPetProcessor {
private static MapleDataProvider dataRoot = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Item.wz"));
public static void processSpawnPet(MapleClient c, byte slot, boolean lead) {
c.lockClient();
try {
MapleCharacter chr = c.getPlayer();
MaplePet pet = chr.getInventory(MapleInventoryType.CASH).getItem(slot).getPet();
if (pet == null) return;
if (c.tryacquireClient()) {
try {
MapleCharacter chr = c.getPlayer();
MaplePet pet = chr.getInventory(MapleInventoryType.CASH).getItem(slot).getPet();
if (pet == null) return;
int petid = pet.getItemId();
if (petid == 5000028 || petid == 5000047) //Handles Dragon AND Robos
{
if (chr.haveItem(petid + 1)) {
chr.dropMessage(5, "You can't hatch your " + (petid == 5000028 ? "Dragon egg" : "Robo egg") + " if you already have a Baby " + (petid == 5000028 ? "Dragon." : "Robo."));
c.announce(MaplePacketCreator.enableActions());
return;
} else {
int evolveid = MapleDataTool.getInt("info/evol1", dataRoot.getData("Pet/" + petid + ".img"));
int petId = MaplePet.createPet(evolveid);
if (petId == -1) {
int petid = pet.getItemId();
if (petid == 5000028 || petid == 5000047) //Handles Dragon AND Robos
{
if (chr.haveItem(petid + 1)) {
chr.dropMessage(5, "You can't hatch your " + (petid == 5000028 ? "Dragon egg" : "Robo egg") + " if you already have a Baby " + (petid == 5000028 ? "Dragon." : "Robo."));
c.announce(MaplePacketCreator.enableActions());
return;
} else {
int evolveid = MapleDataTool.getInt("info/evol1", dataRoot.getData("Pet/" + petid + ".img"));
int petId = MaplePet.createPet(evolveid);
if (petId == -1) {
return;
}
long expiration = chr.getInventory(MapleInventoryType.CASH).getItem(slot).getExpiration();
MapleInventoryManipulator.removeById(c, MapleInventoryType.CASH, petid, (short) 1, false, false);
MapleInventoryManipulator.addById(c, evolveid, (short) 1, null, petId, expiration);
pet.deleteFromDb();
c.announce(MaplePacketCreator.enableActions());
return;
}
long expiration = chr.getInventory(MapleInventoryType.CASH).getItem(slot).getExpiration();
MapleInventoryManipulator.removeById(c, MapleInventoryType.CASH, petid, (short) 1, false, false);
MapleInventoryManipulator.addById(c, evolveid, (short) 1, null, petId, expiration);
pet.deleteFromDb();
}
if (chr.getPetIndex(pet) != -1) {
chr.unequipPet(pet, true);
} else {
if (chr.getSkillLevel(SkillFactory.getSkill(8)) == 0 && chr.getPet(0) != null) {
chr.unequipPet(chr.getPet(0), false);
}
if (lead) {
chr.shiftPetsRight();
}
Point pos = chr.getPosition();
pos.y -= 12;
pet.setPos(pos);
pet.setFh(chr.getMap().getFootholds().findBelow(pet.getPos()).getId());
pet.setStance(0);
pet.setSummoned(true);
pet.saveToDb();
chr.addPet(pet);
chr.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showPet(c.getPlayer(), pet, false, false), true);
c.announce(MaplePacketCreator.petStatUpdate(c.getPlayer()));
c.announce(MaplePacketCreator.enableActions());
return;
}
}
if (chr.getPetIndex(pet) != -1) {
chr.unequipPet(pet, true);
} else {
if (chr.getSkillLevel(SkillFactory.getSkill(8)) == 0 && chr.getPet(0) != null) {
chr.unequipPet(chr.getPet(0), false);
}
if (lead) {
chr.shiftPetsRight();
}
Point pos = chr.getPosition();
pos.y -= 12;
pet.setPos(pos);
pet.setFh(chr.getMap().getFootholds().findBelow(pet.getPos()).getId());
pet.setStance(0);
pet.setSummoned(true);
pet.saveToDb();
chr.addPet(pet);
chr.getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showPet(c.getPlayer(), pet, false, false), true);
c.announce(MaplePacketCreator.petStatUpdate(c.getPlayer()));
c.announce(MaplePacketCreator.enableActions());
chr.commitExcludedItems();
chr.getClient().getWorldServer().registerPetHunger(chr, chr.getPetIndex(pet));
chr.commitExcludedItems();
chr.getClient().getWorldServer().registerPetHunger(chr, chr.getPetIndex(pet));
}
} finally {
c.releaseClient();
}
} finally {
c.unlockClient();
}
}
}

View File

@@ -54,123 +54,124 @@ public class StorageProcessor {
return;
}
c.lockClient();
try {
if (mode == 4) { // take out
byte type = slea.readByte();
byte slot = slea.readByte();
if (slot < 0 || slot > storage.getSlots()) { // removal starts at zero
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to work with storage slot " + slot + "\r\n");
c.disconnect(true, false);
return;
}
slot = storage.getSlot(MapleInventoryType.getByType(type), slot);
Item item = storage.getItem(slot);
if (item != null) {
if (MapleItemInformationProvider.getInstance().isPickupRestricted(item.getItemId()) && chr.haveItemWithId(item.getItemId(), true)) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0C));
if (c.tryacquireClient()) {
try {
if (mode == 4) { // take out
byte type = slea.readByte();
byte slot = slea.readByte();
if (slot < 0 || slot > storage.getSlots()) { // removal starts at zero
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to work with storage slot " + slot + "\r\n");
c.disconnect(true, false);
return;
}
int takeoutFee = storage.getTakeOutFee();
if (chr.getMeso() < takeoutFee) {
slot = storage.getSlot(MapleInventoryType.getByType(type), slot);
Item item = storage.getItem(slot);
if (item != null) {
if (MapleItemInformationProvider.getInstance().isPickupRestricted(item.getItemId()) && chr.haveItemWithId(item.getItemId(), true)) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0C));
return;
}
int takeoutFee = storage.getTakeOutFee();
if (chr.getMeso() < takeoutFee) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0B));
return;
} else {
chr.gainMeso(-takeoutFee, false);
}
if (MapleInventoryManipulator.checkSpace(c, item.getItemId(), item.getQuantity(), item.getOwner())) {
item = storage.takeOut(slot);//actually the same but idc
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " took out " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
chr.setUsedStorage();
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
MapleInventoryManipulator.addFromDrop(c, item, false);
storage.sendTakenOut(c, item.getInventoryType());
} else {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0A));
}
}
} else if (mode == 5) { // store
short slot = slea.readShort();
int itemId = slea.readInt();
short quantity = slea.readShort();
MapleInventoryType slotType = ItemConstants.getInventoryType(itemId);
MapleInventory Inv = chr.getInventory(slotType);
if (slot < 1 || slot > Inv.getSlotLimit()) { //player inv starts at one
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to store item at slot " + slot + "\r\n");
c.disconnect(true, false);
return;
}
if (quantity < 1 || chr.getItemQuantity(itemId, false) < quantity) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if (storage.isFull()) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x11));
return;
}
int storeFee = storage.getStoreFee();
if (chr.getMeso() < storeFee) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0B));
} else {
MapleInventoryType invType = ItemConstants.getInventoryType(itemId);
Item item = chr.getInventory(invType).getItem(slot).copy();
if (item != null && item.getItemId() == itemId && (item.getQuantity() >= quantity || ItemConstants.isRechargeable(itemId))) {
if (ItemConstants.isRechargeable(itemId)) {
quantity = item.getQuantity();
}
chr.gainMeso(-storeFee, false, true, false);
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
MapleInventoryManipulator.removeFromSlot(c, invType, slot, quantity, false);
item.setQuantity(quantity);
storage.store(item);
storage.sendStored(c, ItemConstants.getInventoryType(itemId));
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " stored " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
chr.setUsedStorage();
}
}
} else if (mode == 6) { // arrange items
if(ServerConstants.USE_STORAGE_ITEM_SORT) storage.arrangeItems(c);
c.announce(MaplePacketCreator.enableActions());
} else if (mode == 7) { // meso
int meso = slea.readInt();
int storageMesos = storage.getMeso();
int playerMesos = chr.getMeso();
if ((meso > 0 && storageMesos >= meso) || (meso < 0 && playerMesos >= -meso)) {
if (meso < 0 && (storageMesos - meso) < 0) {
meso = Integer.MIN_VALUE + storageMesos;
if (meso < playerMesos) {
c.announce(MaplePacketCreator.enableActions());
return;
}
} else if (meso > 0 && (playerMesos + meso) < 0) {
meso = Integer.MAX_VALUE - playerMesos;
if (meso > storageMesos) {
c.announce(MaplePacketCreator.enableActions());
return;
}
}
storage.setMeso(storageMesos - meso);
chr.gainMeso(meso, false, true, false);
FilePrinter.print(FilePrinter.STORAGE + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + (meso > 0 ? " took out " : " stored ") + Math.abs(meso) + " mesos\r\n");
chr.setUsedStorage();
} else {
c.announce(MaplePacketCreator.enableActions());
return;
} else {
chr.gainMeso(-takeoutFee, false);
}
if (MapleInventoryManipulator.checkSpace(c, item.getItemId(), item.getQuantity(), item.getOwner())) {
item = storage.takeOut(slot);//actually the same but idc
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " took out " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
chr.setUsedStorage();
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
MapleInventoryManipulator.addFromDrop(c, item, false);
storage.sendTakenOut(c, item.getInventoryType());
} else {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0A));
}
storage.sendMeso(c);
} else if (mode == 8) {// close
storage.close();
}
} else if (mode == 5) { // store
short slot = slea.readShort();
int itemId = slea.readInt();
short quantity = slea.readShort();
MapleInventoryType slotType = ItemConstants.getInventoryType(itemId);
MapleInventory Inv = chr.getInventory(slotType);
if (slot < 1 || slot > Inv.getSlotLimit()) { //player inv starts at one
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with storage.");
FilePrinter.print(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to store item at slot " + slot + "\r\n");
c.disconnect(true, false);
return;
}
if (quantity < 1 || chr.getItemQuantity(itemId, false) < quantity) {
c.announce(MaplePacketCreator.enableActions());
return;
}
if (storage.isFull()) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x11));
return;
}
int storeFee = storage.getStoreFee();
if (chr.getMeso() < storeFee) {
c.announce(MaplePacketCreator.getStorageError((byte) 0x0B));
} else {
MapleInventoryType invType = ItemConstants.getInventoryType(itemId);
Item item = chr.getInventory(invType).getItem(slot).copy();
if (item != null && item.getItemId() == itemId && (item.getQuantity() >= quantity || ItemConstants.isRechargeable(itemId))) {
if (ItemConstants.isRechargeable(itemId)) {
quantity = item.getQuantity();
}
chr.gainMeso(-storeFee, false, true, false);
MapleKarmaManipulator.toggleKarmaFlagToUntradeable(item);
MapleInventoryManipulator.removeFromSlot(c, invType, slot, quantity, false);
item.setQuantity(quantity);
storage.store(item);
storage.sendStored(c, ItemConstants.getInventoryType(itemId));
String itemName = MapleItemInformationProvider.getInstance().getName(item.getItemId());
FilePrinter.print(FilePrinter.STORAGE + c.getAccountName() + ".txt", c.getPlayer().getName() + " stored " + item.getQuantity() + " " + itemName + " (" + item.getItemId() + ")\r\n");
chr.setUsedStorage();
}
}
} else if (mode == 6) { // arrange items
if(ServerConstants.USE_STORAGE_ITEM_SORT) storage.arrangeItems(c);
c.announce(MaplePacketCreator.enableActions());
} else if (mode == 7) { // meso
int meso = slea.readInt();
int storageMesos = storage.getMeso();
int playerMesos = chr.getMeso();
if ((meso > 0 && storageMesos >= meso) || (meso < 0 && playerMesos >= -meso)) {
if (meso < 0 && (storageMesos - meso) < 0) {
meso = -2147483648 + storageMesos;
if (meso < playerMesos) {
c.announce(MaplePacketCreator.enableActions());
return;
}
} else if (meso > 0 && (playerMesos + meso) < 0) {
meso = 2147483647 - playerMesos;
if (meso > storageMesos) {
c.announce(MaplePacketCreator.enableActions());
return;
}
}
storage.setMeso(storageMesos - meso);
chr.gainMeso(meso, false, true, false);
FilePrinter.print(FilePrinter.STORAGE + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + (meso > 0 ? " took out " : " stored ") + Math.abs(meso) + " mesos\r\n");
chr.setUsedStorage();
} else {
c.announce(MaplePacketCreator.enableActions());
return;
}
storage.sendMeso(c);
} else if (mode == 8) {// close
storage.close();
} finally {
c.releaseClient();
}
} finally {
c.unlockClient();
}
}
}

View File

@@ -54,6 +54,7 @@ public class ServerConstants {
public static final boolean USE_DEBUG = false; //Will enable some text prints on the client, oriented for debugging purposes.
public static final boolean USE_DEBUG_SHOW_INFO_EQPEXP = false; //Prints on the cmd all equip exp gain info.
public static boolean USE_DEBUG_SHOW_RCVD_PACKET = false; //Prints on the cmd all received packet ids.
public static boolean USE_SUPPLY_RATE_COUPONS = true; //Allows rate coupons to be sold through the Cash Shop.
public static final boolean USE_MAXRANGE = true; //Will send and receive packets from all events on a map, rather than those of only view range.
public static final boolean USE_MAXRANGE_ECHO_OF_HERO = true;
@@ -104,6 +105,7 @@ public class ServerConstants {
//Cash Shop Configuration
public static final boolean USE_JOINT_CASHSHOP_INVENTORY = true;//Enables usage of a same cash shop inventory for explorers, cygnus and legends. Items from exclusive cash shop inventories won't show up on the shared inventory, though.
public static final boolean USE_CLEAR_OUTDATED_COUPONS = true; //Enables deletion of older code coupon registry from the DB, freeing so-long irrelevant data.
//Maker Configuration
public static final boolean USE_MAKER_PERMISSIVE_ATKUP = true; //Allows players to use attack-based strengthening gems on non-weapon items.
@@ -148,7 +150,8 @@ public class ServerConstants {
//Map Monitor Configuration
public static final int ITEM_EXPIRE_CHECK = 10 * 1000; //Interval between item expiring tasks on maps, which checks and makes disappear expired items.
public static final int ITEM_LIMIT_ON_MAP = 200; //Max number of items allowed on a map.
public static final int MAP_VISITED_SIZE = 5; //Max length for last mapids visited by a player. This is used to recover and update drops on these maps accordingly with player actions.
public static final int MAP_VISITED_SIZE = 5; //Max length for last mapids visited by a player. This is used to recover and update drops on these maps accordingly with player actions.
public static final int MAP_DAMAGE_OVERTIME_INTERVAL = 5000;//Interval in seconds between map environment damage (e.g. El Nath and Aqua Road surrondings).
//Channel Mob Disease Monitor Configuration
public static final int MOB_STATUS_MONITOR_PROC = 200; //Frequency in milliseconds between each proc on the mob disease monitor schedule.
@@ -172,7 +175,7 @@ public class ServerConstants {
//Other Skills Configuration
public static final boolean USE_FAST_REUSE_HERO_WILL = true;//Greatly reduce cooldown on Hero's Will.
public static final boolean USE_ANTI_IMMUNITY_CRASH = true; //Crash skills additionally removes the mob's invincibility buffs.
public static final boolean USE_ANTI_IMMUNITY_CRASH = true; //Crash skills additionally removes the mob's invincibility buffs. Suggestion thanks to Celestial.
public static final boolean USE_UNDISPEL_HOLY_SHIELD = true;//Holy shield buff also prevents players from suffering dispel from mobs.
//Character Configuration
@@ -200,6 +203,7 @@ public class ServerConstants {
//Equipment Configuration
public static final boolean USE_EQUIPMNT_LVLUP_SLOTS = true;//Equips can upgrade slots at level up.
public static final boolean USE_EQUIPMNT_LVLUP_POWER = true;//Enable more powerful stat upgrades at equip level up.
public static final boolean USE_EQUIPMNT_LVLUP_CASH = true; //Enable equip leveling up on cash equipments as well.
public static final boolean USE_SPIKES_AVOID_BANISH = true; //Shoes equipped with spikes prevents mobs from banishing wearer.
public static final int MAX_EQUIPMNT_LVLUP_STAT_UP = 10000; //Max stat upgrade an equipment can have on a levelup.
public static final int MAX_EQUIPMNT_STAT = 32767; //Max stat on an equipment by leveling up.

View File

@@ -33,6 +33,5 @@ public class SuperGM {
public static final int HIDE = 9101004;
public static final int RESURRECTION = 9101005;
public static final int SUPER_DRAGON_ROAR = 9001001;
public static final int TELEPORT = 9101007;
public static final int HYPER_BODY = 9101008;
}

View File

@@ -80,6 +80,7 @@ import client.MapleCharacter;
import client.SkillFactory;
import client.inventory.Item;
import client.inventory.ItemFactory;
import client.inventory.manipulator.MapleCashidGenerator;
import client.newyear.NewYearCardRecord;
import constants.ItemConstants;
import constants.GameConstants;
@@ -90,7 +91,6 @@ import server.life.MaplePlayerNPCFactory;
import server.quest.MapleQuest;
import tools.AutoJCE;
import tools.DatabaseConnection;
import tools.FilePrinter;
import tools.Pair;
public class Server {
@@ -518,6 +518,34 @@ public class Server {
return couponRates;
}
public static void cleanNxcodeCoupons(Connection con) throws SQLException {
if (!ServerConstants.USE_CLEAR_OUTDATED_COUPONS) return;
long timeClear = System.currentTimeMillis() - 14 * 24 * 60 * 60 * 1000;
PreparedStatement ps = con.prepareStatement("SELECT * FROM nxcode WHERE expiration <= ?");
ps.setLong(1, timeClear);
ResultSet rs = ps.executeQuery();
if (!rs.isLast()) {
PreparedStatement ps2 = con.prepareStatement("DELETE FROM nxcode_items WHERE codeid = ?");
while (rs.next()) {
ps2.setInt(1, rs.getInt("id"));
ps2.addBatch();
}
ps2.executeBatch();
ps2.close();
ps2 = con.prepareStatement("DELETE FROM nxcode WHERE expiration <= ?");
ps2.setLong(1, timeClear);
ps2.executeUpdate();
ps2.close();
}
rs.close();
ps.close();
}
private void loadCouponRates(Connection c) throws SQLException {
PreparedStatement ps = c.prepareStatement("SELECT couponid, rate FROM nxcoupons");
ResultSet rs = ps.executeQuery();
@@ -818,6 +846,7 @@ public class Server {
ps.executeUpdate();
ps.close();
cleanNxcodeCoupons(c);
loadCouponRates(c);
updateActiveCoupons();
@@ -825,6 +854,9 @@ public class Server {
} catch (SQLException sqle) {
sqle.printStackTrace();
}
MapleCashidGenerator.loadExistentCashIdsFromDb();
IoBuffer.setUseDirectBuffer(false);
IoBuffer.setAllocator(new SimpleBufferAllocator());
acceptor = new NioSocketAcceptor();
@@ -893,17 +925,6 @@ public class Server {
online = true;
}
public void shutdown() {
try {
TimerManager.getInstance().stop();
acceptor.unbind();
} catch (NullPointerException e) {
FilePrinter.printError(FilePrinter.EXCEPTION_CAUGHT, e);
}
System.out.println("Server offline.");
System.exit(0);// BOEIEND :D
}
public static void main(String args[]) {
System.setProperty("wzpath", "wz");
Security.setProperty("crypto.policy", "unlimited");

View File

@@ -198,6 +198,7 @@ public final class Channel {
System.out.println("Shutting down Channel " + channel + " on World " + world);
closeAllMerchants();
disconnectAwayPlayers();
players.disconnectAll();
if(respawnTask != null) {
@@ -314,6 +315,10 @@ public final class Channel {
return world;
}
public World getWorldServer() {
return Server.getInstance().getWorld(world);
}
public void addPlayer(MapleCharacter chr) {
players.addPlayer(chr);
chr.announce(MaplePacketCreator.serverMessage(serverMessage));
@@ -393,6 +398,16 @@ public final class Channel {
public boolean canUninstall() {
return players.getSize() == 0 && playersAway.isEmpty();
}
private void disconnectAwayPlayers() {
World wserv = getWorldServer();
for (Integer cid : playersAway) {
MapleCharacter chr = wserv.getPlayerStorage().getCharacterById(cid);
if (chr != null && chr.isLoggedin()) {
chr.getClient().disconnect(true, false);
}
}
}
public class respawnMaps implements Runnable {
@@ -465,7 +480,7 @@ public final class Channel {
public void setServerMessage(String message) {
this.serverMessage = message;
broadcastPacket(MaplePacketCreator.serverMessage(message));
Server.getInstance().getWorld(world).resetDisabledServerMessages();
getWorldServer().resetDisabledServerMessages();
}
private static String [] getEvents(){
@@ -692,7 +707,7 @@ public final class Channel {
lock.unlock();
}
World wserv = Server.getInstance().getWorld(world);
World wserv = getWorldServer();
Pair<Integer, Integer> coupleId = wserv.getMarriageQueuedCouple(ret);
Pair<Boolean, Set<Integer>> typeGuests = wserv.removeMarriageQueued(ret);
@@ -704,7 +719,7 @@ public final class Channel {
}
public boolean isWeddingReserved(Integer weddingId) {
World wserv = Server.getInstance().getWorld(world);
World wserv = getWorldServer();
lock.lock();
try {
@@ -746,7 +761,7 @@ public final class Channel {
public int pushWeddingReservation(Integer weddingId, boolean cathedral, boolean premium, Integer groomId, Integer brideId) {
if(weddingId == null || isWeddingReserved(weddingId)) return -1;
World wserv = Server.getInstance().getWorld(world);
World wserv = getWorldServer();
wserv.putMarriageQueued(weddingId, cathedral, premium, groomId, brideId);
lock.lock();
@@ -935,7 +950,7 @@ public final class Channel {
public Pair<Integer, Integer> getWeddingCoupleForGuest(int guestId, boolean cathedral) {
lock.lock();
try {
return (isOngoingWeddingGuest(cathedral, guestId)) ? Server.getInstance().getWorld(world).getRelationshipCouple(getOngoingWedding(cathedral)) : null;
return (isOngoingWeddingGuest(cathedral, guestId)) ? getWorldServer().getRelationshipCouple(getOngoingWedding(cathedral)) : null;
} finally {
lock.unlock();
}
@@ -1038,7 +1053,7 @@ public final class Channel {
public void debugMarriageStatus() {
System.out.println(" ----- WORLD DATA -----");
Server.getInstance().getWorld(world).debugMarriageStatus();
getWorldServer().debugMarriageStatus();
System.out.println(" ----- CH. " + channel + " -----");
System.out.println(" ----- CATHEDRAL -----");

View File

@@ -24,7 +24,6 @@ package net.server.channel.handlers;
import client.MapleClient;
import client.MapleCharacter;
import net.AbstractMaplePacketHandler;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
public final class CancelChairHandler extends AbstractMaplePacketHandler {
@@ -35,21 +34,6 @@ public final class CancelChairHandler extends AbstractMaplePacketHandler {
MapleCharacter mc = c.getPlayer();
if(!mc.isLoggedinWorld()) return;
if (id == -1) { // Cancel Chair
mc.setChair(0);
if(mc.unregisterChairBuff()) {
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.cancelForeignChairSkillEffect(mc.getId()), false);
}
c.announce(MaplePacketCreator.cancelChair(-1));
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showChair(c.getPlayer().getId(), 0), false);
} else { // Use In-Map Chair
mc.setChair(id);
if(mc.registerChairBuff()) {
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.giveForeignChairSkillEffect(mc.getId()), false);
}
c.announce(MaplePacketCreator.cancelChair(id));
}
mc.sitChair(id == -1 ? 0 : id);
}
}

View File

@@ -38,8 +38,10 @@ import server.CashShop;
import server.CashShop.CashItem;
import server.CashShop.CashItemFactory;
import client.inventory.manipulator.MapleInventoryManipulator;
import constants.ServerConstants;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Pair;
import tools.data.input.SeekableLittleEndianAccessor;
public final class CashOperationHandler extends AbstractMaplePacketHandler {
@@ -62,18 +64,20 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
CashItem cItem = CashItemFactory.getItem(snCS);
if (!canBuy(cItem, cs.getCash(useNX))) {
FilePrinter.printError(FilePrinter.ITEM, "Denied to sell cash item with SN " + cItem.getSN());
c.announce(MaplePacketCreator.enableActions());
return;
}
if(ItemConstants.isCashStore(cItem.getItemId()) && chr.getLevel() < 16) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
if (action == 0x03) { // Item
if(ItemConstants.isMapleLife(cItem.getItemId()) && chr.getLevel() < 30) {
c.announce(MaplePacketCreator.enableActions());
if (ItemConstants.isCashStore(cItem.getItemId()) && chr.getLevel() < 16) {
c.enableCSActions();
return;
} else if (ItemConstants.isRateCoupon(cItem.getItemId()) && !ServerConstants.USE_SUPPLY_RATE_COUPONS) {
chr.dropMessage(1, "Rate coupons are currently unavailable to purchase.");
c.enableCSActions();
return;
} else if (ItemConstants.isMapleLife(cItem.getItemId()) && chr.getLevel() < 30) {
c.enableCSActions();
return;
}
@@ -95,20 +99,17 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
Map<String, String> recipient = MapleCharacter.getCharacterFromDatabase(slea.readMapleAsciiString());
String message = slea.readMapleAsciiString();
if (!canBuy(cItem, cs.getCash(4)) || message.length() < 1 || message.length() > 73) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
if (!checkBirthday(c, birthday)) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
c.announce(MaplePacketCreator.enableActions());
return;
} else if (recipient == null) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xA9));
c.announce(MaplePacketCreator.enableActions());
return;
} else if (recipient.get("accountid").equals(String.valueOf(c.getAccID()))) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xA8));
c.announce(MaplePacketCreator.enableActions());
return;
}
cs.gift(Integer.parseInt(recipient.get("id")), chr.getName(), message, cItem.getSN());
@@ -139,7 +140,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
if (mode == 0) {
byte type = slea.readByte();
if (cs.getCash(cash) < 4000) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
if (chr.gainSlots(type, 4, false)) {
@@ -151,7 +152,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
CashItem cItem = CashItemFactory.getItem(slea.readInt());
int type = (cItem.getItemId() - 9110000) / 1000;
if (!canBuy(cItem, cs.getCash(cash))) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
if (chr.gainSlots(type, 8, false)) {
@@ -166,7 +167,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
byte mode = slea.readByte();
if (mode == 0) {
if (cs.getCash(cash) < 4000) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
if (chr.getStorage().gainSlots(4)) {
@@ -181,7 +182,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
CashItem cItem = CashItemFactory.getItem(slea.readInt());
if (!canBuy(cItem, cs.getCash(cash))) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
if (chr.getStorage().gainSlots(8)) {
@@ -196,7 +197,7 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
CashItem cItem = CashItemFactory.getItem(slea.readInt());
if (!canBuy(cItem, cs.getCash(cash))) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
@@ -206,13 +207,13 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
c.announce(MaplePacketCreator.showCash(chr));
} else {
chr.dropMessage(1, "You have already used up all 12 extra character slots.");
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
} else if (action == 0x0D) { // Take from Cash Inventory
Item item = cs.findByCashId(slea.readInt());
if (item == null) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
if (chr.getInventory(item.getInventoryType()).addItem(item) != -1) {
@@ -240,11 +241,11 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
MapleInventory mi = chr.getInventory(MapleInventoryType.getByType(invType));
Item item = mi.findByCashId(cashId);
if (item == null) {
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
} else if(c.getPlayer().getPetIndex(item.getPetId()) > -1) {
chr.getClient().announce(MaplePacketCreator.serverNotice(1, "You cannot put the pet you currently equip into the Cash Shop inventory."));
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}
cs.addToInventory(item);
@@ -265,19 +266,19 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
/* if (partner.getGender() == chr.getGender()) {
chr.dropMessage("You and your partner are the same gender, please buy a friendship ring.");
c.announce(MaplePacketCreator.enableActions());
c.enableCSActions();
return;
}*/ //Gotta let them faggots marry too, hence why this is commented out <3
if(itemRing.toItem() instanceof Equip) {
Equip eqp = (Equip) itemRing.toItem();
int ringid = MapleRing.createRing(itemRing.getItemId(), chr, partner);
eqp.setRingId(ringid);
Pair<Integer, Integer> rings = MapleRing.createRing(itemRing.getItemId(), chr, partner);
eqp.setRingId(rings.getLeft());
cs.addToInventory(eqp);
c.announce(MaplePacketCreator.showBoughtCashItem(eqp, c.getAccID()));
cs.gift(partner.getId(), chr.getName(), text, eqp.getSN(), (ringid + 1));
cs.gift(partner.getId(), chr.getName(), text, eqp.getSN(), rings.getRight());
cs.gainCash(toCharge, itemRing, chr.getWorld());
chr.addCrushRing(MapleRing.loadFromDb(ringid));
chr.addCrushRing(MapleRing.loadFromDb(rings.getLeft()));
try {
chr.sendNote(partner.getName(), text, (byte) 1);
} catch (SQLException ex) {
@@ -288,17 +289,33 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
}
} else {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
c.announce(MaplePacketCreator.enableActions());
}
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
} else if (action == 0x20) { // everything is 1 meso...
int itemId = CashItemFactory.getItem(slea.readInt()).getItemId();
} else if (action == 0x20) {
int serialNumber = slea.readInt(); // thanks GabrielSin for detecting a potential exploit with 1 meso cash items.
if (serialNumber / 10000000 != 8) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC0));
return;
}
if (chr.getMeso() > 0) {
CashItem item = CashItemFactory.getItem(serialNumber);
if (item == null || !item.isOnSale()) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC0));
return;
}
int itemId = item.getItemId();
int itemPrice = item.getPrice();
if (itemPrice <= 0) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC0));
return;
}
if (chr.getMeso() >= itemPrice) {
if (chr.canHold(itemId)) {
chr.gainMeso(-1, false);
MapleInventoryManipulator.addById(c, itemId, (short) 1);
chr.gainMeso(-itemPrice, false);
MapleInventoryManipulator.addById(c, itemId, (short) 1, "", -1);
c.announce(MaplePacketCreator.showBoughtQuestItem(itemId));
}
}
@@ -321,13 +338,13 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
// Need to check to make sure its actually an equip and the right SN...
if(itemRing.toItem() instanceof Equip) {
Equip eqp = (Equip) itemRing.toItem();
int ringid = MapleRing.createRing(itemRing.getItemId(), chr, partner);
eqp.setRingId(ringid);
Pair<Integer, Integer> rings = MapleRing.createRing(itemRing.getItemId(), chr, partner);
eqp.setRingId(rings.getLeft());
cs.addToInventory(eqp);
c.announce(MaplePacketCreator.showBoughtCashItem(eqp, c.getAccID()));
cs.gift(partner.getId(), chr.getName(), text, eqp.getSN(), (ringid + 1));
cs.gift(partner.getId(), chr.getName(), text, eqp.getSN(), rings.getRight());
cs.gainCash(payment, -itemRing.getPrice());
chr.addFriendshipRing(MapleRing.loadFromDb(ringid));
chr.addFriendshipRing(MapleRing.loadFromDb(rings.getLeft()));
try {
chr.sendNote(partner.getName(), text, (byte) 1);
} catch (SQLException ex) {
@@ -338,7 +355,6 @@ public final class CashOperationHandler extends AbstractMaplePacketHandler {
}
} else {
c.announce(MaplePacketCreator.showCashShopMessage((byte) 0xC4));
c.announce(MaplePacketCreator.enableActions());
}
c.announce(MaplePacketCreator.showCash(c.getPlayer()));

View File

@@ -50,7 +50,7 @@ public final class CloseRangeDamageHandler extends AbstractDealDamageHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
chr.setPetLootCd(currentServerTime());
//chr.setPetLootCd(currentServerTime());
/*long timeElapsed = currentServerTime() - chr.getAutobanManager().getLastSpam(8);
if(timeElapsed < 300) {

View File

@@ -4,6 +4,8 @@
Matthias Butz <matze@odinms.de>
Jan Christian Meyer <vimes@odinms.de>
Copyleft (L) 2016 - 2018 RonanLana (HeavenMS)
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
@@ -21,107 +23,228 @@
*/
package net.server.channel.handlers;
import java.sql.SQLException;
import client.MapleClient;
import client.MapleCharacter;
import client.inventory.Item;
import client.inventory.manipulator.MapleInventoryManipulator;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import net.AbstractMaplePacketHandler;
import client.inventory.manipulator.MapleInventoryManipulator;
import net.server.Server;
import server.CashShop;
import server.MapleItemInformationProvider;
import tools.DatabaseConnection;
import tools.FilePrinter;
import tools.MaplePacketCreator;
import tools.Pair;
import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Penguins (Acrylic)
* @author Ronan (HeavenMS)
*/
public final class CouponCodeHandler extends AbstractMaplePacketHandler {
private static List<Pair<Integer, Pair<Integer, Integer>>> getNXCodeItems(MapleCharacter chr, Connection con, int codeid) throws SQLException {
Map<Integer, Integer> couponItems = new HashMap<>();
Map<Integer, Integer> couponPoints = new HashMap<>(5);
PreparedStatement ps = con.prepareStatement("SELECT * FROM nxcode_items WHERE codeid = ?");
ps.setInt(1, codeid);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
int type = rs.getInt("type"), item = rs.getInt("item");
if (type < 5) {
Integer i = couponPoints.get(type);
if (i != null) {
couponPoints.put(type, i + item);
} else {
couponPoints.put(type, item);
}
} else {
int quantity = rs.getInt("quantity");
Integer i = couponItems.get(item);
if (i != null) {
couponItems.put(item, i + quantity);
} else {
couponItems.put(item, quantity);
}
}
}
rs.close();
ps.close();
List<Pair<Integer, Pair<Integer, Integer>>> ret = new LinkedList<>();
if (!couponItems.isEmpty()) {
for (Entry<Integer, Integer> e : couponItems.entrySet()) {
int item = e.getKey(), qty = e.getValue();
if (MapleItemInformationProvider.getInstance().getName(item) == null) {
item = 4000000;
qty = 1;
FilePrinter.printError(FilePrinter.UNHANDLED_EVENT, "Error trying to redeem itemid " + item + " from codeid " + codeid + ".");
}
if (!chr.canHold(item, qty)) {
return null;
}
ret.add(new Pair<>(5, new Pair<>(item, qty)));
}
}
if (!couponPoints.isEmpty()) {
for (Entry<Integer, Integer> e : couponPoints.entrySet()) {
ret.add(new Pair<>(e.getKey(), new Pair<>(e.getValue(), 777)));
}
}
return ret;
}
private static Pair<Integer, List<Pair<Integer, Pair<Integer, Integer>>>> getNXCodeResult(MapleCharacter chr, String code) {
MapleClient c = chr.getClient();
List<Pair<Integer, Pair<Integer, Integer>>> ret = new LinkedList<>();
try {
if (!c.attemptCsCoupon()) {
return new Pair<>(-5, null);
}
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT * FROM nxcode WHERE code = ?");
ps.setString(1, code);
ResultSet rs = ps.executeQuery();
if (!rs.next()) {
return new Pair<>(-1, null);
}
if (rs.getString("retriever") != null) {
return new Pair<>(-2, null);
}
if (rs.getLong("expiration") < Server.getInstance().getCurrentTime()) {
return new Pair<>(-3, null);
}
int codeid = rs.getInt("id");
rs.close();
ps.close();
ret = getNXCodeItems(chr, con, codeid);
if (ret == null) {
return new Pair<>(-4, null);
}
ps = con.prepareStatement("UPDATE nxcode SET retriever = ? WHERE code = ?");
ps.setString(1, chr.getName());
ps.setString(2, code);
ps.executeUpdate();
ps.close();
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
c.resetCsCoupon();
return new Pair<>(0, ret);
}
private static int parseCouponResult(int res) {
switch (res) {
case -1:
return 0xB0;
case -2:
return 0xB3;
case -3:
return 0xB2;
case -4:
return 0xBB;
default:
return 0xB1;
}
}
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
slea.skip(2);
String code = slea.readMapleAsciiString();
boolean validcode = false;
int type = -1;
int item = -1;
validcode = getNXCodeValid(code.toUpperCase(), validcode);
if (validcode) {
type = getNXCode(code, "type");
item = getNXCode(code, "item");
if (type != 5) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("UPDATE nxcode SET `valid` = 0 WHERE code = " + code);
ps.executeUpdate();
ps.close();
ps = con.prepareStatement("UPDATE nxcode SET `user` = ? WHERE code = ?");
ps.setString(1, c.getPlayer().getName());
ps.setString(2, code);
ps.executeUpdate();
ps.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
if (c.tryacquireClient()) {
try {
Pair<Integer, List<Pair<Integer, Pair<Integer, Integer>>>> codeRes = getNXCodeResult(c.getPlayer(), code.toUpperCase());
int type = codeRes.getLeft();
if (type < 0) {
c.announce(MaplePacketCreator.showCashShopMessage((byte) parseCouponResult(type)));
} else {
List<Item> couponPackage = new LinkedList<>();
for (Pair<Integer, Pair<Integer, Integer>> p : codeRes.getRight()) {
type = p.getLeft();
int item = p.getRight().getLeft();
CashShop cs = c.getPlayer().getCashShop();
switch (type) {
case 0:
case 4:
cs.gainCash(1, item); //nxCredit
break;
case 1:
cs.gainCash(2, item); //maplePoint
break;
case 2:
cs.gainCash(4, item); //nxPrepaid
break;
case 3:
cs.gainCash(1, item);
cs.gainCash(4, (item / 5000));
break;
default:
short qty = p.getRight().getRight().shortValue();
if (MapleItemInformationProvider.getInstance().isCash(item)) {
Item it = CashShop.generateCouponItem(item, qty);
cs.addToInventory(it);
couponPackage.add(it);
} else {
MapleInventoryManipulator.addById(c, item, qty, "", -1);
}
//c.announce(MaplePacketCreator.showCouponRedeemedItem(item));
break;
}
}
if (!couponPackage.isEmpty()) {
c.announce(MaplePacketCreator.showBoughtCashPackage(couponPackage, c.getAccID()));
} else {
c.announce(MaplePacketCreator.showBoughtQuestItem(0));
}
c.enableCSActions();
}
} finally {
c.releaseClient();
}
switch (type) {
case 0:
case 1:
case 2:
c.getPlayer().getCashShop().gainCash(type, item);
break;
case 3:
c.getPlayer().getCashShop().gainCash(0, item);
c.getPlayer().getCashShop().gainCash(2, (item / 5000));
break;
case 4:
MapleInventoryManipulator.addById(c, item, (short) 1, null, -1, -1);
c.announce(MaplePacketCreator.showCouponRedeemedItem(item));
break;
case 5:
c.getPlayer().getCashShop().gainCash(0, item);
break;
}
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
} else {
//c.announce(MaplePacketCreator.wrongCouponCode());
}
c.announce(MaplePacketCreator.enableCSUse());
}
private int getNXCode(String code, String type) {
int item = -1;
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT `" + type + "` FROM nxcode WHERE code = ?");
ps.setString(1, code);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
item = rs.getInt(type);
}
rs.close();
ps.close();
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return item;
}
private boolean getNXCodeValid(String code, boolean validcode) {
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT `valid` FROM nxcode WHERE code = ?");
ps.setString(1, code);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
validcode = rs.getInt("valid") != 0;
}
rs.close();
ps.close();
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return validcode;
}
}

View File

@@ -111,7 +111,7 @@ public final class EnterMTSHandler extends AbstractMaplePacketHandler {
ex.printStackTrace();
}
chr.getCashShop().open(true);// xD
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(MaplePacketCreator.MTSWantedListingOver(0, 0));
c.announce(MaplePacketCreator.showMTSCash(c.getPlayer()));
List<MTSItemInfo> items = new ArrayList<>();

View File

@@ -40,13 +40,13 @@ public final class FaceExpressionHandler extends AbstractMaplePacketHandler {
}
}
if(c.trylockClient()) {
if(c.tryacquireClient()) {
try { // expecting players never intends to wear the emote 0 (default face, that changes back after 5sec timeout)
if (emote != 0 && chr.isLoggedinWorld()) {
chr.changeFaceExpression(emote);
}
} finally {
c.unlockClient();
c.releaseClient();
}
}
}

View File

@@ -60,7 +60,7 @@ public final class ItemRewardHandler extends AbstractMaplePacketHandler {
}
MapleInventoryManipulator.addFromDrop(c, item, false);
} else {
MapleInventoryManipulator.addById(c, reward.itemid, reward.quantity);
MapleInventoryManipulator.addById(c, reward.itemid, reward.quantity, "", -1);
}
MapleInventoryManipulator.removeById(c, MapleInventoryType.USE, itemId, 1, false, false);
if (reward.worldmsg != null) {

View File

@@ -214,7 +214,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
c.getPlayer().gainMeso(-5000, false);
c.announce(MaplePacketCreator.MTSConfirmSell());
c.announce(getMTS(1, 0, 0));
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(MaplePacketCreator.transferInventory(getTransfer(c.getPlayer().getId())));
c.announce(MaplePacketCreator.notYetSoldInv(getNotYetSold(c.getPlayer().getId())));
}
@@ -240,7 +240,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
}
c.getPlayer().changeTab(tab);
c.getPlayer().changeType(type);
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(MaplePacketCreator.transferInventory(getTransfer(c.getPlayer().getId())));
c.announce(MaplePacketCreator.notYetSoldInv(getNotYetSold(c.getPlayer().getId())));
} else if (op == 6) { //search
@@ -253,7 +253,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
c.getPlayer().changeTab(tab);
c.getPlayer().changeType(type);
c.getPlayer().changeCI(ci);
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(MaplePacketCreator.enableActions());
c.announce(getMTSSearch(tab, type, ci, search, c.getPlayer().getCurrentPage()));
c.announce(MaplePacketCreator.showMTSCash(c.getPlayer()));
@@ -277,7 +277,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
} catch (SQLException e) {
e.printStackTrace();
}
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(getMTS(c.getPlayer().getCurrentTab(), c.getPlayer().getCurrentType(), c.getPlayer().getCurrentPage()));
c.announce(MaplePacketCreator.notYetSoldInv(getNotYetSold(c.getPlayer().getId())));
c.announce(MaplePacketCreator.transferInventory(getTransfer(c.getPlayer().getId())));
@@ -331,7 +331,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
pse.executeUpdate();
}
MapleInventoryManipulator.addFromDrop(c, i, false);
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(getCart(c.getPlayer().getId()));
c.announce(getMTS(c.getPlayer().getCurrentTab(), c.getPlayer().getCurrentType(), c.getPlayer().getCurrentPage()));
c.announce(MaplePacketCreator.MTSConfirmTransfer(i.getQuantity(), i.getPosition()));
@@ -374,7 +374,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
e.printStackTrace();
}
c.announce(getMTS(c.getPlayer().getCurrentTab(), c.getPlayer().getCurrentType(), c.getPlayer().getCurrentPage()));
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(MaplePacketCreator.enableActions());
c.announce(MaplePacketCreator.transferInventory(getTransfer(c.getPlayer().getId())));
c.announce(MaplePacketCreator.notYetSoldInv(getNotYetSold(c.getPlayer().getId())));
@@ -393,7 +393,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
e.printStackTrace();
}
c.announce(getCart(c.getPlayer().getId()));
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(MaplePacketCreator.transferInventory(getTransfer(c.getPlayer().getId())));
c.announce(MaplePacketCreator.notYetSoldInv(getNotYetSold(c.getPlayer().getId())));
} else if (op == 12) { //put item up for auction
@@ -445,7 +445,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
pse.executeUpdate();
pse.close();
c.getPlayer().getCashShop().gainCash(4, -price);
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(getMTS(c.getPlayer().getCurrentTab(), c.getPlayer().getCurrentType(), c.getPlayer().getCurrentPage()));
c.announce(MaplePacketCreator.MTSConfirmBuy());
c.announce(MaplePacketCreator.showMTSCash(c.getPlayer()));
@@ -507,7 +507,7 @@ public final class MTSHandler extends AbstractMaplePacketHandler {
pse.close();
c.getPlayer().getCashShop().gainCash(4, -price);
c.announce(getCart(c.getPlayer().getId()));
c.announce(MaplePacketCreator.enableCSUse());
c.enableCSActions();
c.announce(MaplePacketCreator.MTSConfirmBuy());
c.announce(MaplePacketCreator.showMTSCash(c.getPlayer()));
c.announce(MaplePacketCreator.transferInventory(getTransfer(c.getPlayer().getId())));

View File

@@ -39,7 +39,7 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
chr.setPetLootCd(currentServerTime());
//chr.setPetLootCd(currentServerTime());
/*long timeElapsed = currentServerTime() - chr.getAutobanManager().getLastSpam(8);
if(timeElapsed < 300) {

View File

@@ -23,6 +23,7 @@ package net.server.channel.handlers;
import client.MapleCharacter;
import client.MapleClient;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import client.inventory.MaplePet;
import client.autoban.AutobanManager;
@@ -65,18 +66,25 @@ public final class PetFoodHandler extends AbstractMaplePacketHandler {
short pos = slea.readShort();
int itemId = slea.readInt();
Item use = chr.getInventory(MapleInventoryType.USE).getItem(pos);
if (use == null || (itemId / 10000) != 212 || use.getItemId() != itemId) {
return;
}
c.lockClient();
try {
pet.gainClosenessFullness(chr, (pet.getFullness() <= 75) ? 1 : 0, 30, 1); // 25+ "emptyness" to get +1 closeness
} finally {
c.unlockClient();
if (c.tryacquireClient()) {
try {
MapleInventory useInv = chr.getInventory(MapleInventoryType.USE);
useInv.lockInventory();
try {
Item use = useInv.getItem(pos);
if (use == null || (itemId / 10000) != 212 || use.getItemId() != itemId || use.getQuantity() < 1) {
return;
}
pet.gainClosenessFullness(chr, (pet.getFullness() <= 75) ? 1 : 0, 30, 1); // 25+ "emptyness" to get +1 closeness
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, pos, (short) 1, false);
} finally {
useInv.unlockInventory();
}
} finally {
c.releaseClient();
}
}
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, pos, (short) 1, false);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -51,8 +51,8 @@ public final class RangedAttackHandler extends AbstractDealDamageHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
MapleCharacter chr = c.getPlayer();
chr.setPetLootCd(currentServerTime());
//chr.setPetLootCd(currentServerTime());
/*long timeElapsed = currentServerTime() - chr.getAutobanManager().getLastSpam(8);
if(timeElapsed < 300) {
AutobanFactory.FAST_ATTACK.alert(chr, "Time: " + timeElapsed);

View File

@@ -273,20 +273,20 @@ public final class RingActionHandler extends AbstractMaplePacketHandler {
}
public static void giveMarriageRings(MapleCharacter player, MapleCharacter partner, int marriageRingId) {
int ringid = MapleRing.createRing(marriageRingId, player, partner);
Pair<Integer, Integer> rings = MapleRing.createRing(marriageRingId, player, partner);
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
Item ringObj = ii.getEquipById(marriageRingId);
Equip ringEqp = (Equip) ringObj;
ringEqp.setRingId(ringid);
player.addMarriageRing(MapleRing.loadFromDb(ringid));
ringEqp.setRingId(rings.getLeft());
player.addMarriageRing(MapleRing.loadFromDb(rings.getLeft()));
MapleInventoryManipulator.addFromDrop(player.getClient(), ringEqp, false, -1);
player.broadcastMarriageMessage();
ringObj = ii.getEquipById(marriageRingId);
ringEqp = (Equip) ringObj;
ringEqp.setRingId(ringid + 1);
partner.addMarriageRing(MapleRing.loadFromDb(ringid + 1));
ringEqp.setRingId(rings.getRight());
partner.addMarriageRing(MapleRing.loadFromDb(rings.getRight()));
MapleInventoryManipulator.addFromDrop(partner.getClient(), ringEqp, false, -1);
partner.broadcastMarriageMessage();
}
@@ -513,6 +513,6 @@ public final class RingActionHandler extends AbstractMaplePacketHandler {
break;
}
c.getSession().write(MaplePacketCreator.enableActions());
c.announce(MaplePacketCreator.enableActions());
}
}

View File

@@ -28,9 +28,10 @@ import tools.data.input.SeekableLittleEndianAccessor;
/**
*
* @author Acrylic (Terry Han)
* @author Terry Han (Acrylic)
*/
public final class TouchingCashShopHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
c.announce(MaplePacketCreator.showCash(c.getPlayer()));
}

View File

@@ -276,7 +276,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
if (item == null) //hack
{
return;
} else if (((item.getFlag() & ItemConstants.UNTRADEABLE) == ItemConstants.UNTRADEABLE) || (ii.isDropRestricted(item.getItemId()) && !MapleKarmaManipulator.hasKarmaFlag(item))) {
} else if (item.isUntradeable()) {
player.dropMessage(1, "You cannot trade this item.");
c.announce(MaplePacketCreator.enableActions());
return;
@@ -299,7 +299,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
break;
}
remove(c, itemId);
} else if (itemType == 508) { // graduation banner, thanks to tmskdl12
} else if (itemType == 508) { // graduation banner, thanks to tmskdl12. Also, thanks ratency for first pointing lack of Kite handling
MapleKite kite = new MapleKite(player, slea.readMapleAsciiString(), itemId);
if (!GameConstants.isFreeMarketRoom(player.getMapId())) {
@@ -517,7 +517,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
Equip toScroll = (Equip) eitem;
if (toScroll.getUpgradeSlots() < 1) {
c.getSession().write(MaplePacketCreator.getInventoryFull());
c.announce(MaplePacketCreator.getInventoryFull());
return;
}
@@ -527,10 +527,10 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
player.toggleBlockCashShop();
final int curlevel = toScroll.getLevel();
c.getSession().write(MaplePacketCreator.sendVegaScroll(0x40));
c.announce(MaplePacketCreator.sendVegaScroll(0x40));
final Equip scrolled = (Equip) ii.scrollEquipWithId(toScroll, uitem.getItemId(), false, itemId, player.isGM());
c.getSession().write(MaplePacketCreator.sendVegaScroll(scrolled.getLevel() > curlevel ? 0x41 : 0x43));
c.announce(MaplePacketCreator.sendVegaScroll(scrolled.getLevel() > curlevel ? 0x41 : 0x43));
//opcodes 0x42, 0x44: "this item cannot be used"; 0x39, 0x45: crashes
MapleInventoryManipulator.removeFromSlot(c, MapleInventoryType.USE, uSlot, (short) 1, false);
@@ -555,7 +555,7 @@ public final class UseCashItemHandler extends AbstractMaplePacketHandler {
player.equipChanged();
}
client.getSession().write(MaplePacketCreator.enableActions());
client.announce(MaplePacketCreator.enableActions());
}
}, 1000 * 3);
} else {

View File

@@ -24,7 +24,6 @@ package net.server.channel.handlers;
import client.MapleClient;
import client.inventory.MapleInventoryType;
import net.AbstractMaplePacketHandler;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
public final class UseChairHandler extends AbstractMaplePacketHandler {
@@ -34,8 +33,7 @@ public final class UseChairHandler extends AbstractMaplePacketHandler {
if (c.getPlayer().getInventory(MapleInventoryType.SETUP).findById(itemId) == null) {
return;
}
c.getPlayer().setChair(itemId);
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.showChair(c.getPlayer().getId(), itemId), false);
c.announce(MaplePacketCreator.enableActions());
c.getPlayer().sitChair(itemId);
}
}

View File

@@ -25,6 +25,7 @@ import client.MapleClient;
import client.MapleCharacter;
import client.MapleMount;
import client.inventory.Item;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import constants.ExpTable;
import net.AbstractMaplePacketHandler;
@@ -45,29 +46,37 @@ public final class UseMountFoodHandler extends AbstractMaplePacketHandler {
MapleCharacter chr = c.getPlayer();
MapleMount mount = chr.getMount();
Item item = chr.getInventory(MapleInventoryType.USE).getItem(pos);
if (item != null && item.getItemId() == itemid && mount != null) {
c.lockClient();
MapleInventory useInv = chr.getInventory(MapleInventoryType.USE);
if (c.tryacquireClient()) {
try {
int curTiredness = mount.getTiredness();
int healedTiredness = Math.min(curTiredness, 30);
float healedFactor = (float) healedTiredness / 30;
mount.setTiredness(curTiredness - healedTiredness);
if (healedFactor > 0.0f) {
mount.setExp(mount.getExp() + (int) Math.ceil(healedFactor * (2 * mount.getLevel() + 6)));
int level = mount.getLevel();
boolean levelup = mount.getExp() >= ExpTable.getMountExpNeededForLevel(level) && level < 31;
if (levelup) {
mount.setLevel(level + 1);
useInv.lockInventory();
try {
Item item = useInv.getItem(pos);
if (item != null && item.getItemId() == itemid && mount != null) {
int curTiredness = mount.getTiredness();
int healedTiredness = Math.min(curTiredness, 30);
float healedFactor = (float) healedTiredness / 30;
mount.setTiredness(curTiredness - healedTiredness);
if (healedFactor > 0.0f) {
mount.setExp(mount.getExp() + (int) Math.ceil(healedFactor * (2 * mount.getLevel() + 6)));
int level = mount.getLevel();
boolean levelup = mount.getExp() >= ExpTable.getMountExpNeededForLevel(level) && level < 31;
if (levelup) {
mount.setLevel(level + 1);
}
chr.getMap().broadcastMessage(MaplePacketCreator.updateMount(chr.getId(), mount, levelup));
}
MapleInventoryManipulator.removeById(c, MapleInventoryType.USE, itemid, 1, true, false);
}
chr.getMap().broadcastMessage(MaplePacketCreator.updateMount(chr.getId(), mount, levelup));
} finally {
useInv.unlockInventory();
}
MapleInventoryManipulator.removeById(c, MapleInventoryType.USE, itemid, 1, true, false);
} finally {
c.unlockClient();
c.releaseClient();
}
}
}

View File

@@ -49,9 +49,9 @@ public final class WhisperHandler extends AbstractMaplePacketHandler {
String recipient = slea.readMapleAsciiString();
String text = slea.readMapleAsciiString();
MapleCharacter player = c.getChannelServer().getPlayerStorage().getCharacterByName(recipient);
if(c.getPlayer().getAutobanManager().getLastSpam(7) + 200 > currentServerTime()) {
return;
}
if (c.getPlayer().getAutobanManager().getLastSpam(7) + 200 > currentServerTime()) {
return;
}
if (text.length() > Byte.MAX_VALUE && !player.isGM()) {
AutobanFactory.PACKET_EDIT.alert(c.getPlayer(), c.getPlayer().getName() + " tried to packet edit with whispers.");
FilePrinter.printError(FilePrinter.EXPLOITS + c.getPlayer().getName() + ".txt", c.getPlayer().getName() + " tried to send text with length of " + text.length() + "\r\n");
@@ -92,7 +92,7 @@ public final class WhisperHandler extends AbstractMaplePacketHandler {
} else {
c.announce(MaplePacketCreator.getFindReply(victim.getName(), victim.getMap().getId(), 1));
}
} else if (c.getPlayer().gmLevel() > 1) { // not found
} else if (c.getPlayer().isGM()) { // not found
try {
Connection con = DatabaseConnection.getConnection();
PreparedStatement ps = con.prepareStatement("SELECT gm FROM characters WHERE name = ?");

View File

@@ -37,6 +37,9 @@ import tools.data.input.SeekableLittleEndianAccessor;
import client.MapleClient;
import java.sql.ResultSet;
import java.sql.Statement;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public final class LoginPasswordHandler implements MaplePacketHandler {
@@ -45,6 +48,11 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
return !c.isLoggedIn();
}
private static String hashpwSHA512(String pwd) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digester = MessageDigest.getInstance("SHA-512");
digester.update(pwd.getBytes("UTF-8"), 0, pwd.length());
return HexTool.toString(digester.digest()).replace(" ", "").toLowerCase();
}
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
@@ -65,7 +73,7 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
con = DatabaseConnection.getConnection();
ps = con.prepareStatement("INSERT INTO accounts (name, password, birthday, tempban) VALUES (?, ?, ?, ?);", Statement.RETURN_GENERATED_KEYS); //Jayd: Added birthday, tempban
ps.setString(1, login);
ps.setString(2, BCrypt.hashpw(pwd, BCrypt.gensalt(12)));
ps.setString(2, ServerConstants.BCRYPT_MIGRATION ? BCrypt.hashpw(pwd, BCrypt.gensalt(12)) : hashpwSHA512(pwd));
ps.setString(3, "2018-06-20"); //Jayd's idea: was added to solve the MySQL 5.7 strict checking (birthday)
ps.setString(4, "2018-06-20"); //Jayd's idea: was added to solve the MySQL 5.7 strict checking (tempban)
ps.executeUpdate();
@@ -74,7 +82,7 @@ public final class LoginPasswordHandler implements MaplePacketHandler {
rs.next();
c.setAccID(rs.getInt(1));
rs.close();
} catch (SQLException e) {
} catch (SQLException | NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
disposeSql(con, ps);

View File

@@ -682,8 +682,8 @@ public class AbstractPlayerInteraction {
public boolean isEventLeader() {
return getEventInstance() != null && getPlayer().getId() == getEventInstance().getLeaderId();
}
public void givePartyItems(int id, short quantity, List<MapleCharacter> party) {
public void givePartyItems(int id, short quantity, List<MapleCharacter> party) {
for (MapleCharacter chr : party) {
MapleClient cl = chr.getClient();
if (quantity >= 0) {
@@ -695,7 +695,6 @@ public class AbstractPlayerInteraction {
}
}
public void removeHPQItems() {
int[] items = {4001095, 4001096, 4001097, 4001098, 4001099, 4001100, 4001101};
for (int i = 0; i < items.length; i ++) {

View File

@@ -345,7 +345,7 @@ public class EventInstanceManager {
private void dismissEventTimer() {
for(MapleCharacter chr: getPlayers()) {
chr.getClient().getSession().write(MaplePacketCreator.removeClock());
chr.getClient().announce(MaplePacketCreator.removeClock());
}
event_schedule = null;

View File

@@ -582,4 +582,9 @@ public class CashShop {
return null;
}
}
public static Item generateCouponItem(int itemId, short quantity) {
CashItem it = new CashItem(77777777, itemId, 7777, ItemConstants.isPet(itemId) ? 30 : 0, quantity, true);
return it.toItem();
}
}

View File

@@ -373,6 +373,7 @@ public class MapleItemInformationProvider {
private static short getExtraSlotMaxFromPlayer(MapleClient c, int itemId) {
short ret = 0;
// thanks GMChuck for detecting player sensitive data being cached into getSlotMax
if (ItemConstants.isThrowingStar(itemId)) {
if(c.getPlayer().getJob().isA(MapleJob.NIGHTWALKER1)) {
ret += c.getPlayer().getSkillLevel(SkillFactory.getSkill(NightWalker.CLAW_MASTERY)) * 10;
@@ -658,11 +659,11 @@ public class MapleItemInformationProvider {
}
private static short getMaximumShortMaxIfOverflow(int value1, int value2) {
return (short)Math.min(Short.MAX_VALUE, Math.max(value1, value2));
return (short) Math.min(Short.MAX_VALUE, Math.max(value1, value2));
}
private static short getShortMaxIfOverflow(int value) {
return (short)Math.min(Short.MAX_VALUE, value);
return (short) Math.min(Short.MAX_VALUE, value);
}
private static short chscrollRandomizedStat(int range) {

View File

@@ -94,12 +94,12 @@ public class MapleShop {
if (c.getPlayer().getMeso() >= amount) {
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
if (!ItemConstants.isRechargeable(itemId)) { //Pets can't be bought from shops
MapleInventoryManipulator.addById(c, itemId, quantity);
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
c.getPlayer().gainMeso(-amount, false);
} else {
short slotMax = ii.getSlotMax(c, item.getItemId());
quantity = slotMax;
MapleInventoryManipulator.addById(c, itemId, quantity);
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
c.getPlayer().gainMeso(-item.getPrice(), false);
}
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
@@ -115,12 +115,12 @@ public class MapleShop {
if (c.getPlayer().getInventory(MapleInventoryType.ETC).countById(4310000) >= amount) {
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
if (!ItemConstants.isRechargeable(itemId)) {
MapleInventoryManipulator.addById(c, itemId, quantity);
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, amount, false, false);
} else {
short slotMax = ii.getSlotMax(c, item.getItemId());
quantity = slotMax;
MapleInventoryManipulator.addById(c, itemId, quantity);
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1);
MapleInventoryManipulator.removeById(c, MapleInventoryType.ETC, 4310000, amount, false, false);
}
c.announce(MaplePacketCreator.shopTransaction((byte) 0));
@@ -138,9 +138,9 @@ public class MapleShop {
if (MapleInventoryManipulator.checkSpace(c, itemId, quantity, "")) {
if (ItemConstants.isPet(itemId)) {
int petid = MaplePet.createPet(itemId);
MapleInventoryManipulator.addById(c, itemId, quantity, null, petid, -1);
MapleInventoryManipulator.addById(c, itemId, quantity, "", petid, -1);
} else {
MapleInventoryManipulator.addById(c, itemId, quantity);
MapleInventoryManipulator.addById(c, itemId, quantity, "", -1, -1);
}
c.getPlayer().gainMeso(diff, false);
} else {

View File

@@ -376,7 +376,7 @@ public class MapleHiredMerchant extends AbstractMapleMapObject {
if (mpsi.getItem().getInventoryType().equals(MapleInventoryType.EQUIP)) {
MapleInventoryManipulator.addFromDrop(c, mpsi.getItem(), false);
} else {
MapleInventoryManipulator.addById(c, mpsi.getItem().getItemId(), (short) (mpsi.getBundles() * mpsi.getItem().getQuantity()), null, -1, mpsi.getItem().getFlag(), mpsi.getItem().getExpiration());
MapleInventoryManipulator.addById(c, mpsi.getItem().getItemId(), (short) (mpsi.getBundles() * mpsi.getItem().getQuantity()), mpsi.getItem().getOwner(), -1, mpsi.getItem().getFlag(), mpsi.getItem().getExpiration());
}
}
}

View File

@@ -43,12 +43,12 @@ public class MapleKite extends AbstractMapleMapObject {
@Override
public void sendDestroyData(MapleClient client) {
client.getSession().write(makeDestroyData());
client.announce(makeDestroyData());
}
@Override
public void sendSpawnData(MapleClient client) {
client.getSession().write(makeSpawnData());
client.announce(makeSpawnData());
}
public final byte[] makeSpawnData() {

View File

@@ -3882,7 +3882,7 @@ public class MapleMap {
public void spawnHorntailOnGroundBelow(final Point targetPoint) { // ayy lmao
MapleMonster htIntro = MapleLifeFactory.getMonster(8810026);
spawnMonsterOnGroundBelow(htIntro, targetPoint);
spawnMonsterOnGroundBelow(htIntro, targetPoint); // htintro spawn animation converting into horntail detected thanks to Arnah
final MapleMonster ht = MapleLifeFactory.getMonster(8810018);
ht.setParentMobOid(htIntro.getObjectId());

View File

@@ -427,21 +427,14 @@ public class MapleMapFactory {
public Map<Integer, MapleMap> getMaps() {
mapsRLock.lock();
try {
return Collections.unmodifiableMap(maps);
return new HashMap<>(maps);
} finally {
mapsRLock.unlock();
}
}
public void dispose() {
Collection<MapleMap> mapValues;
mapsRLock.lock();
try {
mapValues = maps.values();
} finally {
mapsRLock.unlock();
}
Collection<MapleMap> mapValues = getMaps().values();
for(MapleMap map: mapValues) {
map.dispose();

View File

@@ -23,6 +23,7 @@ package server.maps;
import client.MapleCharacter;
import client.MapleClient;
import net.server.Server;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -31,23 +32,25 @@ import tools.MaplePacketCreator;
/**
*
* @author Matze
* @author Ronan (refactored String GameType to enum MiniGameType)
* @author Ronan (HeavenMS)
*/
public class MapleMiniGame extends AbstractMapleMapObject {
private MapleCharacter owner;
private MapleCharacter visitor;
private String password;
private MiniGameType GameType = MiniGameType.UNDEFINED;
private int piecetype;
private int inprogress = 0;
private int[] piece = new int[250];
private List<Integer> list4x3 = new ArrayList<>();
private List<Integer> list5x4 = new ArrayList<>();
private List<Integer> list6x5 = new ArrayList<>();
private String description;
private int loser = 1;
private int piecetype;
private int firstslot = 0;
private int visitorpoints = 0;
private int ownerpoints = 0;
private int visitorpoints = 0, visitorscore = 0, visitorforfeits = 0, lastvisitor = -1;
private int ownerpoints = 0, ownerscore = 0, ownerforfeits = 0;
private long nextavailabletie = 0;
private int matchestowin = 0;
public static enum MiniGameType {
@@ -91,12 +94,21 @@ public class MapleMiniGame extends AbstractMapleMapObject {
public void addVisitor(MapleCharacter challenger) {
visitor = challenger;
if (lastvisitor != challenger.getId()) {
ownerscore = 0;
ownerforfeits = 0;
visitorscore = 0;
visitorforfeits = 0;
lastvisitor = challenger.getId();
}
MapleCharacter owner = this.getOwner();
if (GameType == MiniGameType.OMOK) {
owner.announce(MaplePacketCreator.getMiniGameNewVisitor(challenger, 1));
owner.announce(MaplePacketCreator.getMiniGameNewVisitor(this, challenger, 1));
owner.getMap().broadcastMessage(MaplePacketCreator.addOmokBox(owner, 2, 0));
} else if (GameType == MiniGameType.MATCH_CARD) {
owner.announce(MaplePacketCreator.getMatchCardNewVisitor(challenger, 1));
owner.announce(MaplePacketCreator.getMatchCardNewVisitor(this, challenger, 1));
owner.getMap().broadcastMessage(MaplePacketCreator.addMatchCardBox(owner, 2, 0));
}
}
@@ -117,6 +129,13 @@ public class MapleMiniGame extends AbstractMapleMapObject {
return visitor == challenger;
}
public void broadcastToOwner(final byte[] packet) {
MapleClient c = owner.getClient();
if (c != null && c.getSession() != null) {
c.announce(packet);
}
}
public void broadcastToVisitor(final byte[] packet) {
if (visitor != null) {
visitor.getClient().announce(packet);
@@ -131,15 +150,83 @@ public class MapleMiniGame extends AbstractMapleMapObject {
return firstslot;
}
private void updateMiniGameBox() {
this.getOwner().getMap().broadcastMessage(MaplePacketCreator.addOmokBox(owner, visitor != null ? 2 : 1, inprogress));
}
private void minigameMatchFinished() {
inprogress = 0;
updateMiniGameBox();
}
public void minigameMatchStarted() {
inprogress = 1;
}
public boolean isMatchInProgress() {
return inprogress != 0;
}
public void denyTie(MapleCharacter chr) {
if (this.isOwner(chr)) {
inprogress |= (1 << 1);
} else {
inprogress |= (1 << 2);
}
}
public boolean isTieDenied(MapleCharacter chr) {
if (this.isOwner(chr)) {
return ((inprogress >> 1) % 2) == 1;
} else {
return ((inprogress >> 2) % 2) == 1;
}
}
public void minigameMatchOwnerWins(boolean forfeit) {
owner.setMiniGamePoints(visitor, 1, this.isOmok());
if (visitorforfeits < 4 || !forfeit) ownerscore += 50;
visitorscore += (15 * (forfeit ? -1 : 1));
if (forfeit) visitorforfeits++;
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this, forfeit));
minigameMatchFinished();
}
public void minigameMatchVisitorWins(boolean forfeit) {
owner.setMiniGamePoints(visitor, 2, this.isOmok());
if (ownerforfeits < 4 || !forfeit) visitorscore += 50;
ownerscore += (15 * (forfeit ? -1 : 1));
if (forfeit) ownerforfeits++;
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this, forfeit));
minigameMatchFinished();
}
public void minigameMatchDraw() {
owner.setMiniGamePoints(visitor, 3, this.isOmok());
long timeNow = Server.getInstance().getCurrentTime();
if (nextavailabletie <= timeNow) {
visitorscore += 10;
ownerscore += 10;
nextavailabletie = timeNow + 5 * 60 * 1000;
}
this.broadcast(MaplePacketCreator.getMiniGameTie(this));
minigameMatchFinished();
}
public void setOwnerPoints() {
ownerpoints++;
if (ownerpoints + visitorpoints == matchestowin) {
if (ownerpoints == visitorpoints) {
this.broadcast(MaplePacketCreator.getMatchCardTie(this));
minigameMatchDraw();
} else if (ownerpoints > visitorpoints) {
this.broadcast(MaplePacketCreator.getMatchCardOwnerWin(this));
minigameMatchOwnerWins(false);
} else {
this.broadcast(MaplePacketCreator.getMatchCardVisitorWin(this));
minigameMatchVisitorWins(false);
}
ownerpoints = 0;
visitorpoints = 0;
@@ -150,11 +237,11 @@ public class MapleMiniGame extends AbstractMapleMapObject {
visitorpoints++;
if (ownerpoints + visitorpoints == matchestowin) {
if (ownerpoints > visitorpoints) {
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
minigameMatchOwnerWins(false);
} else if (visitorpoints > ownerpoints) {
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
minigameMatchVisitorWins(false);
} else {
this.broadcast(MaplePacketCreator.getMiniGameTie(this));
minigameMatchDraw();
}
ownerpoints = 0;
visitorpoints = 0;
@@ -198,6 +285,10 @@ public class MapleMiniGame extends AbstractMapleMapObject {
public MiniGameType getGameType() {
return GameType;
}
public boolean isOmok() {
return GameType.equals(MiniGameType.OMOK);
}
public void shuffleList() {
if (matchestowin == 6) {
@@ -212,11 +303,11 @@ public class MapleMiniGame extends AbstractMapleMapObject {
public int getCardId(int slot) {
int cardid;
if (matchestowin == 6) {
cardid = list4x3.get(slot - 1);
cardid = list4x3.get(slot);
} else if (matchestowin == 10) {
cardid = list5x4.get(slot - 1);
cardid = list5x4.get(slot);
} else {
cardid = list6x5.get(slot - 1);
cardid = list6x5.get(slot);
}
return cardid;
}
@@ -234,10 +325,7 @@ public class MapleMiniGame extends AbstractMapleMapObject {
}
public void broadcast(final byte[] packet) {
MapleClient c = owner.getClient();
if (c != null && c.getSession() != null) {
c.announce(packet);
}
broadcastToOwner(packet);
broadcastToVisitor(packet);
}
@@ -270,10 +358,10 @@ public class MapleMiniGame extends AbstractMapleMapObject {
for (int x = 0; x < 11; x++) {
if (searchCombo(x, y, type)) {
if (this.isOwner(chr)) {
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
this.minigameMatchOwnerWins(false);
this.setLoser(0);
} else {
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
this.minigameMatchVisitorWins(false);
this.setLoser(1);
}
for (int y2 = 0; y2 < 15; y2++) {
@@ -289,10 +377,10 @@ public class MapleMiniGame extends AbstractMapleMapObject {
for (int x = 4; x < 15; x++) {
if (searchCombo2(x, y, type)) {
if (this.isOwner(chr)) {
this.broadcast(MaplePacketCreator.getMiniGameOwnerWin(this));
this.minigameMatchOwnerWins(false);
this.setLoser(0);
} else {
this.broadcast(MaplePacketCreator.getMiniGameVisitorWin(this));
this.minigameMatchVisitorWins(false);
this.setLoser(1);
}
for (int y2 = 0; y2 < 15; y2++) {
@@ -351,14 +439,20 @@ public class MapleMiniGame extends AbstractMapleMapObject {
public String getDescription() {
return description;
}
@Override
public void sendDestroyData(MapleClient client) {
public int getOwnerScore() {
return ownerscore;
}
public int getVisitorScore() {
return visitorscore;
}
@Override
public void sendSpawnData(MapleClient client) {
}
public void sendDestroyData(MapleClient client) {}
@Override
public void sendSpawnData(MapleClient client) {}
@Override
public MapleMapObjectType getType() {

View File

@@ -354,7 +354,7 @@ public class MapleQuest {
newStatus.setCompletionTime(System.currentTimeMillis());
c.updateQuest(newStatus);
c.getClient().getSession().write(MaplePacketCreator.showSpecialEffect(9)); // Quest completion
c.announce(MaplePacketCreator.showSpecialEffect(9)); // Quest completion
c.getMap().broadcastMessage(c, MaplePacketCreator.showForeignEffect(c.getId(), 9), false); //use 9 instead of 12 for both
return true;
}

View File

@@ -149,7 +149,7 @@ public class ItemAction extends MapleQuestAction {
}
for(Pair<Integer, Integer> iPair: giveItem) {
MapleInventoryManipulator.addById(chr.getClient(), iPair.getLeft(), (short) iPair.getRight().shortValue());
MapleInventoryManipulator.addById(chr.getClient(), iPair.getLeft(), (short) iPair.getRight().shortValue(), "", -1);
chr.announce(MaplePacketCreator.getShowItemGain(iPair.getLeft(), (short) iPair.getRight().shortValue(), true));
}
}

View File

@@ -1996,9 +1996,9 @@ public class MaplePacketCreator {
MapleMiniGame miniGame = chr.getMiniGame();
if (miniGame != null && miniGame.isOwner(chr)) {
if (miniGame.hasFreeSlot()) {
spawnAnnounceBox(mplew, miniGame, 0, 1, 0);
addAnnounceBox(mplew, miniGame, 1, 0);
} else {
spawnAnnounceBox(mplew, miniGame, 0, 2, 1);
addAnnounceBox(mplew, miniGame, 2, miniGame.isMatchInProgress() ? 1 : 0);
}
} else {
mplew.write(0);
@@ -2170,23 +2170,12 @@ public class MaplePacketCreator {
mplew.write(0);
}
private static void addAnnounceBox(final MaplePacketLittleEndianWriter mplew, MapleMiniGame game, int type, int ammount, int joinable) {
mplew.write(game.getGameType().getValue());
mplew.writeInt(game.getObjectId()); // gameid/shopid
mplew.writeMapleAsciiString(game.getDescription()); // desc
mplew.writeMapleAsciiString(game.getPassword());
mplew.write(type);
mplew.write(ammount);
mplew.write(2);
mplew.write(joinable);
}
private static void spawnAnnounceBox(final MaplePacketLittleEndianWriter mplew, MapleMiniGame game, int type, int ammount, int joinable) {
private static void addAnnounceBox(final MaplePacketLittleEndianWriter mplew, MapleMiniGame game, int ammount, int joinable) {
mplew.write(game.getGameType().getValue());
mplew.writeInt(game.getObjectId()); // gameid/shopid
mplew.writeMapleAsciiString(game.getDescription()); // desc
mplew.writeBool(!game.getPassword().isEmpty()); // password here, thanks GabrielSin!
mplew.write(type);
mplew.write(game.getPieceType());
mplew.write(ammount);
mplew.write(2); //player capacity
mplew.write(joinable);
@@ -5016,7 +5005,7 @@ public class MaplePacketCreator {
mplew.writeInt(minigame.getOwner().getMiniGamePoints(MiniGameResult.WIN, true));
mplew.writeInt(minigame.getOwner().getMiniGamePoints(MiniGameResult.TIE, true));
mplew.writeInt(minigame.getOwner().getMiniGamePoints(MiniGameResult.LOSS, true));
mplew.writeInt(2000);
mplew.writeInt(minigame.getOwnerScore());
if (minigame.getVisitor() != null) {
MapleCharacter visitor = minigame.getVisitor();
mplew.write(1);
@@ -5024,7 +5013,7 @@ public class MaplePacketCreator {
mplew.writeInt(visitor.getMiniGamePoints(MiniGameResult.WIN, true));
mplew.writeInt(visitor.getMiniGamePoints(MiniGameResult.TIE, true));
mplew.writeInt(visitor.getMiniGamePoints(MiniGameResult.LOSS, true));
mplew.writeInt(2000);
mplew.writeInt(minigame.getVisitorScore());
}
mplew.write(0xFF);
mplew.writeMapleAsciiString(minigame.getDescription());
@@ -5115,7 +5104,7 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
public static byte[] getMiniGameNewVisitor(MapleCharacter c, int slot) {
public static byte[] getMiniGameNewVisitor(MapleMiniGame minigame, MapleCharacter c, int slot) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
mplew.write(PlayerInteractionHandler.Action.VISIT.getCode());
@@ -5126,7 +5115,7 @@ public class MaplePacketCreator {
mplew.writeInt(c.getMiniGamePoints(MiniGameResult.WIN, true));
mplew.writeInt(c.getMiniGamePoints(MiniGameResult.TIE, true));
mplew.writeInt(c.getMiniGamePoints(MiniGameResult.LOSS, true));
mplew.writeInt(2000);
mplew.writeInt(minigame.getVisitorScore());
return mplew.getPacket();
}
@@ -5138,50 +5127,64 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
private static byte[] getMiniGameResult(MapleMiniGame game, int win, int lose, int tie, int result, int forfeit, boolean omok) {
private static byte[] getMiniGameResult(MapleMiniGame game, int tie, int result, int forfeit) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
mplew.write(PlayerInteractionHandler.Action.GET_RESULT.getCode());
int matchResultType;
if (tie == 0 && forfeit != 1) {
mplew.write(0);
} else if (tie == 1) {
mplew.write(1);
} else if (forfeit == 1) {
mplew.write(2);
matchResultType = 0;
} else if (tie != 0) {
matchResultType = 1;
} else {
matchResultType = 2;
}
mplew.write(0); // owner
mplew.writeInt(1); // unknown
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.WIN, omok) + win); // wins
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.TIE, omok) + tie); // ties
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.LOSS, omok) + lose); // losses
mplew.writeInt(2000); // points
mplew.writeInt(1); // start of visitor; unknown
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.WIN, omok) + lose); // wins
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.TIE, omok) + tie); // ties
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.LOSS, omok) + win); // losses
mplew.writeInt(2000); // points
game.getOwner().setMiniGamePoints(game.getVisitor(), result, omok);
mplew.write(matchResultType);
mplew.writeBool(result == 2); // host/visitor wins
boolean omok = game.isOmok();
if (matchResultType == 1) {
mplew.write(0);
mplew.writeShort(0);
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.WIN, omok)); // wins
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.TIE, omok)); // ties
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.LOSS, omok)); // losses
mplew.writeInt(game.getOwnerScore()); // points
mplew.writeInt(0); // unknown
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.WIN, omok)); // wins
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.TIE, omok)); // ties
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.LOSS, omok)); // losses
mplew.writeInt(game.getVisitorScore()); // points
mplew.write(0);
} else {
mplew.writeInt(0);
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.WIN, omok)); // wins
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.TIE, omok)); // ties
mplew.writeInt(game.getOwner().getMiniGamePoints(MiniGameResult.LOSS, omok)); // losses
mplew.writeInt(game.getOwnerScore()); // points
mplew.writeInt(0);
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.WIN, omok)); // wins
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.TIE, omok)); // ties
mplew.writeInt(game.getVisitor().getMiniGamePoints(MiniGameResult.LOSS, omok)); // losses
mplew.writeInt(game.getVisitorScore()); // points
}
return mplew.getPacket();
}
public static byte[] getMiniGameOwnerWin(MapleMiniGame game) {
return getMiniGameResult(game, 0, 1, 0, 1, 0, true);
public static byte[] getMiniGameOwnerWin(MapleMiniGame game, boolean forfeit) {
return getMiniGameResult(game, 0, 1, forfeit ? 1 : 0);
}
public static byte[] getMiniGameVisitorWin(MapleMiniGame game) {
return getMiniGameResult(game, 1, 0, 0, 2, 0, true);
public static byte[] getMiniGameVisitorWin(MapleMiniGame game, boolean forfeit) {
return getMiniGameResult(game, 0, 2, forfeit ? 1 : 0);
}
public static byte[] getMiniGameTie(MapleMiniGame game) {
return getMiniGameResult(game, 0, 0, 1, 3, 0, true);
}
public static byte[] getMiniGameOwnerForfeit(MapleMiniGame game) {
return getMiniGameResult(game, 0, 1, 0, 2, 1, true);
}
public static byte[] getMiniGameVisitorForfeit(MapleMiniGame game) {
return getMiniGameResult(game, 1, 0, 0, 1, 1, true);
return getMiniGameResult(game, 1, 3, 0);
}
public static byte[] getMiniGameClose(int type) {
@@ -5215,7 +5218,9 @@ public class MaplePacketCreator {
mplew.writeInt(minigame.getOwner().getMiniGamePoints(MiniGameResult.WIN, false));
mplew.writeInt(minigame.getOwner().getMiniGamePoints(MiniGameResult.TIE, false));
mplew.writeInt(minigame.getOwner().getMiniGamePoints(MiniGameResult.LOSS, false));
mplew.writeInt(2000);
//set vs
mplew.writeInt(minigame.getOwnerScore());
if (minigame.getVisitor() != null) {
MapleCharacter visitor = minigame.getVisitor();
mplew.write(1);
@@ -5223,7 +5228,7 @@ public class MaplePacketCreator {
mplew.writeInt(visitor.getMiniGamePoints(MiniGameResult.WIN, false));
mplew.writeInt(visitor.getMiniGamePoints(MiniGameResult.TIE, false));
mplew.writeInt(visitor.getMiniGamePoints(MiniGameResult.LOSS, false));
mplew.writeInt(2000);
mplew.writeInt(minigame.getVisitorScore());
}
mplew.write(0xFF);
mplew.writeMapleAsciiString(minigame.getDescription());
@@ -5237,20 +5242,24 @@ public class MaplePacketCreator {
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
mplew.write(PlayerInteractionHandler.Action.START.getCode());
mplew.write(loser);
mplew.write(0x0C);
int last = 13;
int last;
if (game.getMatchesToWin() > 10) {
last = 31;
last = 30;
} else if (game.getMatchesToWin() > 6) {
last = 21;
last = 20;
} else {
last = 12;
}
for (int i = 1; i < last; i++) {
mplew.write(last);
for (int i = 0; i < last; i++) {
mplew.writeInt(game.getCardId(i));
}
return mplew.getPacket();
}
public static byte[] getMatchCardNewVisitor(MapleCharacter c, int slot) {
public static byte[] getMatchCardNewVisitor(MapleMiniGame minigame, MapleCharacter c, int slot) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.PLAYER_INTERACTION.getValue());
mplew.write(PlayerInteractionHandler.Action.VISIT.getCode());
@@ -5261,7 +5270,7 @@ public class MaplePacketCreator {
mplew.writeInt(c.getMiniGamePoints(MiniGameResult.WIN, false));
mplew.writeInt(c.getMiniGamePoints(MiniGameResult.TIE, false));
mplew.writeInt(c.getMiniGamePoints(MiniGameResult.LOSS, false));
mplew.writeInt(2000);
mplew.writeInt(minigame.getVisitorScore());
return mplew.getPacket();
}
@@ -5280,18 +5289,6 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
public static byte[] getMatchCardOwnerWin(MapleMiniGame game) {
return getMiniGameResult(game, 1, 0, 0, 1, 0, false);
}
public static byte[] getMatchCardVisitorWin(MapleMiniGame game) {
return getMiniGameResult(game, 0, 1, 0, 2, 0, false);
}
public static byte[] getMatchCardTie(MapleMiniGame game) {
return getMiniGameResult(game, 0, 0, 1, 3, 0, false);
}
public static byte[] fredrickMessage(byte operation) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.FREDRICK_MESSAGE.getValue());
@@ -5343,7 +5340,7 @@ public class MaplePacketCreator {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(c.getId());
addAnnounceBox(mplew, c.getMiniGame(), 0, ammount, type);
addAnnounceBox(mplew, c.getMiniGame(), ammount, type);
return mplew.getPacket();
}
@@ -5351,7 +5348,7 @@ public class MaplePacketCreator {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.UPDATE_CHAR_BOX.getValue());
mplew.writeInt(c.getId());
addAnnounceBox(mplew, c.getMiniGame(), 0, ammount, type);
addAnnounceBox(mplew, c.getMiniGame(), ammount, type);
return mplew.getPacket();
}
@@ -6005,7 +6002,7 @@ public class MaplePacketCreator {
mplew.write(new byte[]{-1, -1, -1, 0});
return mplew.getPacket();
}
public static byte[] showCouponRedeemedItem(int itemid) {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.writeShort(SendOpcode.CASHSHOP_OPERATION.getValue());
@@ -6030,11 +6027,8 @@ public class MaplePacketCreator {
return mplew.getPacket();
}
public static byte[] enableCSUse() {
final MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
mplew.write(0x12);
mplew.skip(6);
return mplew.getPacket();
public static byte[] enableCSUse(MapleCharacter mc) {
return showCash(mc);
}
/**

View File

@@ -1,129 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tools.dropspider;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import provider.MapleData;
import provider.MapleDataDirectoryEntry;
import provider.MapleDataFileEntry;
import provider.MapleDataProvider;
import provider.MapleDataProviderFactory;
import provider.MapleDataTool;
import server.MapleItemInformationProvider;
import tools.Pair;
/**
*
* @author Simon
*/
public class DataTool {
private static Map<String, Integer> hardcodedMobs = new HashMap<>();
private static ArrayList<Pair<Integer, String>> npc_list = null;
private static LinkedList<Pair<Integer, String>> mob_pairs = null;
private static MapleDataProvider data = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Mob.wz"));
private static HashSet<Integer> bosses = null;
public static void setHardcodedMobNames() {
hardcodedMobs.put("Red Slime [2]", 7120103);
hardcodedMobs.put("Gold Slime", 7120105);
hardcodedMobs.put("Nibelung [3]", 8220015);
}
public static void addMonsterIdsFromHardcodedName(List<Integer> monster_ids, String monster_name) {
Integer id = hardcodedMobs.get(monster_name);
if(id != null) {
monster_ids.add(id);
}
}
public static ArrayList<Integer> monsterIdsFromName(String name) {
MapleData data = null;
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz"));
ArrayList<Integer> ret = new ArrayList<>();
data = dataProvider.getData("Mob.img");
if (mob_pairs == null) {
mob_pairs = new LinkedList<>();
for (MapleData mobIdData : data.getChildren()) {
int mobIdFromData = Integer.parseInt(mobIdData.getName());
String mobNameFromData = MapleDataTool.getString(mobIdData.getChildByPath("name"), "NO-NAME");
mob_pairs.add(new Pair<>(mobIdFromData, mobNameFromData));
}
}
for (Pair<Integer, String> mobPair : mob_pairs) {
if (mobPair.getRight().toLowerCase().equals(name.toLowerCase())) {
ret.add(mobPair.getLeft());
}
}
return ret;
}
private static void populateBossList() {
bosses = new HashSet<>();
MapleDataDirectoryEntry mob_data = data.getRoot();
for (MapleDataFileEntry mdfe : mob_data.getFiles()) {
MapleData boss_candidate = data.getData(mdfe.getName());
MapleData monsterInfoData = boss_candidate.getChildByPath("info");
int mid = Integer.valueOf(boss_candidate.getName().replaceAll("[^0-9]", ""));
boolean boss = MapleDataTool.getIntConvert("boss", monsterInfoData, 0) > 0 || mid == 8810018 || mid == 9410066;
if (boss) {
bosses.add(mid);
}
}
}
public static boolean isBoss(int mid) {
if (bosses == null) {
populateBossList();
}
return bosses.contains(mid);
}
public static ArrayList<Integer> itemIdsFromName(String name) {
ArrayList<Integer> ret = new ArrayList<>();
for (Pair<Integer, String> itemPair : MapleItemInformationProvider.getInstance().getAllItems()) {
String item_name = itemPair.getRight().toLowerCase().replaceAll("\\&quot;", "");
item_name = item_name.replaceAll("'", "");
item_name = item_name.replaceAll("\\'", "");
name = name.toLowerCase().replaceAll("\\&quot;", "");
name = name.replaceAll("'", "");
name = name.replaceAll("\\'", "");
if (item_name.equals(name)) {
ret.add(itemPair.getLeft());
return ret;
}
}
return ret;
}
public static ArrayList<Integer> npcIdsFromName(String name) {
MapleDataProvider dataProvider = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/" + "String.wz"));
ArrayList<Integer> ret = new ArrayList<>();
if (npc_list == null) {
ArrayList<Pair<Integer, String>> searchList = new ArrayList<>();
for (MapleData searchData : dataProvider.getData("Npc.img").getChildren()) {
int searchFromData = Integer.parseInt(searchData.getName());
String infoFromData = MapleDataTool.getString(searchData.getChildByPath("name"), "NO-NAME");
searchList.add(new Pair<>(searchFromData, infoFromData));
}
npc_list = searchList;
}
for (Pair<Integer, String> searched : npc_list) {
if (searched.getRight().toLowerCase().contains(name.toLowerCase())) {
ret.add(searched.getLeft());
}
}
return ret;
}
}

View File

@@ -1,177 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tools.dropspider;
import client.inventory.MapleInventoryType;
import constants.ItemConstants;
/**
*
* @author Simon
*/
public class DropEntry {
private int version;
private int item_id;
private int monster_id;
private int chance;
private int mindrop;
private int maxdrop;
public DropEntry(int item_id, int monster_id, int version) {
this.item_id = item_id;
this.monster_id = monster_id;
mindrop = 1;
maxdrop = 1;
chance = calculateChance(item_id);
this.version = version;
}
private int calculateChance(int item_id) {
MapleInventoryType mit = ItemConstants.getInventoryType(item_id);
boolean boss = DataTool.isBoss(monster_id);
int number = (item_id / 1000) % 1000;
switch (mit) {
case EQUIP:
if (boss) {
return 40000;
}
return 700;
case USE:
if (boss) {
mindrop = 1;
maxdrop = 4;
}
switch (number) {
case 0: // normal potions
mindrop = 1;
if (version > 98) {
maxdrop = 5;
}
return 40000;
case 1: // watermelons, pills, speed potions, etc
case 2: // same thing
return 10000;
case 3: // advanced potions from crafting (should not drop)
case 4: // same thing
case 11: // poison mushroom
case 28: // cool items
case 30: // return scrolls
case 46: // gallant scrolls
return 0;
case 10: // strange potions like apples, eggs
case 12: // drakes blood, sap of ancient tree (rare use)
case 20: // salad, fried chicken, dews
case 22: // air bubbles and stuff. ALSO nependeath honey but oh well
case 50: // antidotes and stuff
return 3000;
case 290: // mastery books
if(boss)
return 40000;
else
return 1000;
case 40: // Scrolls
case 41: // Scrolls
case 43: // Scrolls
case 44: // Scrolls
case 48: // pet scrolls
if(boss)
return 10000;
else
return 750;
case 100: // summon bags
case 101: // summon bags
case 102: // summon bags
case 109: // summon bags
case 120: // pet food
case 211: // cliffs special potion
case 240: // rings
case 270: // pheromone, additional weird stuff
case 310: // teleport rock
case 320: // weird drops
case 390: // weird
case 430: // Scripted items
case 440: // jukebox
case 460: // magnifying glass
case 470: // golden hammer
case 490: // crystanol
case 500: // sp reset
return 0;
case 47: // tablets from dragon rider
return 220000;
case 49: // clean slats, potential scroll, ees
case 70: // throwing stars
case 210: // rare monster piece drops
case 330: // bullets
if(boss)
return 2500;
else
return 400;
case 60: // bow arrows
case 61: // crossbow arrows
mindrop = 10;
maxdrop = 50;
return 10000;
case 213: // boss transfrom
return 100000;
case 280: // skill books
if(boss)
return 20000;
else
return 1000;
case 381: // monster book things
case 382:
case 383:
case 384:
case 385:
case 386:
case 387:
case 388:
return 20000;
case 510: // recipes
case 511:
case 512:
return 10000;
default:
return 0;
}
case ETC:
switch (number) {
case 0: // monster pieces
return 200000;
case 4: // crystal ores
case 130: // simulators
case 131: // manuals
return 3000;
case 30: // game pieces
return 10000;
case 32: // misc items
return 10000;
default:
return 7000;
}
default:
return 7000;
}
}
public String getQuerySegment() {
StringBuilder sb = new StringBuilder();
sb.append("(");
sb.append(monster_id);
sb.append(", ");
sb.append(item_id);
sb.append(", ");
sb.append(mindrop);//min
sb.append(", ");
sb.append(maxdrop);//max
sb.append(", ");
sb.append(0);//quest
sb.append(", ");
sb.append(chance);
sb.append(")");
return sb.toString();
}
}

View File

@@ -1,19 +0,0 @@
package tools.dropspider;
import java.util.LinkedList;
public class Errors {
public String mobName;
public LinkedList<String> wrong = new LinkedList<>();
public String createErrorLog() {
StringBuilder sb = new StringBuilder();
for (String w : wrong) {
sb.append(mobName).append(" : ").append(w).append("\r\n");
}
return sb.toString();
}
}

View File

@@ -1,339 +0,0 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package tools.dropspider;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
import javax.net.ssl.HttpsURLConnection;
/**
*
* @author Simon
*/
//NOTE: this tool is currently unsupported since HS started using HTTPS. Missing proper SSL certificates to access Hidden-Street's website.
public class Main {
private static ArrayList<DropEntry> drop_entries = new ArrayList<>();
private static HashMap<String, Errors> problems = new HashMap<>();
// private static final String TEST_STRING = " <a href=\"/items/leftover/ligator-skin\" alt=\"/tip.php?nid=2138\">Ligator Skin</a>, <a href=\"/items/leftover/the-magic-rock\" alt=\"/tip.php?nid=3954\">The Magic Rock</a>, <a href=\"/items/quest/witch-grass-leaves\" alt=\"/tip.php?nid=6129\">Witch Grass Leaves</a> </td> ";
private static final String BASE_URL = "https://bbb.hidden-street.net";
private static final int VERSION = 83;
private static String[] pages = {"1-10", "11-20", "21-30", "31-40", "41-50", "51-60", "61-70", "71-80", "81-90", "91-100"};
private static String[] additionalPages88 = {"101-150", "151-200"};
private static String[] additionalPagesBB = {"101-120,", "121-140", "141-160", "161-180", "181-200"};
public static void main(String[] args) {
System.setProperty("wzpath", "wz");
//DataTool.setHardcodedMobNames();
//parsePage("https://bbb.hidden-street.net/monster/nibelung-3");
crawlProgram();
dumpQuery();
dumpErrors();
}
private static void crawlProgram() {
//parseMonsterSection(TEST_STRING);
for (String s : pages) {
crawlPage("https://bbb.hidden-street.net/monster/" + s);
}
if (VERSION > 92) { // big bang
for (String s : additionalPagesBB) {
crawlPage("https://bbb.hidden-street.net/monster/" + s);
}
crawlPage("https://bbb.hidden-street.net/monster/101-120?page=1"); //page 1's bugged
} else {
for (String s : additionalPages88) {
crawlPage("https://bbb.hidden-street.net/monster/" + s);
}
}
}
private static void crawlPage(String url) { //recursive method
try {
URL page = new URL(url);
//Authenticator.setDefault( new MyAuthenticator()); // todo keystore/truststore pass
HttpsURLConnection http = (HttpsURLConnection)page.openConnection();
http.setAllowUserInteraction(true);
http.setRequestMethod("GET");
http.connect();
InputStream is = http.getInputStream();
Scanner s = new Scanner(is);
String temp_data = "";
while (s.hasNext()) {
temp_data += s.nextLine() + "\n";
}
s.close();
is.close();
while (temp_data.contains("class=\"monster\">")) {
String monster_section = getStringBetween(temp_data, "class=\"monster\">", "</table>");
parseMonsterSection(monster_section);
temp_data = trimUntil(temp_data, "</table>");
}
if (temp_data.contains("Go to next page")) {
String next_url_segment = getStringBetween(temp_data, "<li class=\"pager-next\"><a href=\"", "\" title=\"Go to next page");
String next_url = BASE_URL + next_url_segment;
crawlPage(next_url);
} else {
System.out.println("Finished crawling section.");
}
} catch (MalformedURLException mue) {
mue.printStackTrace();
System.out.println("Error parsing URL: " + url);
return;
} catch (IOException ioe) {
ioe.printStackTrace();
System.out.println("Error reading from URL: " + ioe.getLocalizedMessage());
return;
}
}
private static void parsePage(String url) { //unit method
try {
URL page = new URL(url);
InputStream is = page.openStream();
Scanner s = new Scanner(is);
String temp_data = "";
while (s.hasNext()) {
temp_data += s.nextLine() + "\n";
}
s.close();
is.close();
while (temp_data.contains("class=\"monster\">")) {
String monster_section = getStringBetween(temp_data, "class=\"monster\">", "</table>");
parseMonsterSection(monster_section);
temp_data = trimUntil(temp_data, "</table>");
}
if (temp_data.contains("Go to next page")) {
String next_url_segment = getStringBetween(temp_data, "<li class=\"pager-next\"><a href=\"", "\" title=\"Go to next page");
String next_url = BASE_URL + next_url_segment;
//crawlPage(next_url);
} else {
System.out.println("Finished parsing section.");
}
} catch (MalformedURLException mue) {
mue.printStackTrace();
System.out.println("Error parsing URL: " + url);
return;
} catch (IOException ioe) {
ioe.printStackTrace();
System.out.println("Error reading from URL: " + ioe.getLocalizedMessage());
return;
}
}
private static void parseMonsterSection(String html_data) {
String monster_name = getStringBetween(html_data, "alt=\"", "\" title=");
System.out.println(monster_name);
// System.out.println(html_data);
//parse etc drop
parseItemSection(getStringBetween(html_data, "Etc. drop:</strong>", "</td>"), monster_name);
//parse useable drop
parseItemSection(getStringBetween(html_data, "Useable drop:</strong>", "</td>"), monster_name);
//parse ore drop
parseItemSection(getStringBetween(html_data, "Ore drop:</strong>", "</td>"), monster_name);
//parse equips
parseItemSection(getStringBetween(html_data, "Common equipment:</strong>", "</div>"), monster_name);
parseItemSection(getStringBetween(html_data, "Warrior equipment:</strong>", "</div>"), monster_name);
parseItemSection(getStringBetween(html_data, "Magician equipment:</strong>", "</div>"), monster_name);
parseItemSection(getStringBetween(html_data, "Bowman equipment:</strong>", "</div>"), monster_name);
parseItemSection(getStringBetween(html_data, "Thief equipment:</strong>", "</div>"), monster_name);
parseItemSection(getStringBetween(html_data, "Pirate equipment:</strong>", "</div>"), monster_name);
//System.out.println(monster_name);
}
private static void parseItemSection(String html_data, String monster_name) {
String temp_data = html_data;
while (temp_data.contains("<a href")) {
// System.out.println("Temp_data: " + temp_data);
String s1 = trimUntil(temp_data, ">");
String item_name = getStringBetween(s1, "", "</a>");
temp_data = trimUntil(temp_data, "</a>");
boolean gender_equip = false;
if (item_name.contains("(M)") || item_name.contains("(F)")) {
item_name = item_name.replaceAll("(\\(M\\))|(\\(F\\))", "");
gender_equip = true;
}
item_name = item_name.replaceAll("Throwing-Star", "Throwing-Stars").trim();
item_name = item_name.replaceAll("for Magic Attack", "for Magic Att.").trim();
item_name = item_name.replaceAll("\\(50%\\)", "").trim();
item_name = item_name.replaceAll("\\(70%\\)", "").trim();
item_name = item_name.replaceAll("\\'s", "").trim();
monster_name = monster_name.replaceAll("Horntail\\'s Head B", "Horntail");
// Process scrolls, nexon doesn't have the % on most of the scrolls. So we need to remove it
// Unfortunately they do for some, so we have to handle that too.
boolean scroll = false;
int scrollType = 0;
if(item_name.contains("100%")) {
scroll = true;
item_name = item_name.replaceAll("100%", "").trim();
item_name = item_name.replaceAll("\\(\\)", "").trim(); // Hidden Street has a few scroll %'s with ()s around them.. sigh
} else if(item_name.contains("60%")) {
scroll = true;
scrollType = 1;
item_name = item_name.replaceAll("60%", "").trim();
item_name = item_name.replaceAll("\\(\\)", "").trim();
} else if(item_name.contains("10%")) {
scroll = true;
scrollType = 2;
item_name = item_name.replaceAll("10%", "").trim();
item_name = item_name.replaceAll("\\(\\)", "").trim();
//f(item_name.contains(" ()")) item_name = item_name.substring(0, item_name.lastIndexOf(" ("));
} else if(item_name.contains("70%")) {
scroll = true;
scrollType = 4;
item_name = item_name.replaceAll("70%", "").trim();
item_name = item_name.replaceAll("\\(\\)", "").trim();
} else if(item_name.contains("30%")) {
scroll = true;
scrollType = 5;
item_name = item_name.replaceAll("30%", "").trim();
item_name = item_name.replaceAll("\\(\\)", "").trim();
}
// System.out.println("Item name: " + item_name);
//drop entry
ArrayList<Integer> monster_ids = DataTool.monsterIdsFromName(monster_name);
//DataTool.addMonsterIdsFromHardcodedName(monster_ids, monster_name);
ArrayList<Integer> item_ids = DataTool.itemIdsFromName(item_name);
if(scroll && item_ids.isEmpty()) {
// Try adding on the % again. Thanks nexon...
if(scrollType == 0) item_name += " 100%";
if(scrollType == 1) item_name += " 60%";
if(scrollType == 2) item_name += " 10%";
if(scrollType == 4) item_name += " 70%";
if(scrollType == 5) item_name += " 30%";
item_ids = DataTool.itemIdsFromName(item_name);
}
if (!monster_ids.isEmpty() && !item_ids.isEmpty()) {
int item_id = item_ids.get(0);
if(scroll) {
item_id += scrollType;
}
int item_id_2 = -1;
for (Integer mob_id : monster_ids) {
System.out.println("Monster ID: " + mob_id + ", Item ID: " + item_id);
drop_entries.add(new DropEntry(item_id, mob_id, VERSION));
if (gender_equip && item_ids.size() > 1) {
item_id_2 = item_ids.get(1);
drop_entries.add(new DropEntry(item_id_2, mob_id, VERSION));
}
}
} else {
System.out.println("Error parsing item " + item_name + " dropped by " + monster_name + ".");
if (!monster_ids.isEmpty()) {
if (!problems.containsKey(monster_name)) {
Errors e = new Errors();
e.mobName = monster_name;
problems.put(monster_name, e);
}
problems.get(monster_name).wrong.add(item_name);
}
//System.out.println("Monster ids size: " + monster_ids.size() + ", Item IDs size: " + item_ids.size());
}
}
}
/**
* Returns the string lying between the two specified strings.
*
* @param line The string to parse
* @param start The first string
* @param end The last string
* @return The string between the two specified strings
*/
public static String getStringBetween(String line, String start, String end) {
int start_offset = line.indexOf(start) + start.length();
return line.substring(start_offset, line.substring(start_offset).indexOf(end) + start_offset);
}
public static String trimUntil(String line, String until) {
int until_pos = line.indexOf(until);
if (until_pos == -1) {
return null;
} else {
return line.substring(until_pos + until.length());
}
}
public static void dumpErrors() {
String file = "errors.txt";
try {
File f = new File(file);
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
PrintWriter pw = new PrintWriter(bw);
for (Errors err : problems.values()) {
pw.write(err.createErrorLog());
}
pw.flush();
pw.close();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void dumpQuery() {
String filename = "drops.sql";
try {
File output = new File(filename);
BufferedWriter bw = new BufferedWriter(new FileWriter(output));
PrintWriter pw = new PrintWriter(bw);
StringBuilder sb = new StringBuilder();
pw.write("TRUNCATE TABLE `drop_data`;\r\n");
pw.write("INSERT INTO `drop_data` (`dropperid`, `itemid`, `minimum_quantity`, `maximum_quantity`, `questid`, `chance`) VALUES ");
for (Iterator<DropEntry> i = drop_entries.iterator(); i.hasNext();) {
DropEntry de = i.next();
pw.write(de.getQuerySegment());
if (i.hasNext()) {
pw.write(", \r\n");
}
}
pw.write(sb.toString());
pw.close();
bw.close();
} catch (IOException ioe) {
ioe.printStackTrace();
System.out.println("Error writing to file: " + ioe.getLocalizedMessage());
}
}
}