Public Repository for the Magicbane Shadowbane Emulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
11 KiB

// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.net.client;
import engine.Enum.DispatchChannel;
import engine.Enum.GameObjectType;
import engine.exception.MsgSendException;
import engine.gameManager.*;
import engine.job.JobScheduler;
import engine.jobs.RefreshGroupJob;
import engine.net.Dispatch;
import engine.net.DispatchMessage;
import engine.net.NetMsgHandler;
import engine.net.client.handlers.AbstractClientMsgHandler;
import engine.net.client.msg.*;
import engine.net.client.msg.chat.AbstractChatMsg;
import engine.objects.AbstractCharacter;
import engine.objects.Mob;
import engine.objects.NPC;
import engine.objects.PlayerCharacter;
import engine.server.MBServerStatics;
import engine.server.world.WorldServer;
import engine.session.Session;
import engine.util.StringUtils;
import org.pmw.tinylog.Logger;
/**
* @author:
* @summary: This class is the mainline router for application protocol
* messages received by the client.
*/
public class ClientMessagePump implements NetMsgHandler {
// Instance variable declaration
private final WorldServer server;
public ClientMessagePump(WorldServer server) {
super();
this.server = server;
}
// called when player clicks respawn button
private static void respawn(RespawnMsg msg, ClientConnection origin) throws MsgSendException {
PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(origin);
if (sourcePlayer == null)
return;
if (msg.getObjectType() != sourcePlayer.getObjectType().ordinal() || msg.getObjectID() != sourcePlayer.getObjectUUID()) {
Logger.error("Player " + sourcePlayer.getObjectUUID() + " respawning character of id " + msg.getObjectType() + ' '
+ msg.getObjectID());
return;
}
if (sourcePlayer.isAlive()) {
Logger.error("Player " + sourcePlayer.getObjectUUID() + " respawning while alive");
return;
}
// ResetAfterDeath player
sourcePlayer.respawnLock.writeLock().lock();
try {
sourcePlayer.respawn(true, false, true);
} catch (Exception e) {
Logger.error(e);
} finally {
sourcePlayer.respawnLock.writeLock().unlock();
}
// Echo ResetAfterDeath message back
msg.setPlayerHealth(sourcePlayer.getHealth());
// TODO calculate any experience loss before this point
msg.setPlayerExp(sourcePlayer.getExp() + sourcePlayer.getOverFlowEXP());
Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
MoveToPointMsg moveMsg = new MoveToPointMsg();
moveMsg.setPlayer(sourcePlayer);
moveMsg.setStartCoord(sourcePlayer.getLoc());
moveMsg.setEndCoord(sourcePlayer.getLoc());
moveMsg.setInBuilding(-1);
moveMsg.setInBuildingFloor(-1);
dispatch = Dispatch.borrow(sourcePlayer, moveMsg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
MovementManager.sendRWSSMsg(sourcePlayer);
// refresh the whole group with what just happened
JobScheduler.getInstance().scheduleJob(new RefreshGroupJob(sourcePlayer), MBServerStatics.LOAD_OBJECT_DELAY);
}
// called when player types /show
private static void show(ShowMsg msg, ClientConnection origin) throws MsgSendException {
PlayerCharacter pc = SessionManager.getPlayerCharacter(origin);
if (pc == null)
return;
int targetType = msg.getTargetType();
AbstractCharacter tar = null;
if (targetType == GameObjectType.PlayerCharacter.ordinal())
tar = PlayerCharacter.getFromCache(msg.getTargetID());
else if (targetType == GameObjectType.NPC.ordinal())
tar = NPC.getFromCache(msg.getTargetID());
else if (targetType == GameObjectType.Mob.ordinal())
tar = Mob.getFromCache(msg.getTargetID());
if (tar == null || !tar.isAlive() || !tar.isActive())
return;
msg.setUnknown01(pc.getLoc());
msg.setUnknown02(pc.getLoc());
msg.setRange01(pc.getRange());
msg.setUnknown03(tar.getLoc());
msg.setUnknown04(tar.getLoc());
msg.setRange01(tar.getRange());
Dispatch dispatch = Dispatch.borrow(pc, msg);
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
}
protected static void petAttack(PetAttackMsg msg, ClientConnection conn) throws MsgSendException {
PlayerCharacter pc = SessionManager.getPlayerCharacter(conn);
if (pc == null)
return;
Mob pet = pc.getPet();
if (pet == null)
return;
if (!pet.isAlive())
return;
if ((pc.inSafeZone())
&& (msg.getTargetType() == GameObjectType.PlayerCharacter.ordinal()))
return;
//CombatManager.setAttackTarget(msg, conn);
if (msg.getTargetType() == GameObjectType.Building.ordinal()) {
conn.getPlayerCharacter().getPet().setCombatTarget(PlayerCharacter.getPlayerCharacter(msg.getTargetID()));
}
switch (msg.getTargetType()) {
case 53: //player character
conn.getPlayerCharacter().getPet().setCombatTarget(PlayerCharacter.getPlayerCharacter(msg.getTargetID()));
break;
case 37://mob
conn.getPlayerCharacter().getPet().setCombatTarget(Mob.getMob(msg.getTargetID()));
break;
case 8://mob
conn.getPlayerCharacter().getPet().setCombatTarget(BuildingManager.getBuilding(msg.getTargetID()));
break;
}
if (pet.getCombatTarget() == null)
return;
}
//Handle RepairObject Window and RepairObject Requests
@Override
public boolean handleClientMsg(ClientNetMsg msg) {
if (msg == null) {
Logger.error("handleClientMsg", "Recieved null msg. Returning.");
return false;
}
ClientConnection origin;
Protocol protocolMsg = Protocol.NONE;
Session s;
try {
// Try registered opcodes first as we take a hatchet to this GodObject
AbstractClientMsgHandler msgHandler = msg.getProtocolMsg().handler;
if (msgHandler != null)
return msgHandler.handleNetMsg(msg);
// Any remaining opcodes fall through and are routed
// through this ungodly switch of doom.
origin = (ClientConnection) msg.getOrigin();
s = SessionManager.getSession(origin);
protocolMsg = msg.getProtocolMsg();
switch (protocolMsg) {
/*
* Chat
*/
// Simplify by fall through. Route in ChatManager
case CHATSAY:
case CHATSHOUT:
case CHATTELL:
case CHATGUILD:
case CHATGROUP:
case CHATPVP:
case CHATIC:
case CHATCITY:
case CHATINFO:
case SYSTEMBROADCASTCHANNEL:
case CHATCSR:
case SYSTEMCHANNEL:
case GLOBALCHANNELMESSAGE:
case LEADERCHANNELMESSAGE:
ChatManager.handleChatMsg(s, (AbstractChatMsg) msg);
break;
case READYTOENTER:
break;
case OPENVAULT:
break;
case RESETAFTERDEATH:
respawn((RespawnMsg) msg, origin);
break;
case SHOWCOMBATINFO:
show((ShowMsg) msg, origin);
break;
case REQUESTTOTRADE:
TradeManager.tradeRequest((TradeRequestMsg) msg, origin);
break;
case REQUESTTRADEOK:
TradeManager.acceptTradeRequest((AcceptTradeRequestMsg) msg, origin);
break;
case REQUESTTRADECANCEL:
TradeManager.rejectTradeRequest((RejectTradeRequestMsg) msg, origin);
break;
case TRADEADDOBJECT:
TradeManager.addItemToTradeWindow((AddItemToTradeWindowMsg) msg, origin);
break;
case TRADEADDGOLD:
TradeManager.addGoldToTradeWindow((AddGoldToTradeWindowMsg) msg, origin);
break;
case TRADECONFIRM:
TradeManager.commitToTrade((CommitToTradeMsg) msg, origin);
break;
case TRADEUNCONFIRM:
TradeManager.uncommitToTrade((UncommitToTradeMsg) msg, origin);
break;
case TRADECLOSE:
TradeManager.closeTradeWindow((CloseTradeWindowMsg) msg, origin);
break;
case ARCREQUESTTRADEBUSY:
TradeManager.invalidTradeRequest((InvalidTradeRequestMsg) msg);
break;
case TRAINERLIST:
WorldServer.trainerInfo((TrainerInfoMsg) msg, origin);
break;
case ARCUNTRAINLIST:
WorldServer.refinerScreen((RefinerScreenMsg) msg, origin);
break;
case ARCUNTRAINABILITY:
RefineMsg.refine((RefineMsg) msg, origin);
break;
case POWERTARGNAME:
PowersManager.summon((SendSummonsRequestMsg) msg, origin);
break;
case ARCSUMMON:
PowersManager.recvSummon((RecvSummonsRequestMsg) msg, origin);
break;
case ARCTRACKINGLIST:
PowersManager.trackWindow((TrackWindowMsg) msg, origin);
break;
case STUCK:
MovementManager.stuck(origin);
break;
case ARCPETATTACK:
petAttack((PetAttackMsg) msg, origin);
break;
case CHANNELMUTE:
break;
case KEEPALIVESERVERCLIENT:
break;
case UNKNOWN:
break;
case CONFIRMPROMOTE:
break;
default:
String ocHex = StringUtils.toHexString(protocolMsg.opcode);
Logger.error("Cannot handle Opcode: " + ocHex + " " + protocolMsg.name());
return false;
}
} catch (Exception e) {
Logger.error("handler for " + protocolMsg + " failed: " + e);
return false;
}
return true;
}
}