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:
@@ -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[]) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user