Quest progress overview + Raise UI scripting + Shelved events loadout

Performed a syllabus over quest progress tracking. Quests that were supposed to show up as startable/completable upon achieved progress should be able to do so. Reviewed progress tracking on scripts to adequate to this scenario.
Fixed some scenarios on where quest dialog popups would appear when updating a quest progress.
Fixed some scripts not using updated package addresses after the recent package refactor.
Reviewed Raise UI, no longer rendering players unable to access CS/MTS in certain scenarios.
Fixed a check of available space in inventory, when trying to obtain items from quests, not informing the player it happened due to a one-of-a-kind item already present.
Fixed quest dialog (feature present in many quests) not showing to players when completing it.
Fixed several issues with the Cygnus 1st job advancement quests.
Added scripting within Raise UI open action. Mimiana egg uses this to keep track of player's EXP progress.
Fixed pets not getting despawned as expiration takes place.
Fixed hidden players being able to control mobs when either entering map or hidden state.
Fixed estimated HP/MP alert not taking bonuses (such as from buffs or equipments) into account.
Fixed Energy Charge refreshing buff time upon touching mobs, skewing the  uptime of the skill's stat buffs.
Switched SnakeYaml for YamlBeans, which makes up for a single JAR artifact.
Refactored a channel's event scripts loadout, now taking place after the server bootup phase.
This commit is contained in:
ronancpl
2019-10-03 20:01:09 -03:00
parent eae6dccbc0
commit 7ee947b404
190 changed files with 3281 additions and 1880 deletions

View File

@@ -862,7 +862,7 @@ public class Server {
}
applyAllNameChanges(); //name changes can be missed by INSTANT_NAME_CHANGE
applyAllWorldTransfers();
MaplePet.clearMissingPetsFromDb();
//MaplePet.clearMissingPetsFromDb(); // thanks Optimist for noticing this taking too long to run
MapleCashidGenerator.loadExistentCashIdsFromDb();
IoBuffer.setUseDirectBuffer(false);
@@ -877,17 +877,17 @@ public class Server {
disconnectIdlesOnLoginTask();
long timeLeft = getTimeLeftForNextHour();
tMan.register(new CharacterDiseaseTask(), ServerConstants.UPDATE_INTERVAL, ServerConstants.UPDATE_INTERVAL);
tMan.register(new CharacterDiseaseTask(), YamlConfig.config.server.UPDATE_INTERVAL, YamlConfig.config.server.UPDATE_INTERVAL);
tMan.register(new ReleaseLockTask(), 2 * 60 * 1000, 2 * 60 * 1000);
tMan.register(new CouponTask(), ServerConstants.COUPON_INTERVAL, timeLeft);
tMan.register(new CouponTask(), YamlConfig.config.server.COUPON_INTERVAL, timeLeft);
tMan.register(new RankingCommandTask(), 5 * 60 * 1000, 5 * 60 * 1000);
tMan.register(new RankingLoginTask(), ServerConstants.RANKING_INTERVAL, timeLeft);
tMan.register(new RankingLoginTask(), YamlConfig.config.server.RANKING_INTERVAL, timeLeft);
tMan.register(new LoginCoordinatorTask(), 60 * 60 * 1000, timeLeft);
tMan.register(new EventRecallCoordinatorTask(), 60 * 60 * 1000, timeLeft);
tMan.register(new LoginStorageTask(), 2 * 60 * 1000, 2 * 60 * 1000);
tMan.register(new DueyFredrickTask(), 60 * 60 * 1000, timeLeft);
tMan.register(new InvitationTask(), 30 * 1000, 30 * 1000);
tMan.register(new RespawnTask(), ServerConstants.RESPAWN_INTERVAL, ServerConstants.RESPAWN_INTERVAL);
tMan.register(new RespawnTask(), YamlConfig.config.server.RESPAWN_INTERVAL, YamlConfig.config.server.RESPAWN_INTERVAL);
timeLeft = getTimeLeftForNextDay();
MapleExpeditionBossLog.resetBossLogTable();
@@ -952,6 +952,10 @@ public class Server {
MapleSkillbookInformationProvider.getInstance();
OpcodeConstants.generateOpcodeNames();
CommandsExecutor.getInstance();
for (Channel ch : this.getAllChannels()) {
ch.reloadEventScriptManager();
}
}
public static void main(String args[]) {

View File

@@ -21,13 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.channel;
import net.server.channel.task.FaceExpressionScheduler;
import net.server.channel.task.MobMistScheduler;
import net.server.channel.task.OverallScheduler;
import net.server.channel.task.MobAnimationScheduler;
import net.server.channel.task.MobStatusScheduler;
import net.server.channel.task.MobClearSkillScheduler;
import net.server.channel.task.EventScheduler;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.ArrayList;
@@ -57,6 +50,7 @@ import net.mina.MapleCodecFactory;
import net.server.PlayerStorage;
import net.server.Server;
import net.server.channel.task.*;
import net.server.world.World;
import net.server.world.MapleParty;
@@ -84,7 +78,6 @@ import tools.MaplePacketCreator;
import tools.Pair;
import client.MapleCharacter;
import client.status.MonsterStatusEffect;
import constants.net.ServerConstants;
import server.maps.MapleMiniDungeonInfo;
public final class Channel {
@@ -148,7 +141,6 @@ public final class Channel {
this.ongoingStartTime = startTime + 10000; // rude approach to a world's last channel boot time, placeholder for the 1st wedding reservation ever
this.mapManager = new MapleMapManager(null, world, channel);
try {
eventSM = new EventScriptManager(this, getEvents());
port = 7575 + this.channel - 1;
port += (world * 100);
ip = YamlConfig.config.server.HOST + ":" + port;
@@ -163,7 +155,14 @@ public final class Channel {
for (MapleExpeditionType exped : MapleExpeditionType.values()) {
expedType.add(exped);
}
eventSM.init();
if (Server.getInstance().isOnline()) { // postpone event loading to improve boot time... thanks Riizade, daronhudson for noticing slow startup times
eventSM = new EventScriptManager(this, getEvents());
eventSM.init();
} else {
String[] ev = {};
eventSM = new EventScriptManager(null, ev);
}
dojoStage = new int[20];
dojoFinishTime = new long[20];
@@ -493,6 +492,11 @@ public final class Channel {
return getPlayerStorage().getCharacterByName(name) != null;
}
public boolean isActive() {
EventScriptManager esm = this.getEventSM();
return esm != null && esm.isActive();
}
public boolean finishedShutdown() {
return finishedShutdown;
}

View File

@@ -163,9 +163,11 @@ public abstract class AbstractDealDamageHandler extends AbstractMaplePacketHandl
int mobCount = attackEffect.getMobCount();
if (attack.skill != Cleric.HEAL) {
if (player.isAlive()) {
if(attack.skill == NightWalker.POISON_BOMB) {// Poison Bomb
if(attack.skill == Aran.BODY_PRESSURE || attack.skill == Marauder.ENERGY_CHARGE || attack.skill == ThunderBreaker.ENERGY_CHARGE) { // thanks IxianMace for noticing Energy Charge skills refreshing on touch, leading to misleading buff applies
// prevent touch dmg skills refreshing
} else if(attack.skill == NightWalker.POISON_BOMB) {// Poison Bomb
attackEffect.applyTo(player, new Point(attack.position.x, attack.position.y));
} else if(attack.skill != Aran.BODY_PRESSURE) {// prevent BP refreshing
} else {
attackEffect.applyTo(player);
if (attack.skill == DawnWarrior.FINAL_ATTACK || attack.skill == Page.FINAL_ATTACK_BW || attack.skill == Page.FINAL_ATTACK_SWORD || attack.skill == Fighter.FINAL_ATTACK_SWORD

View File

@@ -34,10 +34,11 @@ import server.movement.LifeMovementFragment;
import server.movement.RelativeLifeMovement;
import server.movement.TeleportMovement;
import tools.data.input.LittleEndianAccessor;
import tools.exceptions.EmptyMovementException;
public abstract class AbstractMovementPacketHandler extends AbstractMaplePacketHandler {
protected List<LifeMovementFragment> parseMovement(LittleEndianAccessor lea) {
protected List<LifeMovementFragment> parseMovement(LittleEndianAccessor lea) throws EmptyMovementException {
List<LifeMovementFragment> res = new ArrayList<>();
byte numCommands = lea.readByte();
for (byte i = 0; i < numCommands; i++) {
@@ -138,15 +139,20 @@ public abstract class AbstractMovementPacketHandler extends AbstractMaplePacketH
}
default:
System.out.println("Unhandled Case:" + command);
return null;
throw new EmptyMovementException(lea);
}
}
if (res.isEmpty()) {
throw new EmptyMovementException(lea);
}
return res;
}
protected void updatePosition(LittleEndianAccessor lea, AnimatedMapleMapObject target, int yOffset) {
protected void updatePosition(LittleEndianAccessor lea, AnimatedMapleMapObject target, int yOffset) throws EmptyMovementException {
byte numCommands = lea.readByte();
if (numCommands < 1) throw new EmptyMovementException(lea);
for (byte i = 0; i < numCommands; i++) {
byte command = lea.readByte();
switch (command) {
@@ -233,6 +239,5 @@ public abstract class AbstractMovementPacketHandler extends AbstractMaplePacketH
return;
}
}
return;
}
}

View File

@@ -149,8 +149,8 @@ public final class BBSOperationHandler extends AbstractMaplePacketHandler {
}
private static void editBBSThread(MapleClient client, String title, String text, int icon, int localthreadid) {
MapleCharacter c = client.getPlayer();
if (c.getGuildId() < 1) {
MapleCharacter chr = client.getPlayer();
if (chr.getGuildId() < 1) {
return;
}
try {
@@ -160,10 +160,10 @@ public final class BBSOperationHandler extends AbstractMaplePacketHandler {
ps.setLong(2, currentServerTime());
ps.setInt(3, icon);
ps.setString(4, text);
ps.setInt(5, c.getGuildId());
ps.setInt(5, chr.getGuildId());
ps.setInt(6, localthreadid);
ps.setInt(7, c.getId());
ps.setBoolean(8, c.getGuildRank() < 3);
ps.setInt(7, chr.getId());
ps.setBoolean(8, chr.getGuildRank() < 3);
ps.execute();
}
con.close();
@@ -174,8 +174,8 @@ public final class BBSOperationHandler extends AbstractMaplePacketHandler {
}
private static void newBBSThread(MapleClient client, String title, String text, int icon, boolean bNotice) {
MapleCharacter c = client.getPlayer();
if (c.getGuildId() <= 0) {
MapleCharacter chr = client.getPlayer();
if (chr.getGuildId() <= 0) {
return;
}
int nextId = 0;
@@ -184,7 +184,7 @@ public final class BBSOperationHandler extends AbstractMaplePacketHandler {
PreparedStatement ps;
if (!bNotice) {
ps = con.prepareStatement("SELECT MAX(localthreadid) AS lastLocalId FROM bbs_threads WHERE guildid = ?");
ps.setInt(1, c.getGuildId());
ps.setInt(1, chr.getGuildId());
try (ResultSet rs = ps.executeQuery()) {
rs.next();
nextId = rs.getInt("lastLocalId") + 1;
@@ -192,12 +192,12 @@ public final class BBSOperationHandler extends AbstractMaplePacketHandler {
ps.close();
}
ps = con.prepareStatement("INSERT INTO bbs_threads " + "(`postercid`, `name`, `timestamp`, `icon`, `startpost`, " + "`guildid`, `localthreadid`) " + "VALUES(?, ?, ?, ?, ?, ?, ?)");
ps.setInt(1, c.getId());
ps.setInt(1, chr.getId());
ps.setString(2, title);
ps.setLong(3, currentServerTime());
ps.setInt(4, icon);
ps.setString(5, text);
ps.setInt(6, c.getGuildId());
ps.setInt(6, chr.getGuildId());
ps.setInt(7, nextId);
ps.execute();
ps.close();

View File

@@ -30,7 +30,6 @@ import client.MapleCharacter;
import client.MapleClient;
import client.Skill;
import client.SkillFactory;
import constants.net.ServerConstants;
import constants.skills.Bishop;
import constants.skills.Evan;
import constants.skills.FPArchMage;
@@ -63,13 +62,9 @@ public final class MagicDamageHandler extends AbstractDealDamageHandler {
c.announce(MaplePacketCreator.getEnergy("energy", chr.getDojoEnergy()));
}
byte[] packet;
if ((attack.skill == Evan.FIRE_BREATH || attack.skill == Evan.ICE_BREATH || attack.skill == FPArchMage.BIG_BANG || attack.skill == ILArchMage.BIG_BANG || attack.skill == Bishop.BIG_BANG)) {
packet = MaplePacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.charge, attack.speed, attack.direction, attack.display);
} else {
packet = MaplePacketCreator.closeRangeAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, attack.speed, attack.direction, attack.display);
}
int charge = (attack.skill == Evan.FIRE_BREATH || attack.skill == Evan.ICE_BREATH || attack.skill == FPArchMage.BIG_BANG || attack.skill == ILArchMage.BIG_BANG || attack.skill == Bishop.BIG_BANG) ? attack.charge : -1;
byte[] packet = MaplePacketCreator.magicAttack(chr, attack.skill, attack.skilllevel, attack.stance, attack.numAttackedAndDamage, attack.allDamage, charge, attack.speed, attack.direction, attack.display);
chr.getMap().broadcastMessage(chr, packet, false, true);
MapleStatEffect effect = attack.getAttackEffect(chr, null);
Skill skill = SkillFactory.getSkill(attack.skill);

View File

@@ -28,6 +28,7 @@ import client.MapleClient;
import server.maps.MapleDragon;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.exceptions.EmptyMovementException;
public class MoveDragonHandler extends AbstractMovementPacketHandler {
@@ -35,19 +36,20 @@ public class MoveDragonHandler extends AbstractMovementPacketHandler {
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
final MapleCharacter chr = c.getPlayer();
final Point startPos = new Point(slea.readShort(), slea.readShort());
long movementDataStart = slea.getPosition();
final MapleDragon dragon = chr.getDragon();
if (dragon != null) {
updatePosition(slea, dragon, 0);
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
if (movementDataLength > 0) {
try {
long movementDataStart = slea.getPosition();
updatePosition(slea, dragon, 0);
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
slea.seek(movementDataStart);
if (chr.isHidden()) {
chr.getMap().broadcastGMMessage(chr, MaplePacketCreator.moveDragon(dragon, startPos, slea, movementDataLength));
} else {
chr.getMap().broadcastMessage(chr, MaplePacketCreator.moveDragon(dragon, startPos, slea, movementDataLength), dragon.getPosition());
}
}
} catch (EmptyMovementException e) {}
}
}
}

View File

@@ -41,6 +41,7 @@ import tools.MaplePacketCreator;
import tools.Pair;
import tools.Randomizer;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.exceptions.EmptyMovementException;
/**
* @author Danny (Leifde)
@@ -142,11 +143,7 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
short start_y = slea.readShort(); // hmm...
Point startPos = new Point(start_x, start_y - 2);
Point serverStartPos = new Point(monster.getPosition());
long movementDataStart = slea.getPosition();
updatePosition(slea, monster, -2); // Thanks Doodle and ZERO傑洛 for noticing sponge-based bosses moving out of stage in case of no-offset applied
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
Boolean aggro = monster.aggroMoveLifeUpdate(player);
if (aggro == null) return;
@@ -156,15 +153,21 @@ public final class MoveLifeHandler extends AbstractMovementPacketHandler {
c.announce(MaplePacketCreator.moveMonsterResponse(objectid, moveid, mobMp, aggro));
}
if (movementDataLength > 0) {
if (YamlConfig.config.server.USE_DEBUG_SHOW_RCVD_MVLIFE) {
System.out.println((isSkill ? "SKILL " : (isAttack ? "ATTCK " : " ")) + "castPos: " + castPos + " rawAct: " + rawActivity + " opt: " + pOption + " skillID: " + useSkillId + " skillLV: " + useSkillLevel + " " + "allowSkill: " + nextMovementCouldBeSkill + " mobMp: " + mobMp);
}
slea.seek(movementDataStart);
map.broadcastMessage(player, MaplePacketCreator.moveMonster(objectid, nextMovementCouldBeSkill, rawActivity, useSkillId, useSkillLevel, pOption, startPos, slea, movementDataLength), serverStartPos);
//updatePosition(res, monster, -2); //does this need to be done after the packet is broadcast?
map.moveMonster(monster, monster.getPosition());
}
try {
long movementDataStart = slea.getPosition();
updatePosition(slea, monster, -2); // Thanks Doodle and ZERO傑洛 for noticing sponge-based bosses moving out of stage in case of no-offset applied
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
slea.seek(movementDataStart);
if (YamlConfig.config.server.USE_DEBUG_SHOW_RCVD_MVLIFE) {
System.out.println((isSkill ? "SKILL " : (isAttack ? "ATTCK " : " ")) + "castPos: " + castPos + " rawAct: " + rawActivity + " opt: " + pOption + " skillID: " + useSkillId + " skillLV: " + useSkillLevel + " " + "allowSkill: " + nextMovementCouldBeSkill + " mobMp: " + mobMp);
}
map.broadcastMessage(player, MaplePacketCreator.moveMonster(objectid, nextMovementCouldBeSkill, rawActivity, useSkillId, useSkillLevel, pOption, startPos, slea, movementDataLength), serverStartPos);
//updatePosition(res, monster, -2); //does this need to be done after the packet is broadcast?
map.moveMonster(monster, monster.getPosition());
} catch (EmptyMovementException e) {}
if (banishPlayers != null) {
for (MapleCharacter chr : banishPlayers) {

View File

@@ -27,6 +27,7 @@ import client.MapleClient;
import server.movement.LifeMovementFragment;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.exceptions.EmptyMovementException;
public final class MovePetHandler extends AbstractMovementPacketHandler {
@Override
@@ -34,8 +35,11 @@ public final class MovePetHandler extends AbstractMovementPacketHandler {
int petId = slea.readInt();
slea.readLong();
// Point startPos = StreamUtil.readShortPoint(slea);
List<LifeMovementFragment> res = parseMovement(slea);
if (res == null || res.isEmpty()) {
List<LifeMovementFragment> res;
try {
res = parseMovement(slea);
} catch (EmptyMovementException e) {
return;
}
MapleCharacter player = c.getPlayer();

View File

@@ -24,22 +24,24 @@ package net.server.channel.handlers;
import client.MapleClient;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.exceptions.EmptyMovementException;
public final class MovePlayerHandler extends AbstractMovementPacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
slea.skip(9);
long movementDataStart = slea.getPosition();
updatePosition(slea, c.getPlayer(), 0);
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
if (movementDataLength > 0) {
slea.seek(movementDataStart);
try { // thanks Sa for noticing empty movement sequences crashing players
long movementDataStart = slea.getPosition();
updatePosition(slea, c.getPlayer(), 0);
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
slea.seek(movementDataStart);
c.getPlayer().getMap().movePlayer(c.getPlayer(), c.getPlayer().getPosition());
if (c.getPlayer().isHidden()) {
c.getPlayer().getMap().broadcastGMMessage(c.getPlayer(), MaplePacketCreator.movePlayer(c.getPlayer().getId(), slea, movementDataLength), false);
} else {
c.getPlayer().getMap().broadcastMessage(c.getPlayer(), MaplePacketCreator.movePlayer(c.getPlayer().getId(), slea, movementDataLength), false);
}
}
} catch (EmptyMovementException e) {}
}
}

View File

@@ -29,6 +29,7 @@ import client.MapleClient;
import server.maps.MapleSummon;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
import tools.exceptions.EmptyMovementException;
public final class MoveSummonHandler extends AbstractMovementPacketHandler {
@Override
@@ -45,11 +46,14 @@ public final class MoveSummonHandler extends AbstractMovementPacketHandler {
}
}
if (summon != null) {
long movementDataStart = slea.getPosition();
updatePosition(slea, summon, 0);
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
slea.seek(movementDataStart);
player.getMap().broadcastMessage(player, MaplePacketCreator.moveSummon(player.getId(), oid, startPos, slea, movementDataLength), summon.getPosition());
try {
long movementDataStart = slea.getPosition();
updatePosition(slea, summon, 0);
long movementDataLength = slea.getPosition() - movementDataStart; //how many bytes were read by updatePosition
slea.seek(movementDataStart);
player.getMap().broadcastMessage(player, MaplePacketCreator.moveSummon(player.getId(), oid, startPos, slea, movementDataLength), summon.getPosition());
} catch (EmptyMovementException e) {}
}
}
}

View File

@@ -43,12 +43,12 @@ public final class PetAutoPotHandler extends AbstractMaplePacketHandler {
MapleStatEffect stat = MapleItemInformationProvider.getInstance().getItemEffect(itemId);
if (stat.getHp() > 0 || stat.getHpRate() > 0.0) {
float estimatedHp = ((float) chr.getHp()) / chr.getMaxHp();
chr.setAutopotHpAlert(estimatedHp);
chr.setAutopotHpAlert(estimatedHp + 0.05f);
}
if (stat.getMp() > 0 || stat.getMpRate() > 0.0) {
float estimatedMp = ((float) chr.getMp()) / chr.getMaxMp();
chr.setAutopotMpAlert(estimatedMp);
chr.setAutopotMpAlert(estimatedMp + 0.05f);
}
PetAutopotProcessor.runAutopotAction(c, slot, itemId);

View File

@@ -116,13 +116,16 @@ public final class PlayerLoggedinHandler extends AbstractMaplePacketHandler {
}
Channel cserv = wserv.getChannel(c.getChannel());
if(cserv == null) {
if(cserv == null || !cserv.isActive()) {
c.setChannel(1);
cserv = wserv.getChannel(c.getChannel());
if(cserv == null) {
c.disconnect(true, false);
return;
} else if (!cserv.isActive()) {
c.announce(MaplePacketCreator.getAfterLoginError(7));
return;
}
}

View File

@@ -51,19 +51,21 @@ public final class PlayerMapTransitionHandler extends AbstractMaplePacketHandler
chr.announce(MaplePacketCreator.giveBuff(1, beaconid, stat));
}
for (MapleMapObject mo : chr.getMap().getMonsters()) { // thanks BHB, IxianMace, Jefe for noticing several issues regarding mob statuses (such as freeze)
MapleMonster m = (MapleMonster) mo;
if (m.getSpawnEffect() == 0 || m.getHp() < m.getMaxHp()) { // avoid effect-spawning mobs
if (m.getController() == chr) {
c.announce(MaplePacketCreator.stopControllingMonster(m.getObjectId()));
m.sendDestroyData(c);
m.aggroRedirectController();
} else {
m.sendDestroyData(c);
}
if (!chr.isHidden()) { // thanks Lame for noticing hidden characters controlling mobs
for (MapleMapObject mo : chr.getMap().getMonsters()) { // thanks BHB, IxianMace, Jefe for noticing several issues regarding mob statuses (such as freeze)
MapleMonster m = (MapleMonster) mo;
if (m.getSpawnEffect() == 0 || m.getHp() < m.getMaxHp()) { // avoid effect-spawning mobs
if (m.getController() == chr) {
c.announce(MaplePacketCreator.stopControllingMonster(m.getObjectId()));
m.sendDestroyData(c);
m.aggroRedirectController();
} else {
m.sendDestroyData(c);
}
m.aggroSwitchController(chr, false);
m.sendSpawnData(c);
m.aggroSwitchController(chr, false);
m.sendSpawnData(c);
}
}
}
}

View File

@@ -2,13 +2,17 @@ package net.server.channel.handlers;
import java.util.Map;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleQuestStatus;
import client.inventory.MapleInventory;
import client.inventory.MapleInventoryType;
import net.AbstractMaplePacketHandler;
import client.inventory.manipulator.MapleInventoryManipulator;
import server.MapleItemInformationProvider;
import server.MapleItemInformationProvider.QuestConsItem;
import server.quest.MapleQuest;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
/**
@@ -22,7 +26,7 @@ public class RaiseIncExpHandler extends AbstractMaplePacketHandler {
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
byte inventorytype = slea.readByte();//nItemIT
short slot = slea.readShort();//nSlotPosition
int itemid = slea.readInt();//nItemID
int itemid = slea.readInt();//nItemID
if (c.tryacquireClient()) {
try {
@@ -32,15 +36,22 @@ public class RaiseIncExpHandler extends AbstractMaplePacketHandler {
return;
}
int questid = consItem.questid;
int infoNumber = consItem.questid;
Map<Integer, Integer> consumables = consItem.items;
MapleCharacter chr = c.getPlayer();
MapleQuest quest = MapleQuest.getInstanceFromInfoNumber(infoNumber);
if (!chr.getQuest(quest).getStatus().equals(MapleQuestStatus.Status.STARTED)) {
c.announce(MaplePacketCreator.enableActions());
return;
}
int consId;
MapleInventory inv = c.getPlayer().getInventory(MapleInventoryType.getByType(inventorytype));
MapleInventory inv = chr.getInventory(MapleInventoryType.getByType(inventorytype));
inv.lockInventory();
try {
consId = inv.getItem(slot).getItemId();
if (!consumables.containsKey(consId) || !c.getPlayer().haveItem(consId)) {
if (!consumables.containsKey(consId) || !chr.haveItem(consId)) {
return;
}
@@ -48,9 +59,12 @@ public class RaiseIncExpHandler extends AbstractMaplePacketHandler {
} finally {
inv.unlockInventory();
}
int nextValue = Math.min(consumables.get(consId) + Integer.parseInt(c.getPlayer().getQuestInfo(questid)), consItem.exp * consItem.grade);
c.getPlayer().updateQuestInfo(questid, "" + nextValue);
int questid = quest.getId();
int nextValue = Math.min(consumables.get(consId) + c.getAbstractPlayerInteraction().getQuestProgressInt(questid, infoNumber), consItem.exp * consItem.grade);
c.getAbstractPlayerInteraction().setQuestProgress(questid, infoNumber, nextValue);
c.announce(MaplePacketCreator.enableActions());
} finally {
c.releaseClient();
}

View File

@@ -1,9 +1,11 @@
package net.server.channel.handlers;
import client.MapleCharacter.DelayedQuestUpdate;
import client.MapleCharacter;
import client.MapleClient;
import client.MapleQuestStatus;
import net.AbstractMaplePacketHandler;
import scripting.quest.QuestScriptManager;
import server.quest.MapleQuest;
import tools.data.input.SeekableLittleEndianAccessor;
@@ -15,19 +17,21 @@ public class RaiseUIStateHandler extends AbstractMaplePacketHandler {
@Override
public final void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
int questid = slea.readShort();
int infoNumber = slea.readShort();
if (c.tryacquireClient()) {
try {
MapleQuest quest = MapleQuest.getInstance(questid);
MapleQuestStatus mqs = c.getPlayer().getQuest(quest);
MapleCharacter chr = c.getPlayer();
MapleQuest quest = MapleQuest.getInstanceFromInfoNumber(infoNumber);
MapleQuestStatus mqs = chr.getQuest(quest);
QuestScriptManager.getInstance().raiseOpen(c, (short) infoNumber, mqs.getNpc());
if (mqs.getStatus() == MapleQuestStatus.Status.NOT_STARTED) {
quest.forceStart(c.getPlayer(), 22000);
c.getPlayer().updateQuestInfo(quest.getId(), "0");
quest.forceStart(chr, 22000);
c.getAbstractPlayerInteraction().setQuestProgress(quest.getId(), infoNumber, 0);
} else if (mqs.getStatus() == MapleQuestStatus.Status.STARTED) {
c.getPlayer().announceUpdateQuest(DelayedQuestUpdate.UPDATE, mqs, false);
} else {
//c.announce(MaplePacketCreator.updateQuestInfo(mqs.getQuestID(), 22000, "0"));
chr.announceUpdateQuest(DelayedQuestUpdate.UPDATE, mqs, mqs.getInfoNumber() > 0);
}
} finally {
c.releaseClient();

View File

@@ -35,22 +35,22 @@ public class MapleGuildCharacter {
private boolean online;
private String name;
public MapleGuildCharacter(MapleCharacter c) {
this.character = c;
this.name = c.getName();
this.level = c.getLevel();
this.id = c.getId();
this.channel = c.getClient().getChannel();
this.world = c.getWorld();
this.jobid = c.getJob().getId();
this.guildrank = c.getGuildRank();
this.guildid = c.getGuildId();
public MapleGuildCharacter(MapleCharacter chr) {
this.character = chr;
this.name = chr.getName();
this.level = chr.getLevel();
this.id = chr.getId();
this.channel = chr.getClient().getChannel();
this.world = chr.getWorld();
this.jobid = chr.getJob().getId();
this.guildrank = chr.getGuildRank();
this.guildid = chr.getGuildId();
this.online = true;
this.allianceRank = c.getAllianceRank();
this.allianceRank = chr.getAllianceRank();
}
public MapleGuildCharacter(MapleCharacter c, int _id, int _lv, String _name, int _channel, int _world, int _job, int _rank, int _gid, boolean _on, int _allianceRank) {
this.character = c;
public MapleGuildCharacter(MapleCharacter chr, int _id, int _lv, String _name, int _channel, int _world, int _job, int _rank, int _gid, boolean _on, int _allianceRank) {
this.character = chr;
this.level = _lv;
this.id = _id;
this.name = _name;

View File

@@ -24,6 +24,7 @@ package net.server.handlers.login;
import client.MapleClient;
import net.AbstractMaplePacketHandler;
import net.server.Server;
import net.server.channel.Channel;
import net.server.world.World;
import tools.MaplePacketCreator;
import tools.data.input.SeekableLittleEndianAccessor;
@@ -42,7 +43,8 @@ public final class CharlistRequestHandler extends AbstractMaplePacketHandler {
}
int channel = slea.readByte() + 1;
if(wserv.getChannel(channel) == null) {
Channel ch = wserv.getChannel(channel);
if(ch == null || !ch.isActive()) {
c.announce(MaplePacketCreator.getServerStatus(2));
return;
}

View File

@@ -212,7 +212,7 @@ public class World {
merchantSchedule = tman.register(new HiredMerchantTask(this), 10 * 60 * 1000, 10 * 60 * 1000);
timedMapObjectsSchedule = tman.register(new TimedMapObjectTask(this), 60 * 1000, 60 * 1000);
charactersSchedule = tman.register(new CharacterAutosaverTask(this), 60 * 60 * 1000, 60 * 60 * 1000);
marriagesSchedule = tman.register(new WeddingReservationTask(this), ServerConstants.WEDDING_RESERVATION_INTERVAL * 60 * 1000, ServerConstants.WEDDING_RESERVATION_INTERVAL * 60 * 1000);
marriagesSchedule = tman.register(new WeddingReservationTask(this), YamlConfig.config.server.WEDDING_RESERVATION_INTERVAL * 60 * 1000, YamlConfig.config.server.WEDDING_RESERVATION_INTERVAL * 60 * 1000);
mapOwnershipSchedule = tman.register(new MapOwnershipTask(this), 20 * 1000, 20 * 1000);
fishingSchedule = tman.register(new FishingTask(this), 10 * 1000, 10 * 1000);
partySearchSchedule = tman.register(new PartySearchTask(this), 10 * 1000, 10 * 1000);
@@ -730,14 +730,14 @@ public class World {
}
public void sendPacket(List<Integer> targetIds, final byte[] packet, int exception) {
MapleCharacter c;
MapleCharacter chr;
for (int i : targetIds) {
if (i == exception) {
continue;
}
c = getPlayerStorage().getCharacterById(i);
if (c != null) {
c.getClient().announce(packet);
chr = getPlayerStorage().getCharacterById(i);
if (chr != null) {
chr.getClient().announce(packet);
}
}
}