Initial Repository Push
This commit is contained in:
@@ -0,0 +1,425 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.job.JobManager;
|
||||
import engine.net.client.Protocol;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public abstract class AbstractConnection implements
|
||||
NetMsgHandler {
|
||||
|
||||
private static final String error01 = "A byte buffer is being free()ed that is not of the size stored in ByteBufferPool. Size: %1%";
|
||||
private static final String error02 = "(IP=%1%): Socket has reached the maximum outbound buffer length of %2%. Moving on while we wait for data to be sent.";
|
||||
|
||||
protected final SocketChannel sockChan;
|
||||
protected final AbstractConnectionManager connMan;
|
||||
protected final NetMsgFactory factory;
|
||||
|
||||
protected long lastMsgTime = System.currentTimeMillis();
|
||||
protected long lastKeepAliveTime = System.currentTimeMillis();
|
||||
protected long lastOpcode = -1;
|
||||
|
||||
protected ConcurrentLinkedQueue<ByteBuffer> outbox = new ConcurrentLinkedQueue<>();
|
||||
protected ByteBuffer outBuf = null;
|
||||
|
||||
protected final AtomicBoolean execTask = new AtomicBoolean(false);
|
||||
|
||||
protected ConcurrentHashMap<Long, Byte> cacheList;
|
||||
|
||||
protected final ReentrantLock writeLock = new ReentrantLock();
|
||||
protected final ReentrantLock readLock = new ReentrantLock();
|
||||
protected long nextWriteTime = 0L;
|
||||
protected Protocol lastProtocol = Protocol.NONE;
|
||||
protected static final long SOCKET_FULL_WRITE_DELAY = 50L; //wait one second to write on full socket
|
||||
|
||||
//Opcode tracking
|
||||
|
||||
private static final int OPCODEHASH = 1016; //Opcodes are unique modulo this number as of 11/21/10
|
||||
|
||||
public AbstractConnection(AbstractConnectionManager connMan,
|
||||
SocketChannel sockChan, boolean clientMode) {
|
||||
this.connMan = connMan;
|
||||
this.sockChan = sockChan;
|
||||
this.factory = new NetMsgFactory(this);
|
||||
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
try {
|
||||
this.sockChan.close();
|
||||
} catch (IOException e) {
|
||||
Logger.error(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes AbstractNetMsg <i>msg</i> into a ByteBuffer, then queues that
|
||||
* ByteBuffer for sending on this AbstractConnection's SocketChannel.
|
||||
*
|
||||
* @param msg
|
||||
* - AbstractNetMsg to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
public final boolean sendMsg(AbstractNetMsg msg) {
|
||||
// Logger.info("Send: " + msg.getSimpleClassName());
|
||||
try {
|
||||
return this._sendMsg(msg);
|
||||
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes AbstractNetMsg <i>msg</i> into a ByteBuffer, then queues that
|
||||
* ByteBuffer for sending on this AbstractConnection's SocketChannel. This
|
||||
* internal function is <b>required</b> to be overridden by subclasses.
|
||||
*
|
||||
* @param msg
|
||||
* - AbstractNetMsg to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
protected abstract boolean _sendMsg(AbstractNetMsg msg);
|
||||
|
||||
/**
|
||||
* Queues ByteBuffer <i>bb</i> for sending on this AbstractConnection's
|
||||
* SocketChannel.
|
||||
*
|
||||
* @param bb
|
||||
* - ByteBuffer to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
public final boolean sendBB(ByteBuffer bb) {
|
||||
|
||||
if (bb == null)
|
||||
return false;
|
||||
try {
|
||||
return this._sendBB(bb);
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues ByteBuffer <i>bb</i> for sending on this AbstractConnection's
|
||||
* SocketChannel. This internal function is designed to be overrideable by
|
||||
* subclasses if needed.
|
||||
*
|
||||
* @param bb
|
||||
* - ByteBuffer to be sent.
|
||||
* @return boolean status if queue is successful or not. On false return,
|
||||
* the field <i>lastError</i> will be set.
|
||||
*/
|
||||
protected boolean _sendBB(ByteBuffer bb) {
|
||||
this.outbox.add(bb);
|
||||
this.connMan.sendStart(this.sockChan);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move data off the socketChannel's buffer and into the Connection's
|
||||
* internal NetMsgFactory.
|
||||
*/
|
||||
// FIXME the int return value on this means nothing! Clean it up!
|
||||
protected int read() {
|
||||
|
||||
if (readLock.tryLock())
|
||||
try {
|
||||
|
||||
if (this.sockChan.isOpen() == false) {
|
||||
Logger.info("Sock channel closed. Disconnecting " + this.getRemoteAddressAndPortAsString());
|
||||
this.disconnect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get socket buffer sized buffer from multipool
|
||||
ByteBuffer bb = Network.byteBufferPool.getBuffer(16);
|
||||
|
||||
int totalBytesRead = 0;
|
||||
int lastRead;
|
||||
do {
|
||||
try {
|
||||
bb.clear();
|
||||
lastRead = this.sockChan.read(bb);
|
||||
|
||||
// On EOF on the SocketChannel, disconnect.
|
||||
if (lastRead <= -1) {
|
||||
Logger.info(" EOF on Socket Channel " + this.getRemoteAddressAndPortAsString());
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastRead == 0)
|
||||
continue;
|
||||
|
||||
synchronized (this.factory) {
|
||||
this.factory.addData(bb);
|
||||
}
|
||||
this.checkInternalFactory();
|
||||
|
||||
totalBytesRead += lastRead;
|
||||
|
||||
} catch (NotYetConnectedException e) {
|
||||
Logger.error(e.toString());
|
||||
break;
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
Logger.error(e.toString());
|
||||
this.disconnect();
|
||||
break;
|
||||
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith(
|
||||
"An existing connection was forcibly closed"))
|
||||
Logger.error(e.toString());
|
||||
this.disconnect();
|
||||
break;
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.toString());
|
||||
break;
|
||||
}
|
||||
} while (lastRead > 0);
|
||||
|
||||
// put buffer back into multipool
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
|
||||
this.checkInternalFactory();
|
||||
return totalBytesRead;
|
||||
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a read lock! Skipping.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move data off the Connection's buffer and into the SocketChannel's
|
||||
* Buffer.
|
||||
*/
|
||||
protected boolean writeAll() {
|
||||
|
||||
//intentional delay if socket is full. Give the socket a chance to clear out.
|
||||
if (System.currentTimeMillis() < this.nextWriteTime)
|
||||
return false;
|
||||
|
||||
if (writeLock.tryLock())
|
||||
try {
|
||||
String s = "";
|
||||
int written = 0;
|
||||
|
||||
boolean allSentOK = true, bufferDoubled = false;
|
||||
|
||||
while (this.outbox.peek() != null) {
|
||||
ByteBuffer bb = this.outbox.peek();
|
||||
|
||||
int toSend = bb.position();
|
||||
|
||||
try {
|
||||
bb.flip();
|
||||
written = this.sockChan.write(bb);
|
||||
|
||||
// Logger.debug("Using a BB with cap of: " + bb.capacity()
|
||||
// + ". toSend: " + toSend + ", written: " + written);
|
||||
if (written != toSend)
|
||||
bb.compact(); // Clean up in case not all gets sent
|
||||
|
||||
if (toSend == written) {
|
||||
// Actually remove it from the queue
|
||||
this.outbox.poll();
|
||||
|
||||
// Pool it
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
continue;
|
||||
|
||||
} else
|
||||
if (written == 0) {
|
||||
//Socket full, let's delay the next write on socket.
|
||||
this.nextWriteTime = System.currentTimeMillis() + AbstractConnection.SOCKET_FULL_WRITE_DELAY;
|
||||
|
||||
int currentBufferSize = this.sockChan.socket()
|
||||
.getSendBufferSize();
|
||||
|
||||
if (!bufferDoubled && currentBufferSize <= Network.INITIAL_SOCKET_BUFFER_SIZE) {
|
||||
this.doubleSocketSendBufferSize();
|
||||
bufferDoubled = true;
|
||||
} else {
|
||||
|
||||
// s = error02;
|
||||
// s = s.replaceAll("%1%", this
|
||||
// .getRemoteAddressAndPortAsString() + ":" +
|
||||
// this.printLastOpcodes());
|
||||
// s = s.replaceAll("%2%", currentBufferSize + "");
|
||||
// this.warn(s);
|
||||
|
||||
allSentOK = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
// Catches AsynchronousCloseException,
|
||||
// and ClosedByInterruptException
|
||||
Logger.error(e);
|
||||
break;
|
||||
|
||||
} catch (Exception e) {
|
||||
// Catches NotYetConnectedException
|
||||
// and IOException
|
||||
Logger.error(e);
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return allSentOK;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a write lock! Skipping.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean doubleSocketSendBufferSize() {
|
||||
String s;
|
||||
try {
|
||||
int currentSize = this.sockChan.socket().getSendBufferSize();
|
||||
int newSize = currentSize << 1;
|
||||
|
||||
this.sockChan.socket().setSendBufferSize(newSize);
|
||||
|
||||
// s = "(IP=" + this.getRemoteAddressAndPortAsString() + "): ";
|
||||
// s += this.printLastOpcodes();
|
||||
// s += "Socket has reached the maximum outbound buffer length of ";
|
||||
// s += currentSize + ". Attempting to double the outbound buffer size.";
|
||||
//
|
||||
// this.warn(s);
|
||||
return true;
|
||||
} catch (SocketException e) {
|
||||
Logger.error( e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return this.sockChan.isConnected();
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return this.sockChan.isOpen();
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters n Setters
|
||||
*/
|
||||
public SocketChannel getSocketChannel() {
|
||||
return this.sockChan;
|
||||
}
|
||||
|
||||
public final void checkInternalFactory() {
|
||||
CheckNetMsgFactoryJob j = new CheckNetMsgFactoryJob(this);
|
||||
JobManager.getInstance().submitJob(j);
|
||||
}
|
||||
|
||||
public NetMsgFactory getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
public String getRemoteAddressAndPortAsString() {
|
||||
String out = "";
|
||||
|
||||
if (this.sockChan == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket() == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket().getRemoteSocketAddress() == null)
|
||||
out += "NotConnected";
|
||||
else
|
||||
out += this.sockChan.socket().getRemoteSocketAddress().toString();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getLocalAddressAndPortAsString() {
|
||||
String out = "";
|
||||
|
||||
if (this.sockChan == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket() == null)
|
||||
out += "NotConnected";
|
||||
else if (this.sockChan.socket().getRemoteSocketAddress() == null)
|
||||
out += "NotConnected";
|
||||
else {
|
||||
out += this.sockChan.socket().getLocalSocketAddress().toString();
|
||||
out += ":";
|
||||
out += this.sockChan.socket().getLocalPort();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the Connection a chance to act on a msg prior to sending it to the
|
||||
* provided NetMsgHandler
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public abstract boolean handleClientMsg(ClientNetMsg msg);
|
||||
|
||||
protected long getLastMsgTime() {
|
||||
return this.lastMsgTime;
|
||||
}
|
||||
|
||||
protected void setLastMsgTime() {
|
||||
// TODO Consider making this a static to latest system time
|
||||
this.lastMsgTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected long getLastKeepAliveTime() {
|
||||
return this.lastKeepAliveTime;
|
||||
}
|
||||
|
||||
protected void setLastKeepAliveTime() {
|
||||
this.lastKeepAliveTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public long getLastOpcode() {
|
||||
return lastOpcode;
|
||||
}
|
||||
|
||||
public void setLastOpcode(long lastOpcode) {
|
||||
this.lastOpcode = lastOpcode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,708 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.core.ControlledRunnable;
|
||||
import engine.job.AbstractJob;
|
||||
import engine.job.JobManager;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public abstract class AbstractConnectionManager extends ControlledRunnable {
|
||||
|
||||
private final Selector selector;
|
||||
private final ServerSocketChannel listenChannel;
|
||||
private final ConcurrentLinkedQueue<ChangeRequest> chngReqs = new ConcurrentLinkedQueue<>();
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
public AbstractConnectionManager(String nodeName, InetAddress hostAddress,
|
||||
int port) throws IOException {
|
||||
super(nodeName);
|
||||
|
||||
this.selector = SelectorProvider.provider().openSelector();
|
||||
|
||||
// Create a new non-blocking Server channel
|
||||
this.listenChannel = ServerSocketChannel.open();
|
||||
this.listenChannel.configureBlocking(false);
|
||||
|
||||
// Bind
|
||||
InetSocketAddress isa = new InetSocketAddress(hostAddress, port);
|
||||
this.listenChannel.socket().bind(isa);
|
||||
|
||||
Logger.info(this.getLocalNodeName() + " Configured to listen: "
|
||||
+ isa.getAddress().toString() + ':' + port);
|
||||
|
||||
// register an interest in Accepting new connections.
|
||||
SelectionKey sk = this.listenChannel.register(this.selector, SelectionKey.OP_ACCEPT);
|
||||
sk.attach(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* ControlledRunnable implementations
|
||||
*/
|
||||
@Override
|
||||
protected void _startup() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void _shutdown() {
|
||||
this.selector.wakeup();
|
||||
this.disconnectAll();
|
||||
this.selector.wakeup();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _preRun() {
|
||||
this.runStatus = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _Run() {
|
||||
while (this.runCmd) {
|
||||
try {
|
||||
this.runLoopHook();
|
||||
|
||||
this.processChangeRequests();
|
||||
this.auditSocketChannelToConnectionMap();
|
||||
this.selector.select(250L);
|
||||
this.processNewEvents();
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(e.toString());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _postRun() {
|
||||
|
||||
this.runStatus = false;
|
||||
|
||||
this.disconnectAll();
|
||||
|
||||
try {
|
||||
this.selector.close();
|
||||
} catch (IOException e) {
|
||||
Logger.error( e.toString());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for subclasses to use.
|
||||
*
|
||||
*/
|
||||
protected void runLoopHook() {
|
||||
}
|
||||
|
||||
/*
|
||||
* Accept / New Connection FNs
|
||||
*/
|
||||
private AbstractConnection acceptNewConnection(final SelectionKey key)
|
||||
throws IOException {
|
||||
|
||||
this.preAcceptNewConnectionHook(key);
|
||||
|
||||
// Cancel incoming connections if server isn't set to listen
|
||||
if (this.listenChannel == null || this.listenChannel.isOpen() == false) {
|
||||
key.cancel();
|
||||
return null;
|
||||
}
|
||||
|
||||
// For an accept to be pending, the key contains a reference to the
|
||||
// ServerSocketChannel
|
||||
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
|
||||
|
||||
// Get SocketChannel
|
||||
SocketChannel sockChan = ssc.accept();
|
||||
sockChan.configureBlocking(false);
|
||||
|
||||
//Configure the Socket
|
||||
Socket socket = sockChan.socket();
|
||||
socket.setSendBufferSize(Network.INITIAL_SOCKET_BUFFER_SIZE);
|
||||
socket.setReceiveBufferSize(Network.INITIAL_SOCKET_BUFFER_SIZE);
|
||||
socket.setTcpNoDelay(MBServerStatics.TCP_NO_DELAY_DEFAULT);
|
||||
|
||||
//Register with the selector
|
||||
SelectionKey sk = sockChan.register(this.selector, SelectionKey.OP_READ);
|
||||
if (sk == null) {
|
||||
Logger.error("FIX ME! NULL SELECTION KEY!");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Initialize Connection
|
||||
AbstractConnection ac = this.getNewIncomingConnection(sockChan);
|
||||
sk.attach(ac);
|
||||
|
||||
this.postAcceptNewConnectionHook(ac);
|
||||
return ac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for subclasses to use.
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
protected void preAcceptNewConnectionHook(SelectionKey key) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for subclasses to use.
|
||||
*
|
||||
* @param ac
|
||||
*/
|
||||
protected void postAcceptNewConnectionHook(AbstractConnection ac) {
|
||||
}
|
||||
|
||||
protected abstract AbstractConnection getNewIncomingConnection(SocketChannel sockChan);
|
||||
|
||||
protected abstract AbstractConnection getNewOutgoingConnection(SocketChannel sockChan);
|
||||
|
||||
/*
|
||||
* Disconnect / Destroy Connection FNs
|
||||
*/
|
||||
protected boolean disconnect(final SelectionKey key) {
|
||||
|
||||
this.disconnect((AbstractConnection) key.attachment());
|
||||
|
||||
key.attach(null);
|
||||
key.cancel();
|
||||
return key.isValid();
|
||||
}
|
||||
|
||||
protected boolean disconnect(final AbstractConnection c) {
|
||||
if (c == null)
|
||||
return false;
|
||||
|
||||
c.disconnect();
|
||||
|
||||
return c.getSocketChannel().isConnected();
|
||||
}
|
||||
|
||||
protected void disconnectAll() {
|
||||
synchronized (this.selector.keys()) {
|
||||
for (SelectionKey sk : this.selector.keys()) {
|
||||
if (sk.channel() instanceof SocketChannel)
|
||||
disconnect(sk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Data IO
|
||||
*/
|
||||
|
||||
/*
|
||||
* WRITE SEQUENCE
|
||||
*/
|
||||
/**
|
||||
* Submits a request to set this Connection to WRITE mode.
|
||||
*
|
||||
*/
|
||||
protected void sendStart(final SocketChannel sockChan) {
|
||||
synchronized (this.chngReqs) {
|
||||
// Indicate we want the interest ops set changed
|
||||
this.chngReqs.add(new ChangeRequest(sockChan, ChangeType.CHANGEOPS, SelectionKey.OP_WRITE));
|
||||
}
|
||||
|
||||
this.selector.wakeup();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key
|
||||
* @return Boolean indication emit success.
|
||||
*/
|
||||
protected boolean sendFinish(final SelectionKey key) {
|
||||
SocketChannel sockChan = (SocketChannel) key.channel();
|
||||
|
||||
// Check to see if the SocketChannel the selector offered up
|
||||
// is null.
|
||||
if (sockChan == null) {
|
||||
Logger.error(": null sockChannel.");
|
||||
this.disconnect(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractConnection c = (AbstractConnection) key.attachment();
|
||||
|
||||
if (c == null) {
|
||||
Logger.error(": null Connection.");
|
||||
this.disconnect(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
// long startTime = System.currentTimeMillis();
|
||||
boolean allSent = c.writeAll();
|
||||
|
||||
// if ((System.currentTimeMillis() - startTime) > 20)
|
||||
// this.logDirectWARNING(c.getRemoteAddressAndPortAsString() + " took " + (System.currentTimeMillis() - startTime) + "ms to handle!");
|
||||
|
||||
// If all was written, switch back to Read Mode.
|
||||
if (allSent || !c.isConnected()) {
|
||||
|
||||
// Indicate we want the interest ops set changed
|
||||
ChangeRequest chReq = new ChangeRequest(c.getSocketChannel(), ChangeType.CHANGEOPS, SelectionKey.OP_READ);
|
||||
synchronized (this.chngReqs) {
|
||||
this.chngReqs.add(chReq);
|
||||
}
|
||||
|
||||
this.selector.wakeup();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* READ SEQUENCE
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @param key
|
||||
* @return Boolean indication of success.
|
||||
*/
|
||||
private boolean receive(final SelectionKey key) {
|
||||
SocketChannel sockChan = (SocketChannel) key.channel();
|
||||
|
||||
// Check to see if the SocketChannel the selector offered up
|
||||
// is null.
|
||||
if (sockChan == null) {
|
||||
Logger.error("null sockChannel.");
|
||||
this.disconnect(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractConnection c = (AbstractConnection) key.attachment();
|
||||
|
||||
if (c == null) {
|
||||
Logger.error("null Connection.");
|
||||
this.disconnect(key);
|
||||
return false;
|
||||
}
|
||||
|
||||
c.read();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Main Loop And Loop Controls
|
||||
*/
|
||||
private void processChangeRequests() {
|
||||
SelectionKey selKey = null;
|
||||
ChangeRequest sccr = null;
|
||||
ChangeType change = null;
|
||||
SocketChannel sockChan = null;
|
||||
|
||||
synchronized (this.chngReqs) {
|
||||
Iterator<ChangeRequest> it = this.chngReqs.iterator();
|
||||
while (it.hasNext()) {
|
||||
sccr = it.next();
|
||||
|
||||
if (sccr == null) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
change = sccr.getChangeType();
|
||||
sockChan = sccr.getSocketChannel();
|
||||
|
||||
switch (change) {
|
||||
case CHANGEOPS:
|
||||
selKey = sockChan.keyFor(this.selector);
|
||||
|
||||
if (selKey == null || selKey.isValid() == false)
|
||||
continue;
|
||||
|
||||
selKey.interestOps(sccr.getOps());
|
||||
break;
|
||||
|
||||
case REGISTER:
|
||||
try {
|
||||
sockChan.register(this.selector, sccr.getOps());
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
// TODO Should a closed channel be logged or just
|
||||
// cleaned up?
|
||||
// Logger.error(this.getLocalNodeName(), e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.chngReqs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void processNewEvents() {
|
||||
SelectionKey thisKey = null;
|
||||
Iterator<SelectionKey> selectedKeys = null;
|
||||
JobManager jm = JobManager.getInstance();
|
||||
|
||||
selectedKeys = this.selector.selectedKeys().iterator();
|
||||
|
||||
if (selectedKeys.hasNext() == false)
|
||||
return;
|
||||
|
||||
while (selectedKeys.hasNext()) {
|
||||
thisKey = selectedKeys.next();
|
||||
|
||||
//To shake out any issues
|
||||
if (thisKey.attachment() == null)
|
||||
Logger.error("Found null attachment! PANIC!");
|
||||
|
||||
if (thisKey.attachment() instanceof AbstractConnection)
|
||||
if (((AbstractConnection) thisKey.attachment()).execTask.get() == true)
|
||||
continue;
|
||||
|
||||
selectedKeys.remove();
|
||||
|
||||
try {
|
||||
if (thisKey.isValid() == false)
|
||||
break; // Changed from continue
|
||||
else if (thisKey.isAcceptable())
|
||||
this.acceptNewConnection(thisKey);
|
||||
else if (thisKey.isReadable())
|
||||
jm.submitJob(new ReadOperationHander(thisKey));
|
||||
else if (thisKey.isWritable())
|
||||
jm.submitJob(new WriteOperationHander(thisKey));
|
||||
else if (thisKey.isConnectable())
|
||||
this.finishConnectingTo(thisKey);
|
||||
else
|
||||
Logger.error("Unhandled keystate: " + thisKey.toString());
|
||||
} catch (CancelledKeyException cke) {
|
||||
Logger.error(this.getLocalNodeName(), cke);
|
||||
this.disconnect(thisKey);
|
||||
|
||||
} catch (IOException e) {
|
||||
Logger.error(this.getLocalNodeName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void connectTo(String host, int port) {
|
||||
try {
|
||||
this.connectTo(InetAddress.getByName(host), port);
|
||||
} catch (UnknownHostException e) {
|
||||
Logger.error(this.getLocalNodeName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void connectTo(InetAddress host, int port) {
|
||||
try {
|
||||
this.startConnectingTo(host, port);
|
||||
this.selector.wakeup();
|
||||
} catch (IOException e) {
|
||||
Logger.error(this.getLocalNodeName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected final void startConnectingTo(InetAddress host, int port)
|
||||
throws IOException {
|
||||
// Create a non-blocking socket channel
|
||||
SocketChannel sockChan = SocketChannel.open();
|
||||
sockChan.configureBlocking(false);
|
||||
sockChan.socket().setSendBufferSize(Network.INITIAL_SOCKET_BUFFER_SIZE);
|
||||
sockChan.socket().setReceiveBufferSize(Network.INITIAL_SOCKET_BUFFER_SIZE);
|
||||
|
||||
// Make a new Connection object
|
||||
this.getNewOutgoingConnection(sockChan);
|
||||
|
||||
// Kick off connection establishment
|
||||
sockChan.connect(new InetSocketAddress(host, port));
|
||||
|
||||
synchronized (this.chngReqs) {
|
||||
this.chngReqs.add(new ChangeRequest(sockChan, ChangeType.REGISTER, SelectionKey.OP_CONNECT));
|
||||
}
|
||||
|
||||
this.selector.wakeup();
|
||||
}
|
||||
|
||||
private void finishConnectingTo(SelectionKey key) throws IOException {
|
||||
this.preFinishConnectingToHook(key);
|
||||
|
||||
// Get sockChan
|
||||
SocketChannel sockChan = (SocketChannel) key.channel();
|
||||
|
||||
// Get AbstractConnection
|
||||
AbstractConnection ac = (AbstractConnection) key.attachment();
|
||||
|
||||
if (sockChan == null) {
|
||||
Logger.error(this.getLocalNodeName(), "null socketChannel");
|
||||
this.disconnect(key);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ac == null) {
|
||||
Logger.error(this.getLocalNodeName(), "null AbstractConnection");
|
||||
this.disconnect(key);
|
||||
return;
|
||||
}
|
||||
|
||||
// Finish the connection. If the connection operation failed
|
||||
// this will raise an IOException.
|
||||
try {
|
||||
sockChan.finishConnect();
|
||||
} catch (IOException e) {
|
||||
if (e.getMessage().startsWith("Connection refused:")
|
||||
|| e.getMessage().startsWith(
|
||||
"An existing connection was forcibly closed")) {
|
||||
// eat this type of IOException
|
||||
} else
|
||||
Logger.error(this.getLocalNodeName(), e);
|
||||
|
||||
// Cancel the channel's registration with our selector
|
||||
key.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
Socket socket = sockChan.socket();
|
||||
Logger.debug("Connected to: "
|
||||
+ socket.getInetAddress() + ':'
|
||||
+ socket.getPort());
|
||||
|
||||
sockChan.configureBlocking(false);
|
||||
sockChan.register(this.selector, SelectionKey.OP_READ);
|
||||
|
||||
this.postFinishConnectingToHook(ac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for subclasses to use.
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
protected void preFinishConnectingToHook(SelectionKey key) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook for subclasses to use.
|
||||
*
|
||||
* @param ac
|
||||
*/
|
||||
protected void postFinishConnectingToHook(AbstractConnection ac) {
|
||||
}
|
||||
|
||||
public final String getLocalNodeName() {
|
||||
return this.getThreadName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the mapping that contains the key 'sockChan'
|
||||
*
|
||||
* @param sockChan
|
||||
*/
|
||||
private long lastAuditTime = 0;
|
||||
|
||||
protected int auditSocketChannelToConnectionMap() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
int numberOfItemsToProcess = 0;
|
||||
|
||||
if (lastAuditTime + MBServerStatics.TIMEOUT_CHECKS_TIMER_MS > startTime)
|
||||
return -1;
|
||||
|
||||
synchronized (this.selector.keys()) {
|
||||
for (SelectionKey sk : this.selector.keys()) {
|
||||
if (!(sk.channel() instanceof SocketChannel))
|
||||
continue;
|
||||
|
||||
SocketChannel sockChan = (SocketChannel) sk.channel();
|
||||
AbstractConnection conn = (AbstractConnection) sk.attachment();
|
||||
|
||||
if (sockChan == null)
|
||||
continue;
|
||||
|
||||
if (!sockChan.isOpen()) {
|
||||
numberOfItemsToProcess++;
|
||||
Logger.info("sockChan closed. Disconnecting..");
|
||||
disconnect(sk);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (conn == null) {
|
||||
numberOfItemsToProcess++;
|
||||
Logger.info("Connection is null, Disconnecting.");
|
||||
disconnect(sk);
|
||||
continue;
|
||||
}
|
||||
|
||||
//removed keep alive timeout. Believe failmu used this for disconnecting players on force quit, but a closed socket will already disconnect.
|
||||
// if (conn.getLastKeepAliveTime() + MBServerStatics.KEEPALIVE_TIMEOUT_MS < startTime) {
|
||||
// numberOfItemsToProcess++;
|
||||
// Logger.info("Keep alive Disconnecting " + conn.getRemoteAddressAndPortAsString());
|
||||
// conn.disconnect();
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (conn.getLastMsgTime() + MBServerStatics.AFK_TIMEOUT_MS < startTime) {
|
||||
numberOfItemsToProcess++;
|
||||
Logger.info("AFK TIMEOUT Disconnecting " + conn.getRemoteAddressAndPortAsString());
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numberOfItemsToProcess != 0)
|
||||
Logger.info( "Cleaned "
|
||||
+ numberOfItemsToProcess
|
||||
+ " dead connections in "
|
||||
+ (System.currentTimeMillis() - startTime)
|
||||
+ " millis.");
|
||||
|
||||
lastAuditTime = System.currentTimeMillis();
|
||||
return numberOfItemsToProcess;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
protected static enum ChangeType {
|
||||
|
||||
REGISTER, CHANGEOPS
|
||||
}
|
||||
|
||||
private class ChangeRequest {
|
||||
|
||||
private final SocketChannel sockChan;
|
||||
private final ChangeType changeType;
|
||||
private final Integer ops;
|
||||
|
||||
public ChangeRequest(SocketChannel sockChan, ChangeType changeType,
|
||||
int ops) {
|
||||
this.sockChan = sockChan;
|
||||
this.changeType = changeType;
|
||||
this.ops = ops;
|
||||
}
|
||||
|
||||
public SocketChannel getSocketChannel() {
|
||||
synchronized (this.sockChan) {
|
||||
return this.sockChan;
|
||||
}
|
||||
}
|
||||
|
||||
public ChangeType getChangeType() {
|
||||
synchronized (this.changeType) {
|
||||
return this.changeType;
|
||||
}
|
||||
}
|
||||
|
||||
public int getOps() {
|
||||
synchronized (this.ops) {
|
||||
return this.ops;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getConnectionSize() {
|
||||
if (this.selector == null)
|
||||
return -1;
|
||||
if (this.selector.keys() == null)
|
||||
return -1;
|
||||
return this.selector.keys().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port on which this socket is listening.
|
||||
*
|
||||
* @return the port number to which this socket is listening or -1 if the
|
||||
* socket is not bound yet.
|
||||
*
|
||||
*/
|
||||
public int getListeningPort() {
|
||||
if (this.listenChannel == null)
|
||||
return -1;
|
||||
if (this.listenChannel.socket() == null)
|
||||
return -1;
|
||||
return this.listenChannel.socket().getLocalPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address of the endpoint this socket is bound to, or null if
|
||||
* it is not bound yet.
|
||||
*
|
||||
* @return a SocketAddress representing the local endpoint of this socket,
|
||||
* or null if it is not bound yet.
|
||||
*/
|
||||
public SocketAddress getListeningAddress() {
|
||||
if (this.listenChannel == null)
|
||||
return null;
|
||||
if (this.listenChannel.socket() == null)
|
||||
return null;
|
||||
return this.listenChannel.socket().getLocalSocketAddress();
|
||||
}
|
||||
|
||||
private class ReadOperationHander extends AbstractJob {
|
||||
|
||||
private final SelectionKey sk;
|
||||
private final AbstractConnection ac;
|
||||
private final boolean runStatus;
|
||||
|
||||
public ReadOperationHander(final SelectionKey sk) {
|
||||
this.sk = sk;
|
||||
|
||||
if (sk.attachment() instanceof AbstractConnection) {
|
||||
this.ac = (AbstractConnection) sk.attachment();
|
||||
this.runStatus = this.ac.execTask.compareAndSet(false, true);
|
||||
} else {
|
||||
this.ac = null;
|
||||
this.runStatus = false;
|
||||
Logger.error("Passed selection key did not have a corresponding Connection!(Read)");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doJob() {
|
||||
if (runStatus) {
|
||||
this.ac.connMan.receive(sk);
|
||||
this.ac.execTask.compareAndSet(true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class WriteOperationHander extends AbstractJob {
|
||||
|
||||
private final SelectionKey sk;
|
||||
private final AbstractConnection ac;
|
||||
private final boolean runStatus;
|
||||
|
||||
public WriteOperationHander(final SelectionKey sk) {
|
||||
this.sk = sk;
|
||||
|
||||
if (sk.attachment() instanceof AbstractConnection) {
|
||||
this.ac = (AbstractConnection) sk.attachment();
|
||||
this.runStatus = this.ac.execTask.compareAndSet(false, true);
|
||||
} else {
|
||||
this.runStatus = false;
|
||||
this.ac = null;
|
||||
Logger.error("Passed selection key did not have a corresponding Connection!(Write)");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doJob() {
|
||||
if (runStatus) {
|
||||
this.ac.connMan.sendFinish(sk);
|
||||
this.ac.execTask.compareAndSet(true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.exception.SerializationException;
|
||||
import engine.net.client.Protocol;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.util.StringUtils;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* This class represents the NetMsgs set to/from the SBClient and in between
|
||||
* MBServer Server Suite components. Note that since the NetMsgs sent to/from
|
||||
* the SBClient do NOT include a MsgLen or DataLen parameter, special
|
||||
* serialization/deserialization must be implemented.
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractNetMsg {
|
||||
|
||||
protected final Protocol protocolMsg;
|
||||
private AbstractConnection origin;
|
||||
|
||||
private static ConcurrentHashMap<Protocol, NetMsgStat> stats = new ConcurrentHashMap<>(MBServerStatics.CHM_INIT_CAP, MBServerStatics.CHM_LOAD, MBServerStatics.CHM_THREAD_HIGH);
|
||||
|
||||
/**
|
||||
* This is the general purpose constructor.
|
||||
*
|
||||
* @param protocolMsg
|
||||
*/
|
||||
protected AbstractNetMsg(Protocol protocolMsg) {
|
||||
super();
|
||||
this.protocolMsg = protocolMsg;
|
||||
}
|
||||
|
||||
protected AbstractNetMsg(Protocol protocolMsg, AbstractConnection origin) {
|
||||
super();
|
||||
this.protocolMsg = protocolMsg;
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
protected AbstractNetMsg(Protocol protocolMsg, AbstractNetMsg msg) {
|
||||
super();
|
||||
this.protocolMsg = protocolMsg;
|
||||
this.origin = msg.origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor is used by NetMsgFactory. It attempts to deserialize the
|
||||
* ByteBuffer into a message. If a BufferUnderflow occurs (based on reading
|
||||
* past the limit) then this constructor Throws that Exception to the
|
||||
* caller.
|
||||
*
|
||||
* @param reader
|
||||
*/
|
||||
protected AbstractNetMsg(Protocol protocolMsg, AbstractConnection origin,
|
||||
ByteBufferReader reader)
|
||||
{
|
||||
this.protocolMsg = protocolMsg;
|
||||
this.origin = origin;
|
||||
|
||||
// Call the subclass specific deserializer
|
||||
try {
|
||||
this._deserialize(reader);
|
||||
} catch (NullPointerException e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the subclass specific items from the supplied
|
||||
* ByteBufferReader
|
||||
*
|
||||
* @param reader
|
||||
*/
|
||||
protected abstract void _deserialize(ByteBufferReader reader);
|
||||
|
||||
/**
|
||||
* Serializes the subclass specific items to the supplied ByteBufferWriter
|
||||
*
|
||||
* @param writer
|
||||
* @throws Exception
|
||||
*/
|
||||
protected abstract void _serialize(ByteBufferWriter writer)
|
||||
throws SerializationException;
|
||||
|
||||
/**
|
||||
* Attempts to serialize this NetMsg into a ByteBuffer. ByteBuffer is
|
||||
* obtained from a pool, so to retain max efficiency, the caller needs to
|
||||
* return this BB to the pool. Header size and layout is entirely defined by
|
||||
* the subclass of AbstractNetMsg
|
||||
*
|
||||
* @return a ByteBuffer
|
||||
*/
|
||||
public final ByteBuffer serialize() {
|
||||
|
||||
NetMsgStat stat;
|
||||
|
||||
if (!AbstractNetMsg.stats.containsKey(this.protocolMsg)) {
|
||||
stat = new NetMsgStat(this.protocolMsg, this.getPowerOfTwoBufferSize());
|
||||
AbstractNetMsg.stats.put(this.protocolMsg, stat);
|
||||
} else
|
||||
stat = AbstractNetMsg.stats.get(this.protocolMsg);
|
||||
int lowerPow = stat.getMax();
|
||||
int upperPow = lowerPow + 4;
|
||||
|
||||
ByteBuffer bb = null;
|
||||
|
||||
int startPos = 0;
|
||||
ByteBufferWriter writer = null;
|
||||
|
||||
for (int i = lowerPow; i < upperPow; ++i) {
|
||||
|
||||
// get an appropriate sized BB from pool
|
||||
|
||||
bb = Network.byteBufferPool.getBuffer(i);
|
||||
|
||||
// Mark start position
|
||||
|
||||
startPos = bb.position();
|
||||
|
||||
// Make a writer
|
||||
|
||||
writer = new ByteBufferWriter(bb); // FIXME inefficient to
|
||||
|
||||
// Set aside header here.
|
||||
|
||||
AbstractNetMsg.allocHeader(writer, this.getHeaderSize());
|
||||
|
||||
// Now serialize the object's specifics
|
||||
|
||||
try {
|
||||
this._serialize(writer);
|
||||
|
||||
//Serialize successful, update NetMsgStat
|
||||
|
||||
stat.updateStat(i);
|
||||
|
||||
} catch (BufferOverflowException boe) {
|
||||
Logger.error("BufferSize PowerOfTwo: " + i
|
||||
+ " is too small for " + protocolMsg != null? protocolMsg.name() : this.getClass().getName() + ", trying again with " + (i + 1));
|
||||
|
||||
//Return buffer.
|
||||
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
continue;
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
//Return buffer.
|
||||
Logger.error(e);
|
||||
e.printStackTrace();
|
||||
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
return null;
|
||||
}
|
||||
|
||||
// This shouldn't throw any errors since this part of the BB has
|
||||
// already been allocated
|
||||
|
||||
this.writeHeaderAt(startPos, writer);
|
||||
return writer.getBb();
|
||||
}
|
||||
|
||||
// If we get here, its not a successful serialization and lastError
|
||||
// should be set
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void allocHeader(ByteBufferWriter writer, int bytes) {
|
||||
byte zero = 0; // prevents the int->byte cast
|
||||
for (int h = 0; h < bytes; ++h) {
|
||||
writer.put(zero);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function allows for setting other than default initial Buffer size for
|
||||
* the Serializer. Override and return the size of the buffer in power of
|
||||
* two bytes.
|
||||
*
|
||||
* Example, if you would like a buffer of 65535, then return 16 from this
|
||||
* value since 2^16 = 65535
|
||||
*
|
||||
* @return the power to raise two to.
|
||||
*/
|
||||
protected int getPowerOfTwoBufferSize() {
|
||||
return (10); // 2^10 == 1024
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces subclass to define how large (in bytes) the message's header is.
|
||||
*
|
||||
* @return the length (in bytes) of this message type's header.
|
||||
*/
|
||||
protected abstract int getHeaderSize();
|
||||
|
||||
/**
|
||||
* Forces subclasses to implement how to write its own header into a
|
||||
* byteBuffer
|
||||
*
|
||||
* @param startPos
|
||||
* - starting position for the header write
|
||||
* @param writer
|
||||
* - ByteBufferWriter to write the header to.
|
||||
*/
|
||||
protected abstract void writeHeaderAt(int startPos, ByteBufferWriter writer);
|
||||
|
||||
/**
|
||||
* @return The protocolMsg of this Msg.
|
||||
*/
|
||||
public Protocol getProtocolMsg() {
|
||||
return protocolMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The protocolMsg As a string.
|
||||
*/
|
||||
public String getOpcodeAsString() {
|
||||
return StringUtils.toHexString(protocolMsg.opcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the origin
|
||||
*/
|
||||
public AbstractConnection getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public void setOrigin(AbstractConnection conn) {
|
||||
this.origin = conn;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.util.ByteBufferUtils;
|
||||
import engine.util.ByteUtils;
|
||||
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ByteBufferReader {
|
||||
|
||||
private final ByteBuffer bb;
|
||||
private final boolean endianFlip;
|
||||
|
||||
/**
|
||||
* Helper class for getting structured information out of a ByteBuffer
|
||||
* easily. ByteBuffer passed in is copied to an internal ByteBuffer.
|
||||
* <B>bbin</B> must have the position attribute at the <i>end</i> of the
|
||||
* data to be copied over, since <b>bbin.flip()</b> is called in this
|
||||
* constructor.
|
||||
*
|
||||
* @param bbin
|
||||
* @param endianFlip
|
||||
*/
|
||||
public ByteBufferReader(ByteBuffer bbin, boolean endianFlip) {
|
||||
super();
|
||||
|
||||
// Copy supplied BB.
|
||||
this.bb = ByteBuffer.allocate(bbin.position()); //FIXME Do we want to get this from pool?
|
||||
bbin.flip();
|
||||
this.bb.put(bbin);
|
||||
|
||||
// prepare bb for reading
|
||||
this.bb.flip();
|
||||
|
||||
this.endianFlip = endianFlip;
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.ByteBuffer#get()
|
||||
*/
|
||||
public byte get() {
|
||||
return bb.get();
|
||||
}
|
||||
|
||||
public void get(byte[] ba) {
|
||||
this.bb.get(ba);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.ByteBuffer#getChar()
|
||||
*/
|
||||
public char getChar() {
|
||||
char x = bb.getChar();
|
||||
if (this.endianFlip) {
|
||||
x = Character.reverseBytes(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.ByteBuffer#getDouble()
|
||||
*/
|
||||
public double getDouble() {
|
||||
double x = 0;
|
||||
if (this.endianFlip) {
|
||||
x = bb.order(ByteOrder.LITTLE_ENDIAN).getDouble();
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
} else {
|
||||
x = bb.getDouble();
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.ByteBuffer#getFloat()
|
||||
*/
|
||||
public float getFloat() {
|
||||
float x = 0;
|
||||
if (this.endianFlip) {
|
||||
x = bb.order(ByteOrder.LITTLE_ENDIAN).getFloat();
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
} else {
|
||||
x = bb.getFloat();
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.ByteBuffer#getInt()
|
||||
*/
|
||||
public int getInt() {
|
||||
int x = bb.getInt();
|
||||
if (this.endianFlip) {
|
||||
x = Integer.reverseBytes(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.ByteBuffer#getLong()
|
||||
*/
|
||||
public long getLong() {
|
||||
long x = bb.getLong();
|
||||
if (this.endianFlip) {
|
||||
x = Long.reverseBytes(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.ByteBuffer#getShort()
|
||||
*/
|
||||
public short getShort() {
|
||||
short x = bb.getShort();
|
||||
if (this.endianFlip) {
|
||||
x = Short.reverseBytes(x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
public final String getString() {
|
||||
if (this.endianFlip) {
|
||||
return ByteBufferUtils.getString(this.bb, true, false);
|
||||
} else {
|
||||
return ByteBufferUtils.getString(this.bb, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
public final String getSmallString() {
|
||||
if (this.endianFlip) {
|
||||
return ByteBufferUtils.getString(this.bb, true, true);
|
||||
} else {
|
||||
return ByteBufferUtils.getString(this.bb, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
public final String getHexString() {
|
||||
if (this.endianFlip) {
|
||||
return ByteBufferUtils.getHexString(this.bb, true);
|
||||
} else {
|
||||
return ByteBufferUtils.getHexString(this.bb);
|
||||
}
|
||||
}
|
||||
|
||||
public final String getUnicodeString() {
|
||||
if (this.endianFlip) {
|
||||
return ByteBufferUtils.getUnicodeString(this.bb, true);
|
||||
} else {
|
||||
return ByteBufferUtils.getUnicodeString(this.bb);
|
||||
}
|
||||
}
|
||||
|
||||
public String get1ByteAsHexString() {
|
||||
return getBytesAsHexStringCommon(new byte[1]);
|
||||
}
|
||||
|
||||
public String get2BytesAsHexString() {
|
||||
return getBytesAsHexStringCommon(new byte[2]);
|
||||
}
|
||||
|
||||
public String get4BytesAsHexString() {
|
||||
return getBytesAsHexStringCommon(new byte[4]);
|
||||
}
|
||||
|
||||
public String get8BytesAsHexString() {
|
||||
return getBytesAsHexStringCommon(new byte[8]);
|
||||
}
|
||||
|
||||
private String getBytesAsHexStringCommon(byte[] ba) {
|
||||
this.bb.get(ba);
|
||||
if (this.endianFlip) {
|
||||
return ByteUtils.byteArrayToStringHex(ByteUtils
|
||||
.switchByteArrayEndianness(ba));
|
||||
} else {
|
||||
return ByteUtils.byteArrayToStringHex(ba);
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3f getVector3f() {
|
||||
Vector3f out = new Vector3f();
|
||||
if (this.endianFlip) {
|
||||
out.x = Float
|
||||
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt()));
|
||||
out.y = Float
|
||||
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt()));
|
||||
out.z = Float
|
||||
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt()));
|
||||
} else {
|
||||
out.x = this.bb.getFloat();
|
||||
out.y = this.bb.getFloat();
|
||||
out.z = this.bb.getFloat();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public Vector3fImmutable getVector3fImmutable() {
|
||||
Vector3fImmutable out;
|
||||
if (this.endianFlip) {
|
||||
out = new Vector3fImmutable(Float.intBitsToFloat(Integer
|
||||
.reverseBytes(this.bb.getInt())), Float
|
||||
.intBitsToFloat(Integer.reverseBytes(this.bb.getInt())),
|
||||
Float
|
||||
.intBitsToFloat(Integer.reverseBytes(this.bb
|
||||
.getInt())));
|
||||
} else {
|
||||
out = new Vector3fImmutable(this.bb.getFloat(), this.bb.getFloat(),
|
||||
this.bb.getFloat());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public final UUID getUUID() {
|
||||
final byte[] buffer = new byte[16];
|
||||
this.bb.get(buffer);
|
||||
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
msb = (msb << 8) | (buffer[i] & 0xff);
|
||||
}
|
||||
|
||||
for (int i = 8; i < 16; i++) {
|
||||
lsb = (lsb << 8) | (buffer[i] & 0xff);
|
||||
}
|
||||
|
||||
return new UUID(msb, lsb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Monitors
|
||||
*/
|
||||
|
||||
public byte monitorByte(byte expectedValue, String label) {
|
||||
return this.monitorByte(expectedValue, label, false);
|
||||
}
|
||||
|
||||
public byte monitorByte(byte expectedValue, String label, boolean peek) {
|
||||
// if (x != expectedValue) {
|
||||
// Logger.info("MonitorTrip: " + label + ". Expected: "
|
||||
// + expectedValue + " Got: " + x);
|
||||
// }
|
||||
return this.get();
|
||||
}
|
||||
|
||||
public short monitorShort(short expectedValue, String label) {
|
||||
return this.monitorShort(expectedValue, label, false);
|
||||
}
|
||||
|
||||
public short monitorShort(short expectedValue, String label, boolean peek) {
|
||||
// if (x != expectedValue) {
|
||||
// Logger.info("MonitorTrip: " + label + ". Expected: "
|
||||
// + expectedValue + " Got: " + x);
|
||||
// }
|
||||
return this.getShort();
|
||||
}
|
||||
|
||||
public int monitorInt(int expectedValue, String label) {
|
||||
return this.monitorInt(expectedValue, label, false);
|
||||
}
|
||||
|
||||
public int monitorInt(int expectedValue, String label, boolean peek) {
|
||||
// if (x != expectedValue) {
|
||||
// Logger.info("MonitorTrip: " + label + ". Expected: "
|
||||
// + expectedValue + " Got: " + x);
|
||||
// }
|
||||
return this.getInt();
|
||||
}
|
||||
|
||||
public long monitorLong(long expectedValue, String label) {
|
||||
return this.monitorLong(expectedValue, label, false);
|
||||
}
|
||||
|
||||
public long monitorLong(long expectedValue, String label, boolean peek) {
|
||||
// if (x != expectedValue) {
|
||||
// Logger.info("MonitorTrip: " + label + ". Expected: "
|
||||
// + expectedValue + " Got: " + x);
|
||||
// }
|
||||
return this.getLong();
|
||||
}
|
||||
|
||||
/*
|
||||
* ByteBuffer delegates
|
||||
*/
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#hasRemaining()
|
||||
*/
|
||||
public final boolean hasRemaining() {
|
||||
return bb.hasRemaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#limit()
|
||||
*/
|
||||
public final int limit() {
|
||||
return bb.limit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#position()
|
||||
*/
|
||||
public final int position() {
|
||||
return bb.position();
|
||||
}
|
||||
public final Buffer position(int newPosition){
|
||||
return bb.position(newPosition);
|
||||
}
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#remaining()
|
||||
*/
|
||||
public final int remaining() {
|
||||
return bb.remaining();
|
||||
}
|
||||
|
||||
/*
|
||||
* Status getters
|
||||
*/
|
||||
|
||||
protected ByteBuffer getBb() {
|
||||
return bb;
|
||||
}
|
||||
|
||||
protected boolean isEndianFlip() {
|
||||
return endianFlip;
|
||||
}
|
||||
|
||||
public String getByteArray() {
|
||||
String ret = "";
|
||||
if (this.bb == null)
|
||||
return ret;
|
||||
byte[] bbyte = bb.array();
|
||||
if (bbyte == null)
|
||||
return ret;
|
||||
for (int i=0;i<bbyte.length;i++) {
|
||||
ret += Integer.toString((bbyte[i] & 0xff) + 0x100, 16).substring(1).toUpperCase();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.math.Vector3f;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.util.ByteBufferUtils;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
//TODO possibly pool this class? Maybe make them static?
|
||||
//TODO need to extract the SB specific stuff from here into subclass.
|
||||
|
||||
public class ByteBufferWriter {
|
||||
|
||||
private final ByteBuffer bb;
|
||||
|
||||
public ByteBufferWriter(ByteBuffer bb) {
|
||||
super();
|
||||
this.bb = bb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Putters
|
||||
*/
|
||||
|
||||
public synchronized void put(byte x) {
|
||||
|
||||
this.bb.put(x);
|
||||
}
|
||||
|
||||
public synchronized void putChar(char x) {
|
||||
|
||||
this.bb.putChar(x);
|
||||
}
|
||||
|
||||
public synchronized void putShort(short x) {
|
||||
|
||||
this.bb.putShort(x);
|
||||
}
|
||||
|
||||
public synchronized void putInt(int x) {
|
||||
this.bb.putInt(x);
|
||||
}
|
||||
|
||||
public synchronized void putLong(long x) {
|
||||
this.bb.putLong(x);
|
||||
}
|
||||
|
||||
public synchronized void putDateTime(DateTime dateTime){
|
||||
this.put((byte)dateTime.getDayOfMonth());
|
||||
this.put((byte) ((byte)dateTime.getMonthOfYear() -1));
|
||||
this.putInt(dateTime.getYear()-1900);
|
||||
this.put((byte)dateTime.getHourOfDay());
|
||||
this.put((byte)dateTime.getMinuteOfHour());
|
||||
this.put((byte)dateTime.getSecondOfDay());
|
||||
}
|
||||
|
||||
public synchronized void putLocalDateTime(LocalDateTime dateTime){
|
||||
this.put((byte)dateTime.getDayOfMonth());
|
||||
this.put((byte) ((byte)dateTime.getMonth().getValue() -1));
|
||||
this.putInt(dateTime.getYear() -1900);
|
||||
this.put((byte)dateTime.getHour());
|
||||
this.put((byte)dateTime.getMinute());
|
||||
this.put((byte)dateTime.getSecond());
|
||||
}
|
||||
|
||||
public synchronized void putFloat(float x) {
|
||||
this.bb.putFloat(x);
|
||||
}
|
||||
|
||||
public synchronized void putDouble(double x) {
|
||||
this.bb.putDouble(x);
|
||||
}
|
||||
|
||||
public synchronized void putString(String x) {
|
||||
ByteBufferUtils.putString(this.bb, x, false, false);
|
||||
}
|
||||
|
||||
public synchronized void putSmallString(String x) {
|
||||
ByteBufferUtils.putString(this.bb, x, false, true);
|
||||
}
|
||||
|
||||
public synchronized void putHexString(String x) {
|
||||
ByteBufferUtils.putHexString(this.bb, x, false);
|
||||
}
|
||||
|
||||
public synchronized void putHexStringWithoutSize(String data) {
|
||||
int length = data.length() / 2;
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
bb.put((byte) Integer.parseInt(data.substring(2 * i, 2 * i + 2), 16));
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void putUnicodeString(String x) {
|
||||
ByteBufferUtils.putUnicodeString(this.bb, x, false);
|
||||
}
|
||||
|
||||
public synchronized void putWriter(ByteBufferWriter writer) {
|
||||
synchronized (writer) {
|
||||
ByteBuffer bbin = writer.bb;
|
||||
bbin.flip();
|
||||
this.bb.put(bbin);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void putBB(ByteBuffer bb) {
|
||||
synchronized (bb) {
|
||||
bb.flip();
|
||||
this.bb.put(bb);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void putIntAt(int value, int position) {
|
||||
// mark end position
|
||||
int endPosition = this.position();
|
||||
|
||||
// go back to the desired position
|
||||
this.bb.position(position);
|
||||
|
||||
// Write in the value:
|
||||
this.putInt(value);
|
||||
|
||||
// now go back to end:
|
||||
this.bb.position(endPosition);
|
||||
}
|
||||
|
||||
public synchronized void putVector3f(Vector3f x) {
|
||||
this.bb.putFloat(x.x);
|
||||
this.bb.putFloat(x.y);
|
||||
this.bb.putFloat(x.z);
|
||||
}
|
||||
|
||||
public synchronized void putVector3f(Vector3fImmutable x) {
|
||||
this.bb.putFloat(x.x);
|
||||
this.bb.putFloat(x.y);
|
||||
this.bb.putFloat(x.z);
|
||||
}
|
||||
|
||||
public synchronized void putUUID(final UUID uuid) {
|
||||
final long msb = uuid.getMostSignificantBits();
|
||||
final long lsb = uuid.getLeastSignificantBits();
|
||||
final byte[] buffer = new byte[16];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
buffer[i] = (byte) (msb >>> 8 * (7 - i));
|
||||
}
|
||||
|
||||
for (int i = 8; i < 16; i++) {
|
||||
buffer[i] = (byte) (lsb >>> 8 * (7 - i));
|
||||
}
|
||||
|
||||
this.bb.put(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#hasRemaining()
|
||||
*/
|
||||
public final boolean hasRemaining() {
|
||||
return bb.hasRemaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#limit()
|
||||
*/
|
||||
public final int limit() {
|
||||
return bb.limit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#position()
|
||||
*/
|
||||
public final int position() {
|
||||
return bb.position();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @see java.nio.Buffer#remaining()
|
||||
*/
|
||||
public final int remaining() {
|
||||
return bb.remaining();
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
public synchronized ByteBuffer getBb() {
|
||||
return this.bb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.gameManager.ConfigManager;
|
||||
import engine.job.AbstractJob;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
public class CheckNetMsgFactoryJob extends AbstractJob {
|
||||
|
||||
private final AbstractConnection conn;
|
||||
|
||||
public CheckNetMsgFactoryJob(AbstractConnection conn) {
|
||||
super();
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doJob() {
|
||||
NetMsgFactory factory = conn.getFactory();
|
||||
|
||||
// Make any/all msg possible
|
||||
factory.parseBuffer();
|
||||
|
||||
// get and route.
|
||||
AbstractNetMsg msg = factory.getMsg();
|
||||
while (msg != null) {
|
||||
|
||||
// Conditionally check to see if origin is set.
|
||||
if (msg.getOrigin() == null) {
|
||||
Logger.warn(msg.getClass().getSimpleName() + " had a NULL for its 'origin'.");
|
||||
msg.setOrigin(this.conn);
|
||||
}
|
||||
|
||||
if (msg instanceof engine.net.client.msg.ClientNetMsg) {
|
||||
ConfigManager.handler.handleClientMsg((ClientNetMsg) msg);
|
||||
|
||||
} else {
|
||||
Logger.error("Unrouteable message of type '" + msg.getClass().getSimpleName() + '\'');
|
||||
}
|
||||
|
||||
msg = factory.getMsg();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.job.AbstractJob;
|
||||
import engine.job.JobScheduler;
|
||||
import engine.server.MBServerStatics;
|
||||
|
||||
public class ConnectionMonitorJob extends AbstractJob {
|
||||
|
||||
private final AbstractConnectionManager connMan;
|
||||
private byte cnt;
|
||||
|
||||
public ConnectionMonitorJob(AbstractConnectionManager connMan, byte cnt) {
|
||||
super();
|
||||
this.connMan = connMan;
|
||||
this.cnt = cnt;
|
||||
this.cnt++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doJob() {
|
||||
|
||||
if (this.cnt >= 5) {
|
||||
this.connMan.auditSocketChannelToConnectionMap();
|
||||
this.cnt = 0;
|
||||
} else
|
||||
this.connMan.auditSocketChannelToConnectionMap();
|
||||
|
||||
// Self Sustain
|
||||
ConnectionMonitorJob cmj = new ConnectionMonitorJob(this.connMan, cnt);
|
||||
JobScheduler.getInstance().scheduleJob(cmj, MBServerStatics.TIMEOUT_CHECKS_TIMER_MS);
|
||||
|
||||
this.setCompletionStatus(JobCompletionStatus.SUCCESS);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import static engine.net.MessageDispatcher.itemPoolSize;
|
||||
|
||||
/**
|
||||
* Data class holds a message and a distribution list
|
||||
*/
|
||||
|
||||
public class Dispatch {
|
||||
|
||||
private static final ConcurrentLinkedQueue<Dispatch> dispatchPool = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public PlayerCharacter player;
|
||||
public AbstractNetMsg msg;
|
||||
|
||||
public Dispatch(PlayerCharacter player, AbstractNetMsg msg) {
|
||||
this.player = player;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.player = null;
|
||||
this.msg = null;
|
||||
}
|
||||
|
||||
public static Dispatch borrow(PlayerCharacter player, AbstractNetMsg msg) {
|
||||
|
||||
Dispatch dispatch;
|
||||
|
||||
dispatch = dispatchPool.poll();
|
||||
|
||||
if (dispatch == null) {
|
||||
dispatch = new Dispatch(player, msg);
|
||||
} else {
|
||||
dispatch.player = player;
|
||||
dispatch.msg = msg;
|
||||
itemPoolSize.decrement();
|
||||
}
|
||||
|
||||
return dispatch;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
this.reset();
|
||||
dispatchPool.add(this);
|
||||
itemPoolSize.increment();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.objects.AbstractWorldObject;
|
||||
import engine.objects.Item;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import static engine.net.MessageDispatcher.dispatchCount;
|
||||
import static engine.net.MessageDispatcher.maxRecipients;
|
||||
|
||||
/*
|
||||
* Dispatch Message is the main interface to Magicbane's threaded
|
||||
* asynch message delivery system.
|
||||
*/
|
||||
|
||||
public class DispatchMessage {
|
||||
|
||||
public static void startMessagePump() {
|
||||
|
||||
Thread messageDispatcher;
|
||||
messageDispatcher = new Thread(new MessageDispatcher());
|
||||
|
||||
messageDispatcher.setName("MessageDispatcher");
|
||||
messageDispatcher.start();
|
||||
}
|
||||
|
||||
|
||||
public static void sendToAllInRange(AbstractWorldObject obj,
|
||||
AbstractNetMsg msg){
|
||||
|
||||
if (obj == null)
|
||||
return;
|
||||
|
||||
if (obj.getObjectType() == GameObjectType.PlayerCharacter || obj.getObjectType() == GameObjectType.Mob || obj.getObjectType() == GameObjectType.NPC || obj.getObjectType() == GameObjectType.Corpse)
|
||||
dispatchMsgToInterestArea(obj, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
else
|
||||
dispatchMsgToInterestArea(obj ,msg, DispatchChannel.PRIMARY, MBServerStatics.STRUCTURE_LOAD_RANGE, false, false);
|
||||
|
||||
}
|
||||
|
||||
// Dispatches a message to a playercharacter's interest area
|
||||
// Method includes handling of exclusion rules for visibility, self, etc.
|
||||
|
||||
public static void dispatchMsgToInterestArea(AbstractWorldObject sourceObject, AbstractNetMsg msg, DispatchChannel dispatchChannel, int interestRange, boolean sendToSelf, boolean useIgnore) {
|
||||
|
||||
Dispatch messageDispatch;
|
||||
HashSet<AbstractWorldObject> gridList;
|
||||
PlayerCharacter gridPlayer;
|
||||
AbstractWorldObject dispatchSource;
|
||||
PlayerCharacter sourcePlayer = null;
|
||||
long recipientCount = 0;
|
||||
|
||||
if (sourceObject == null)
|
||||
return;
|
||||
|
||||
// If the source of the message is a structure, item or player
|
||||
// setup our method variables accordingly.
|
||||
|
||||
switch (sourceObject.getObjectType()) {
|
||||
case Item:
|
||||
dispatchSource = (AbstractWorldObject) ((Item) sourceObject).getOwner();
|
||||
break;
|
||||
case PlayerCharacter:
|
||||
dispatchSource = sourceObject;
|
||||
sourcePlayer = (PlayerCharacter)sourceObject;
|
||||
if (sourcePlayer.getClientConnection() != null && sendToSelf){
|
||||
Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
dispatchSource = sourceObject;
|
||||
}
|
||||
|
||||
gridList = WorldGrid.getObjectsInRangePartial(dispatchSource.getLoc(), interestRange, MBServerStatics.MASK_PLAYER);
|
||||
|
||||
for (AbstractWorldObject gridObject : gridList) {
|
||||
|
||||
gridPlayer = (PlayerCharacter)gridObject;
|
||||
|
||||
// Apply filter options if source of dispatch is a player
|
||||
|
||||
if ((dispatchSource.getObjectType() == GameObjectType.PlayerCharacter) &&
|
||||
(sourcePlayer != null)) {
|
||||
|
||||
if (gridPlayer.getObjectUUID() == sourcePlayer.getObjectUUID())
|
||||
continue;
|
||||
|
||||
if ((useIgnore == true) && (gridPlayer.isIgnoringPlayer(sourcePlayer) == true))
|
||||
continue;
|
||||
|
||||
if(gridPlayer.canSee(sourcePlayer) == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
messageDispatch = Dispatch.borrow(gridPlayer, msg);
|
||||
MessageDispatcher.send(messageDispatch, dispatchChannel);
|
||||
recipientCount++;
|
||||
}
|
||||
|
||||
// Update metrics
|
||||
|
||||
if (recipientCount > maxRecipients[dispatchChannel.getChannelID()])
|
||||
maxRecipients[dispatchChannel.getChannelID()] = recipientCount;
|
||||
|
||||
dispatchCount[dispatchChannel.getChannelID()].increment();
|
||||
}
|
||||
|
||||
public static void dispatchMsgToInterestArea(Vector3fImmutable targetLoc,AbstractWorldObject sourceObject, AbstractNetMsg msg, DispatchChannel dispatchChannel, int interestRange, boolean sendToSelf, boolean useIgnore) {
|
||||
|
||||
Dispatch messageDispatch;
|
||||
HashSet<AbstractWorldObject> gridList;
|
||||
PlayerCharacter gridPlayer;
|
||||
AbstractWorldObject dispatchSource;
|
||||
PlayerCharacter sourcePlayer = null;
|
||||
long recipientCount = 0;
|
||||
|
||||
if (sourceObject == null)
|
||||
return;
|
||||
|
||||
// If the source of the message is a structure, item or player
|
||||
// setup our method variables accordingly.
|
||||
|
||||
switch (sourceObject.getObjectType()) {
|
||||
case Item:
|
||||
dispatchSource = (AbstractWorldObject) ((Item) sourceObject).getOwner();
|
||||
break;
|
||||
case PlayerCharacter:
|
||||
dispatchSource = sourceObject;
|
||||
sourcePlayer = (PlayerCharacter)sourceObject;
|
||||
|
||||
if (sourcePlayer.getClientConnection() != null && sendToSelf){
|
||||
Dispatch dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
dispatchSource = sourceObject;
|
||||
}
|
||||
|
||||
gridList = WorldGrid.getObjectsInRangePartial(targetLoc, interestRange, MBServerStatics.MASK_PLAYER);
|
||||
|
||||
for (AbstractWorldObject gridObject : gridList) {
|
||||
|
||||
gridPlayer = (PlayerCharacter)gridObject;
|
||||
|
||||
// Apply filter options if source of dispatch is a player
|
||||
|
||||
if ((dispatchSource.getObjectType() == GameObjectType.PlayerCharacter) &&
|
||||
(sourcePlayer != null)) {
|
||||
|
||||
if (gridPlayer.getObjectUUID() == sourcePlayer.getObjectUUID())
|
||||
continue;
|
||||
|
||||
if ((useIgnore == true) && (gridPlayer.isIgnoringPlayer(sourcePlayer) == true))
|
||||
continue;
|
||||
|
||||
if(gridPlayer.canSee(sourcePlayer) == false)
|
||||
continue;
|
||||
}
|
||||
|
||||
messageDispatch = Dispatch.borrow(gridPlayer, msg);
|
||||
MessageDispatcher.send(messageDispatch, dispatchChannel);
|
||||
recipientCount++;
|
||||
}
|
||||
|
||||
// Update metrics
|
||||
|
||||
if (recipientCount > maxRecipients[dispatchChannel.getChannelID()])
|
||||
maxRecipients[dispatchChannel.getChannelID()] = recipientCount;
|
||||
|
||||
dispatchCount[dispatchChannel.getChannelID()].increment();
|
||||
}
|
||||
|
||||
// Sends a message to all players in the game
|
||||
|
||||
public static void dispatchMsgToAll(AbstractNetMsg msg) {
|
||||
|
||||
Dispatch messageDispatch;
|
||||
long recipientCount = 0;
|
||||
|
||||
// Send message to nobody? No thanks!
|
||||
|
||||
if (SessionManager.getAllActivePlayerCharacters().isEmpty())
|
||||
return;
|
||||
|
||||
// Messages to all we will default to the secondary dispatch
|
||||
// delivery channel. They are generally large, or inconsequential.
|
||||
|
||||
for (PlayerCharacter player : SessionManager.getAllActivePlayerCharacters()) {
|
||||
messageDispatch = Dispatch.borrow(player, msg);
|
||||
MessageDispatcher.send(messageDispatch, DispatchChannel.SECONDARY);
|
||||
recipientCount++;
|
||||
}
|
||||
|
||||
// Update metrics
|
||||
|
||||
if (recipientCount > maxRecipients[DispatchChannel.SECONDARY.getChannelID()])
|
||||
maxRecipients[DispatchChannel.SECONDARY.getChannelID()] = recipientCount;
|
||||
|
||||
dispatchCount[DispatchChannel.SECONDARY.getChannelID()].increment();
|
||||
|
||||
}
|
||||
|
||||
public static void dispatchMsgToAll(PlayerCharacter source, AbstractNetMsg msg, boolean ignore) {
|
||||
|
||||
Dispatch messageDispatch;
|
||||
long recipientCount = 0;
|
||||
|
||||
// Send message to nobody? No thanks!
|
||||
|
||||
if (SessionManager.getAllActivePlayerCharacters().isEmpty())
|
||||
return;
|
||||
|
||||
// Messages to all we will default to the secondary dispatch
|
||||
// delivery channel. They are generally large, or inconsequential.
|
||||
|
||||
for (PlayerCharacter player : SessionManager.getAllActivePlayerCharacters()) {
|
||||
|
||||
if (ignore && player.isIgnoringPlayer(source))
|
||||
continue;
|
||||
|
||||
messageDispatch = Dispatch.borrow(player, msg);
|
||||
MessageDispatcher.send(messageDispatch, DispatchChannel.SECONDARY);
|
||||
recipientCount++;
|
||||
}
|
||||
|
||||
// Update metrics
|
||||
|
||||
if (recipientCount > maxRecipients[DispatchChannel.SECONDARY.getChannelID()])
|
||||
maxRecipients[DispatchChannel.SECONDARY.getChannelID()] = recipientCount;
|
||||
|
||||
dispatchCount[DispatchChannel.SECONDARY.getChannelID()].increment();
|
||||
|
||||
}
|
||||
|
||||
// Sends a message to an arbitrary distribution list
|
||||
|
||||
public static void dispatchMsgDispatch(Dispatch messageDispatch, DispatchChannel dispatchChannel) {
|
||||
|
||||
if (messageDispatch == null){
|
||||
Logger.info("DISPATCH Null for DispatchMessage!");
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to serialize an empty list
|
||||
|
||||
if (messageDispatch.player == null){
|
||||
Logger.info("Player Null for Dispatch!");
|
||||
messageDispatch.release();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
MessageDispatcher.send(messageDispatch, dispatchChannel);
|
||||
|
||||
dispatchCount[dispatchChannel.getChannelID()].increment();
|
||||
|
||||
}
|
||||
|
||||
protected static void serializeDispatch(Dispatch messageDispatch) {
|
||||
ClientConnection connection;
|
||||
|
||||
if (messageDispatch.player == null){
|
||||
Logger.info("Player null in serializeDispatch");
|
||||
messageDispatch.release();
|
||||
return;
|
||||
}
|
||||
|
||||
connection = messageDispatch.player.getClientConnection();
|
||||
|
||||
if ((connection == null) || (connection.isConnected() == false)) {
|
||||
messageDispatch.release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (messageDispatch.msg == null) {
|
||||
Logger.error("null message sent to " + messageDispatch.player.getName());
|
||||
messageDispatch.release();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!connection.sendMsg(messageDispatch.msg))
|
||||
Logger.error(messageDispatch.msg.getProtocolMsg() + " failed sending to " + messageDispatch.player.getName());
|
||||
|
||||
messageDispatch.release();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.objects.ProducedItem;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.DelayQueue;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
/**
|
||||
* Thread blocks until MagicBane dispatch messages are
|
||||
* enqueued then processes them in FIFO order. The collection
|
||||
* is thread safe.
|
||||
*
|
||||
* Any large messages not time sensitive such as load object
|
||||
* sent to more than a single individual should be spawned
|
||||
* individually on a DispatchMessageThread.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public enum ItemProductionManager implements Runnable {
|
||||
|
||||
ITEMPRODUCTIONMANAGER;
|
||||
|
||||
|
||||
// Instance variables
|
||||
|
||||
private ItemQueue itemQueue;
|
||||
|
||||
private long nextFailedItemAudit;
|
||||
|
||||
// Class variables
|
||||
|
||||
@SuppressWarnings("unchecked") // Cannot have arrays of generics in java.
|
||||
private static final DelayQueue<ItemQueue> producedQueue = new DelayQueue<>();
|
||||
|
||||
|
||||
// Performance metrics
|
||||
|
||||
public static volatile long[] messageCount = new long[DispatchChannel.values().length];
|
||||
public static LongAdder[] dispatchCount = new LongAdder[DispatchChannel.values().length];
|
||||
public static volatile long[] maxRecipients = new long[DispatchChannel.values().length];
|
||||
public static LongAdder dispatchPoolSize = new LongAdder();
|
||||
|
||||
public static HashSet<ProducedItem> FailedItems = new HashSet<>();
|
||||
|
||||
public Thread itemProductionThread = null;
|
||||
|
||||
// Thread constructor
|
||||
|
||||
|
||||
public void startMessagePump() {
|
||||
|
||||
itemProductionThread = new Thread(this);
|
||||
itemProductionThread.setName("ItemProductionManager");
|
||||
|
||||
}
|
||||
|
||||
public void initialize(){
|
||||
itemProductionThread.start();
|
||||
}
|
||||
|
||||
|
||||
public static void send(ItemQueue item) {
|
||||
|
||||
// Don't queue up empty dispatches!
|
||||
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
producedQueue.add(item);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
|
||||
this.itemQueue = producedQueue.take();
|
||||
|
||||
if (this.itemQueue == null){
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.itemQueue != null) {
|
||||
if (this.itemQueue.item == null){
|
||||
this.itemQueue.release();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
boolean created = this.itemQueue.item.finishProduction();
|
||||
|
||||
if (!created)
|
||||
FailedItems.add(this.itemQueue.item);
|
||||
|
||||
this.itemQueue.release();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static String getNetstatString() {
|
||||
|
||||
String outString = null;
|
||||
String newLine = System.getProperty("line.separator");
|
||||
outString = "[LUA_NETSTA()]" + newLine;
|
||||
outString += "poolSize: " + dispatchPoolSize.longValue() + '\n';
|
||||
|
||||
for (DispatchChannel dispatchChannel : DispatchChannel.values()) {
|
||||
|
||||
outString += "Channel: " + dispatchChannel.name() + '\n';
|
||||
outString += "Dispatches: " + dispatchCount[dispatchChannel.getChannelID()].longValue()+ '\n';
|
||||
outString += "Messages: " + messageCount[dispatchChannel.getChannelID()] + '\n';
|
||||
outString += "maxRecipients: " + maxRecipients[dispatchChannel.getChannelID()] + '\n';
|
||||
}
|
||||
return outString;
|
||||
}
|
||||
|
||||
// For Debugging:
|
||||
//Logger.error("MessageDispatcher", messageDispatch.msg.getOpcodeAsString() + " sent to " + messageDispatch.playerList.size() + " players");
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.objects.ProducedItem;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static engine.net.MessageDispatcher.itemPoolSize;
|
||||
|
||||
/**
|
||||
* Data class holds a message and a distribution list
|
||||
*/
|
||||
|
||||
public class ItemQueue implements Delayed {
|
||||
|
||||
private static final ConcurrentLinkedQueue<ItemQueue> itemPool = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public ProducedItem item;
|
||||
public long delayTime;
|
||||
|
||||
|
||||
public ItemQueue(ProducedItem item, long delayTime) {
|
||||
this.item = item;
|
||||
this.delayTime = System.currentTimeMillis() + delayTime;
|
||||
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.item = null;
|
||||
this.delayTime = 0;
|
||||
}
|
||||
|
||||
public static ItemQueue borrow(ProducedItem item, long delayTime) {
|
||||
|
||||
ItemQueue itemQueue;
|
||||
|
||||
itemQueue = itemPool.poll();
|
||||
|
||||
if (itemQueue == null) {
|
||||
itemQueue = new ItemQueue(item, delayTime);
|
||||
} else {
|
||||
itemQueue.item = item;
|
||||
itemQueue.delayTime = System.currentTimeMillis() + delayTime;
|
||||
itemPoolSize.decrement();
|
||||
}
|
||||
|
||||
return itemQueue;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
this.reset();
|
||||
itemPool.add(this);
|
||||
itemPoolSize.increment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Delayed another) {
|
||||
ItemQueue anotherTask = (ItemQueue) another;
|
||||
|
||||
if (this.delayTime < anotherTask.delayTime) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (this.delayTime > anotherTask.delayTime) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDelay(TimeUnit unit) {
|
||||
long difference = delayTime - System.currentTimeMillis();
|
||||
return unit.convert(difference, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Thread blocks until MagicBane dispatch messages are
|
||||
* enqueued then processes them in FIFO order. The collection
|
||||
* is thread safe.
|
||||
*
|
||||
* Any large messages not time sensitive such as load object
|
||||
* sent to more than a single individual should be spawned
|
||||
* individually on a DispatchMessageThread.
|
||||
*/
|
||||
|
||||
public class MessageDispatcher implements Runnable {
|
||||
|
||||
// Instance variables
|
||||
|
||||
private Dispatch messageDispatch;
|
||||
private final Pattern filterPattern; // Unused, but just in case
|
||||
|
||||
// Class variables
|
||||
|
||||
@SuppressWarnings("unchecked") // Cannot have arrays of generics in java.
|
||||
private static final ConcurrentLinkedQueue<Dispatch>[] _messageQueue = new ConcurrentLinkedQueue[DispatchChannel.values().length];
|
||||
|
||||
private static final LinkedBlockingQueue<Boolean> _blockingQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
// Performance metrics
|
||||
|
||||
public static volatile long[] messageCount = new long[DispatchChannel.values().length];
|
||||
public static LongAdder[] dispatchCount = new LongAdder[DispatchChannel.values().length];
|
||||
public static volatile long[] maxRecipients = new long[DispatchChannel.values().length];
|
||||
public static LongAdder itemPoolSize = new LongAdder();
|
||||
|
||||
// Thread constructor
|
||||
|
||||
public MessageDispatcher() {
|
||||
|
||||
// Create new FIFO queues for this network thread
|
||||
|
||||
for (DispatchChannel dispatchChannel : DispatchChannel.values()) {
|
||||
_messageQueue[dispatchChannel.getChannelID()] = new ConcurrentLinkedQueue<>();
|
||||
dispatchCount[dispatchChannel.getChannelID()] = new LongAdder();
|
||||
}
|
||||
|
||||
filterPattern = Pattern.compile("[^\\p{ASCII}]");
|
||||
Logger.info( " Dispatcher thread has started!");
|
||||
|
||||
}
|
||||
|
||||
public static void send(Dispatch messageDispatch, DispatchChannel dispatchChannel) {
|
||||
|
||||
// Don't queue up empty dispatches!
|
||||
|
||||
if (messageDispatch.player == null)
|
||||
return;
|
||||
|
||||
_messageQueue[dispatchChannel.getChannelID()].add(messageDispatch);
|
||||
_blockingQueue.add(true);
|
||||
|
||||
// Update performance metrics
|
||||
|
||||
messageCount[dispatchChannel.getChannelID()]++;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
boolean shouldBlock;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
|
||||
shouldBlock = true;
|
||||
|
||||
for (DispatchChannel dispatchChannel : DispatchChannel.values()) {
|
||||
|
||||
this.messageDispatch = _messageQueue[dispatchChannel.getChannelID()].poll();
|
||||
|
||||
if (this.messageDispatch != null) {
|
||||
DispatchMessage.serializeDispatch(this.messageDispatch);
|
||||
shouldBlock = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (shouldBlock == true)
|
||||
shouldBlock = _blockingQueue.take();
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.error(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static String getNetstatString() {
|
||||
|
||||
String outString = null;
|
||||
String newLine = System.getProperty("line.separator");
|
||||
outString = "[LUA_NETSTA()]" + newLine;
|
||||
outString += "poolSize: " + itemPoolSize.longValue() + '\n';
|
||||
|
||||
for (DispatchChannel dispatchChannel : DispatchChannel.values()) {
|
||||
|
||||
outString += "Channel: " + dispatchChannel.name() + '\n';
|
||||
outString += "Dispatches: " + dispatchCount[dispatchChannel.getChannelID()].longValue()+ '\n';
|
||||
outString += "Messages: " + messageCount[dispatchChannel.getChannelID()] + '\n';
|
||||
outString += "maxRecipients: " + maxRecipients[dispatchChannel.getChannelID()] + '\n';
|
||||
}
|
||||
return outString;
|
||||
}
|
||||
|
||||
// For Debugging:
|
||||
//Logger.error("MessageDispatcher", messageDispatch.msg.getOpcodeAsString() + " sent to " + messageDispatch.playerList.size() + " players");
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.exception.FactoryBuildException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.Protocol;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.joda.time.DateTime;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class NetMsgFactory {
|
||||
|
||||
// NetMsg Opcode to Constructor List
|
||||
private static final HashMap<Integer, Constructor> netMsgDefinitions = new HashMap<>();
|
||||
|
||||
// Standardize the error strings
|
||||
private static String ALL_GOOD_JUST_NOT_ENOUGH_BYTES = "Not enough Bytes";
|
||||
private static String DESERIALIZATION_FAILURE = "Deserialization Failure";
|
||||
private static String UNIMPLEMENTED_OPCODE = "Unimplemented Opcode";
|
||||
private static String UNKNOWN_OPCODE = "Unknown Opcode";
|
||||
|
||||
protected ByteBuffer internalBuffer;
|
||||
private final ArrayList<AbstractNetMsg> msgOutbox;
|
||||
|
||||
private boolean enableFloodControl;
|
||||
private boolean bypassFloodControl; // temp bypass
|
||||
private boolean floodControlTripped;
|
||||
|
||||
private static final int FLOOD_CONTROL_TRIP_SETPOINT = 1000;
|
||||
private int badOpcodeCount;
|
||||
private final AbstractConnection owner;
|
||||
private int lastMsgPosition = 0;
|
||||
|
||||
public NetMsgFactory(AbstractConnection origin, boolean enableFloodControl) {
|
||||
this.internalBuffer = Network.byteBufferPool.getBuffer(18); //256k buffer
|
||||
|
||||
this.bypassFloodControl = false;
|
||||
this.msgOutbox = new ArrayList<>();
|
||||
this.enableFloodControl = enableFloodControl;
|
||||
this.floodControlTripped = false;
|
||||
this.owner = origin;
|
||||
}
|
||||
|
||||
public NetMsgFactory(AbstractConnection origin) {
|
||||
this(origin, true);
|
||||
}
|
||||
|
||||
public final void addData(byte[] ba) {
|
||||
// Dont use prefab BB's here, since sizeof(ba) is unknown.
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
bb.position(bb.capacity());
|
||||
this.addData(bb);
|
||||
}
|
||||
|
||||
public final void addData(ByteBuffer newData) {
|
||||
synchronized (this.internalBuffer) {
|
||||
|
||||
int newCapacity = this.internalBuffer.position() + newData.position();
|
||||
|
||||
if (newCapacity >= this.internalBuffer.capacity()) {
|
||||
//Resize!!!!
|
||||
Logger.warn(
|
||||
"Bytebuffer is being be Resized.");
|
||||
|
||||
//Get a newer, bigger BB
|
||||
ByteBuffer newBB = Network.byteBufferPool.getBufferToFit((int) (newCapacity * 1.5));
|
||||
|
||||
//Copy old data in
|
||||
this.internalBuffer.flip();
|
||||
newBB.put(this.internalBuffer);
|
||||
|
||||
//Get a handle on old BB
|
||||
ByteBuffer oldBB = this.internalBuffer;
|
||||
|
||||
//install new BB
|
||||
this.internalBuffer = newBB;
|
||||
|
||||
//Return old BB
|
||||
Network.byteBufferPool.putBuffer(oldBB);
|
||||
}
|
||||
|
||||
synchronized (newData) {
|
||||
// Copy over the data.
|
||||
newData.flip();
|
||||
|
||||
try {
|
||||
this.internalBuffer.put(newData);
|
||||
} catch (Exception e) {
|
||||
Logger.error( e.toString());
|
||||
// TODO figure out how to handle this error.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void parseBuffer() {
|
||||
// Check flood control first
|
||||
if (this.floodControlTripped)
|
||||
// this.conn.disconnect();
|
||||
return;
|
||||
|
||||
// MBServer.jobMan.submitJob(new ParseBufferJob(this));
|
||||
this._parseBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function makes a copy of the current internal byte buffer and loads
|
||||
* the copy into a ByteBufferReader. It is copied so that the Factory can
|
||||
* continue to accumulate data on the internal buffer from the
|
||||
* socketChannels. The ByteBufferReader is then used in an attempt to build
|
||||
* an AbstractNetMsg subclass based on protocolMsg. If a message is successfully
|
||||
* built, the bytes used are removed from the Factory's internal byte
|
||||
* buffer.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void _parseBuffer() {
|
||||
synchronized (this.internalBuffer) {
|
||||
while (this.internalBuffer.position() > 0) {
|
||||
// Check flood control first
|
||||
if (this.floodControlTripped)
|
||||
break;
|
||||
|
||||
ByteBufferReader reader = null;
|
||||
|
||||
// Check to see if the minimum amount of data is here:
|
||||
if (this.internalBuffer.position() < 4)
|
||||
// nothing wrong, just not enough info yet.
|
||||
break;
|
||||
|
||||
// copy internal buffer into a reader
|
||||
reader = new ByteBufferReader(this.internalBuffer, false);
|
||||
|
||||
// Reset the limit to the capacity
|
||||
this.internalBuffer.limit(this.internalBuffer.capacity());
|
||||
|
||||
try {
|
||||
AbstractNetMsg msg = this.tryBuild(owner, reader);
|
||||
|
||||
// error, null messages are being returned on unhandled
|
||||
// opcodes
|
||||
// for some reason
|
||||
if (msg == null)
|
||||
throw new FactoryBuildException(UNIMPLEMENTED_OPCODE);
|
||||
|
||||
|
||||
|
||||
if (owner.getClass().equals(ClientConnection.class)){
|
||||
ClientConnection client = (ClientConnection)owner;
|
||||
client.setLastOpcode(msg.getProtocolMsg().opcode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Logger.debug("Adding a " + msg.getSimpleClassName()
|
||||
// + " to the outbox.");
|
||||
this.addMsgToOutBox(msg);
|
||||
|
||||
this.dropLeadingBytesFromBuffer(reader.position());
|
||||
this.bypassFloodControl = false;
|
||||
|
||||
} catch (FactoryBuildException e) {
|
||||
String error = e.getMessage();
|
||||
int readerPos = reader.position();
|
||||
|
||||
if (error.equals(ALL_GOOD_JUST_NOT_ENOUGH_BYTES)){
|
||||
break;
|
||||
}
|
||||
// no worries, just break.
|
||||
|
||||
else if (error.equals(DESERIALIZATION_FAILURE)) {
|
||||
// Lop readerPos bytes off the buffer.
|
||||
this.dropLeadingBytesFromBuffer(readerPos);
|
||||
|
||||
// Lets bypass flood control for now.
|
||||
this.bypassFloodControl = true;
|
||||
continue;
|
||||
|
||||
} else if (error.equals(UNIMPLEMENTED_OPCODE)) {
|
||||
|
||||
if (owner.lastProtocol != null && owner.lastProtocol.constructor == null){
|
||||
this.dropLeadingBytesFromBuffer(readerPos);
|
||||
this.bypassFloodControl = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Lop readerPos bytes off the buffer.
|
||||
if (reader.position() >= 4)
|
||||
reader.position(reader.position() - 4);
|
||||
int newPosition = Protocol.FindNextValidOpcode(reader);
|
||||
this.dropLeadingBytesFromBuffer(newPosition);
|
||||
// Lets bypass flood control for now.
|
||||
this.bypassFloodControl = true;
|
||||
|
||||
continue;
|
||||
|
||||
} else if (error.equals(UNKNOWN_OPCODE)) {
|
||||
|
||||
if (owner.lastProtocol != null && owner.lastProtocol.constructor == null){
|
||||
this.dropLeadingBytesFromBuffer(readerPos);
|
||||
this.bypassFloodControl = true;
|
||||
continue;
|
||||
}
|
||||
// We don't know what this is or how long, so dump the
|
||||
// first
|
||||
// byte and try again
|
||||
if (reader.position() >= 4)
|
||||
reader.position(reader.position() - 4);
|
||||
int newPosition = Protocol.FindNextValidOpcode(reader);
|
||||
this.dropLeadingBytesFromBuffer(newPosition);
|
||||
// Lets bypass flood control for now.
|
||||
this.bypassFloodControl = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO FIX THIS!!!!
|
||||
// Logger.error( e);
|
||||
|
||||
}// end catch
|
||||
|
||||
} // end while loop
|
||||
}
|
||||
}// end fn
|
||||
|
||||
public AbstractNetMsg tryBuild(AbstractConnection origin,
|
||||
ByteBufferReader reader) throws FactoryBuildException {
|
||||
try {
|
||||
|
||||
// Get the protocolMsg
|
||||
int opcode = reader.getInt();
|
||||
// String ocHex = StringUtils.toHexString(protocolMsg);
|
||||
|
||||
if (MBServerStatics.PRINT_INCOMING_OPCODES)
|
||||
try {
|
||||
Logger.info( "Incoming protocolMsg: "
|
||||
+ Protocol.getByOpcode(opcode).name() + " " + Integer.toHexString(opcode) + ", size: " + reader.getBb().limit() + "; " + getByteArray(reader));
|
||||
} catch (Exception e) {
|
||||
Logger.error( e);
|
||||
}
|
||||
|
||||
return NetMsgFactory.getNewInstanceOf(opcode, origin, reader);
|
||||
|
||||
} catch (BufferUnderflowException e) {
|
||||
// This is okay. it indicates that we recognized the protocolMsg, but
|
||||
// there isn't enough information in
|
||||
// the reader to complete the NetMsg deserialization
|
||||
throw new FactoryBuildException(ALL_GOOD_JUST_NOT_ENOUGH_BYTES);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static String getByteArray(ByteBufferReader reader) {
|
||||
String ret = "";
|
||||
if (reader == null)
|
||||
return ret;
|
||||
|
||||
ByteBuffer bb = reader.getBb();
|
||||
if (bb == null)
|
||||
return ret;
|
||||
|
||||
int length = bb.limit(); // - bb.position();
|
||||
ByteBuffer temp = bb.duplicate();
|
||||
temp.position(bb.limit());
|
||||
temp.flip();
|
||||
for (int i = 0; i < length; i++) {
|
||||
ret += Integer.toString((temp.get() & 0xff) + 0x100, 16).substring(1).toUpperCase();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void incrBadOpcodeCount() {
|
||||
// keeping this a nested if for Troubleshooting/clarity
|
||||
if (this.enableFloodControl == true)
|
||||
if (this.bypassFloodControl == false) {
|
||||
++this.badOpcodeCount;
|
||||
|
||||
|
||||
|
||||
if (this.badOpcodeCount >= FLOOD_CONTROL_TRIP_SETPOINT){
|
||||
if (this.owner != null){
|
||||
if (this.owner instanceof ClientConnection){
|
||||
ClientConnection client = (ClientConnection) this.owner;
|
||||
if (client.getPlayerCharacter() != null){
|
||||
ChatManager.chatSystemError(client.getPlayerCharacter(),"TRIPPED Flood Control! PLEASE RELOG!");
|
||||
Logger.info( client.getPlayerCharacter().getName() + " Tripped Flood Control!" + this.badOpcodeCount);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
this.floodControlTripped = true;
|
||||
}else{
|
||||
if (this.owner != null){
|
||||
if (this.owner instanceof ClientConnection){
|
||||
ClientConnection client = (ClientConnection) this.owner;
|
||||
if (client.getPlayerCharacter() != null){
|
||||
ChatManager.chatSystemError(client.getPlayerCharacter(),"Client sending bad messages. bad message Count " + this.badOpcodeCount);
|
||||
Logger.info( client.getPlayerCharacter().getName() + " has been caught sending bad opcodes. Bad Opcode Count " + this.badOpcodeCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected final void dropLeadingBytesFromBuffer(int numberOfBytes) {
|
||||
this.internalBuffer.limit(this.internalBuffer.position());
|
||||
this.internalBuffer.position(numberOfBytes);
|
||||
this.internalBuffer.compact(); // Compact
|
||||
}
|
||||
|
||||
protected boolean addMsgToOutBox(AbstractNetMsg msg) {
|
||||
synchronized (this.msgOutbox) {
|
||||
return msgOutbox.add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractNetMsg getMsg() {
|
||||
synchronized (this.msgOutbox) {
|
||||
if (this.msgOutbox.isEmpty())
|
||||
return null;
|
||||
return msgOutbox.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasMsg() {
|
||||
synchronized (this.msgOutbox) {
|
||||
return !msgOutbox.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasData() {
|
||||
synchronized (this.internalBuffer) {
|
||||
return (this.internalBuffer.position() != 0);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static AbstractNetMsg getNewInstanceOf(int opcode,
|
||||
AbstractConnection origin, ByteBufferReader reader) {
|
||||
try {
|
||||
|
||||
Protocol protocolMsg = Protocol.getByOpcode(opcode);
|
||||
|
||||
if (protocolMsg == Protocol.NONE){
|
||||
|
||||
String errorString = DateTime.now().toString() + origin.lastProtocol.name();
|
||||
|
||||
int errorCode = errorString.hashCode();
|
||||
|
||||
|
||||
if (origin instanceof ClientConnection){
|
||||
PlayerCharacter player = ((ClientConnection)origin).getPlayerCharacter();
|
||||
if (player != null){
|
||||
// if (MBServerStatics.worldServerName.equals("Grief"))
|
||||
Logger.error("Invalid protocol msg for player " + player.getFirstName() + " : " + opcode + " lastopcode: " + origin.lastProtocol.name() + " Error Code : " + errorCode);
|
||||
}else
|
||||
Logger.error("Invalid protocol msg : " + opcode + " lastopcode: " + origin.lastProtocol.name() + " Error Code : " + errorCode);
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
origin.lastProtocol = protocolMsg;
|
||||
|
||||
if (protocolMsg.constructor == null){
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Constructor<AbstractNetMsg> constructor = protocolMsg.constructor;
|
||||
|
||||
if (constructor == null)
|
||||
return null;
|
||||
|
||||
Object[] myArgs = new Object[2];
|
||||
myArgs[0] = origin;
|
||||
myArgs[1] = reader;
|
||||
|
||||
Object object = constructor.newInstance(myArgs);
|
||||
|
||||
if (object instanceof engine.net.AbstractNetMsg)
|
||||
return (AbstractNetMsg) object;
|
||||
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InstantiationException | ExceptionInInitializerError e) {
|
||||
Logger.error( e);
|
||||
|
||||
} catch (InvocationTargetException e) {
|
||||
if (e.getCause() != null
|
||||
&& e.getCause().getClass() == BufferUnderflowException.class)
|
||||
throw new BufferUnderflowException();
|
||||
Logger.error(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ByteBuffer getInternalBuffer() {
|
||||
return internalBuffer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
|
||||
public interface NetMsgHandler {
|
||||
|
||||
public abstract boolean handleClientMsg(ClientNetMsg msg);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.net.client.Protocol;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class NetMsgStat {
|
||||
|
||||
private final Protocol protocolMsg;
|
||||
private final AtomicLong total = new AtomicLong();
|
||||
private final AtomicLong count = new AtomicLong();
|
||||
private final AtomicInteger average = new AtomicInteger();
|
||||
private final AtomicInteger max = new AtomicInteger();
|
||||
private final AtomicInteger countUnderAverage = new AtomicInteger();
|
||||
private final AtomicInteger countOverAverage = new AtomicInteger();
|
||||
private final AtomicInteger countOverMax = new AtomicInteger();
|
||||
|
||||
public NetMsgStat(Protocol protocolMsg, int startSize) {
|
||||
|
||||
if (startSize < 10)
|
||||
startSize = 10;
|
||||
|
||||
if (startSize > 30)
|
||||
startSize = 30;
|
||||
|
||||
this.protocolMsg = protocolMsg;
|
||||
this.total.set(startSize);
|
||||
this.count.set(1L);
|
||||
this.average.set(10);
|
||||
this.max.set(startSize);
|
||||
this.countUnderAverage.set(0);
|
||||
this.countOverAverage.set(0);
|
||||
this.countOverMax.set(0);
|
||||
}
|
||||
|
||||
public void updateStat(int i) {
|
||||
this.total.addAndGet(i);
|
||||
this.count.incrementAndGet();
|
||||
|
||||
int avg = (int) (this.total.get() / this.count.get());
|
||||
if (avg < 0)
|
||||
avg = 0;
|
||||
else if (avg > 30)
|
||||
avg = 30;
|
||||
else
|
||||
this.average.set(avg);
|
||||
|
||||
if (this.max.get() < i)
|
||||
this.max.set(i);
|
||||
|
||||
if (i <= avg)
|
||||
this.countUnderAverage.incrementAndGet();
|
||||
else if (i < this.max.get())
|
||||
this.countOverAverage.incrementAndGet();
|
||||
else
|
||||
this.countOverMax.incrementAndGet();
|
||||
}
|
||||
|
||||
public Protocol getOpcode() {
|
||||
return this.protocolMsg;
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return this.max.get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net;
|
||||
|
||||
import engine.pooling.MultisizeByteBufferPool;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class Network {
|
||||
|
||||
public static final int INITIAL_SOCKET_BUFFER_SIZE = 128 * 1024;
|
||||
public static final int INITIAL_BYTEBUFFER_POOL_SIZE = 256;
|
||||
|
||||
public static final MultisizeByteBufferPool byteBufferPool = new MultisizeByteBufferPool();
|
||||
|
||||
public static void init() {
|
||||
//Force a few to be created.
|
||||
|
||||
//Small (2^10-15)
|
||||
for (int a = 10; a < 16; ++a) {
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
byteBufferPool.putBuffer(ByteBuffer.allocateDirect(MultisizeByteBufferPool.powersOfTwo[a]));
|
||||
}
|
||||
}
|
||||
|
||||
//standard size (2^16)
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
byteBufferPool.putBuffer(ByteBuffer.allocateDirect(MultisizeByteBufferPool.powersOfTwo[16]));
|
||||
}
|
||||
|
||||
//Large (2^17)
|
||||
for (int i = 0; i < 50; ++i) {
|
||||
byteBufferPool.putBuffer(ByteBuffer.allocateDirect(MultisizeByteBufferPool.powersOfTwo[17]));
|
||||
}
|
||||
|
||||
// NetMsgFactory size (2^18)
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
byteBufferPool.putBuffer(ByteBuffer
|
||||
.allocateDirect(MultisizeByteBufferPool.powersOfTwo[18]));
|
||||
}
|
||||
|
||||
//Very Large (2^19)
|
||||
for (int i = 0; i < 25; ++i) {
|
||||
byteBufferPool.putBuffer(ByteBuffer.allocateDirect(MultisizeByteBufferPool.powersOfTwo[19]));
|
||||
}
|
||||
|
||||
//Very Large (2^20)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
byteBufferPool.putBuffer(ByteBuffer.allocateDirect(MultisizeByteBufferPool.powersOfTwo[20]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client;
|
||||
|
||||
import engine.net.AbstractConnection;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.util.ByteUtils;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyAgreement;
|
||||
import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.interfaces.DHPublicKey;
|
||||
import javax.crypto.spec.DHParameterSpec;
|
||||
import javax.crypto.spec.DHPublicKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.*;
|
||||
|
||||
public class ClientAuthenticator {
|
||||
|
||||
private final AbstractConnection origin;
|
||||
|
||||
private ByteBuffer buffer = ByteBuffer.allocate(100);
|
||||
private byte[] secretKeyBytes = new byte[16];
|
||||
private SecretKeySpec BFKey;
|
||||
|
||||
private Cipher cipher;
|
||||
private byte[] iVecEnc = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
private byte[] iVecDec = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
private int iVecEncOffset = 0;
|
||||
private int iVecDecOffset = 0;
|
||||
private int totalRead = 0;
|
||||
private KeyFactory keyFactory;
|
||||
private DHParameterSpec dhParamSpec;
|
||||
private KeyPairGenerator keyPairGen;
|
||||
private KeyAgreement keyAgree;
|
||||
private boolean initialized = false;
|
||||
private boolean keyInit = false;
|
||||
private byte[] secretKey;
|
||||
private byte[] serverPublicKey;
|
||||
|
||||
public ClientAuthenticator(AbstractConnection origin) {
|
||||
super();
|
||||
this.origin = origin;
|
||||
try {
|
||||
// init the resuable Crypto Stuff.
|
||||
this.keyFactory = KeyFactory.getInstance("DH");
|
||||
this.dhParamSpec = new DHParameterSpec(ClientAuthenticator.P, ClientAuthenticator.G);
|
||||
|
||||
this.keyPairGen = KeyPairGenerator.getInstance("DH");
|
||||
this.keyPairGen.initialize(this.dhParamSpec);
|
||||
this.keyAgree = KeyAgreement.getInstance("DH");
|
||||
|
||||
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
|
||||
Logger.error("NoSuchAlgorithmException " + e.getMessage());
|
||||
this.keyInit = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.keyInit = true;
|
||||
}
|
||||
|
||||
private void calcKeys(AbstractConnection origin, byte[] clientPublicKeyBytes) {
|
||||
|
||||
try {
|
||||
// get the forwarded client public key, in byte[] form.
|
||||
|
||||
// Convert client public key to a BigInteger
|
||||
BigInteger clientPublicKeyBI = new BigInteger(1, clientPublicKeyBytes);
|
||||
|
||||
// convert the client's Public Key to a DHPublicKey object
|
||||
DHPublicKeySpec dhKeySpec = new DHPublicKeySpec(clientPublicKeyBI, ClientAuthenticator.P, ClientAuthenticator.G);
|
||||
DHPublicKey clientPublicKey = (DHPublicKey) this.keyFactory.generatePublic(dhKeySpec);
|
||||
|
||||
// Now calculate the server's PublicKey
|
||||
byte[] serverPublicKeyBytes = new byte[96];
|
||||
boolean invalid = true;
|
||||
|
||||
int tryCnt = 1;
|
||||
while (invalid) {
|
||||
KeyPair keyPair = keyPairGen.generateKeyPair();
|
||||
this.keyAgree = KeyAgreement.getInstance("DH");
|
||||
this.keyAgree.init(keyPair.getPrivate());
|
||||
DHPublicKey serverPublicKey = (DHPublicKey) keyPair.getPublic();
|
||||
|
||||
String hex = serverPublicKey.getY().toString(16);
|
||||
|
||||
if (hex.length() == 192) {
|
||||
invalid = false;
|
||||
serverPublicKeyBytes = ByteUtils.stringHexToByteArray(hex);
|
||||
}
|
||||
if (tryCnt >= 5)
|
||||
// Give java 4 tries to get a Public key of valid length.
|
||||
throw new Exception("Not able to generate a valid length public key");
|
||||
++tryCnt;
|
||||
}
|
||||
|
||||
// Calculate shared DH Secret Key
|
||||
keyAgree.doPhase(clientPublicKey, true);
|
||||
this.secretKey = keyAgree.generateSecret();
|
||||
this.serverPublicKey = serverPublicKeyBytes;
|
||||
|
||||
// Now we have the server's publicKey and the common secretKey
|
||||
} catch (Exception e) {
|
||||
origin.disconnect();
|
||||
Logger.error(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public synchronized int initialize(AbstractConnection origin) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
int read = -1;
|
||||
|
||||
// Read the data from connections socket channel
|
||||
try {
|
||||
read = origin.getSocketChannel().read(this.buffer);
|
||||
} catch (IOException e) {
|
||||
if (e.getLocalizedMessage() != null && !e.getLocalizedMessage().equals(MBServerStatics.EXISTING_CONNECTION_CLOSED) && !e.getLocalizedMessage().equals(MBServerStatics.RESET_BY_PEER))
|
||||
Logger.error(e);
|
||||
origin.disconnect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (read == -1) {
|
||||
Logger.info("EOF on Socket Channel, Disconnecting " + origin.getLocalAddressAndPortAsString());
|
||||
origin.disconnect();
|
||||
return read;
|
||||
}
|
||||
|
||||
this.totalRead += read;
|
||||
|
||||
if (this.totalRead > 100)
|
||||
Logger.error( "Possible Spam warning: "
|
||||
+ origin.getSocketChannel().socket().toString());
|
||||
|
||||
// Not all arrived yet, so wait for more
|
||||
if (this.totalRead < 100)
|
||||
return read;
|
||||
|
||||
this.buffer.flip();
|
||||
this.buffer.getInt(); // get the length first & throw away value.
|
||||
|
||||
byte[] PeerPubKeyEnc = new byte[96];
|
||||
this.buffer.get(PeerPubKeyEnc);
|
||||
|
||||
this.calcKeys(origin, PeerPubKeyEnc);
|
||||
|
||||
try {
|
||||
byte[] sharedSecret = this.secretKey;
|
||||
byte[] PubKeyEnc = this.serverPublicKey;
|
||||
|
||||
// Cut DH SecretKey down to 16 bytes
|
||||
System.arraycopy(sharedSecret, 0, secretKeyBytes, 0, 16);
|
||||
|
||||
// Calculate Blowfish Secret Key and make ciphers streams.
|
||||
this.BFKey = new SecretKeySpec(this.secretKeyBytes, "Blowfish");
|
||||
|
||||
// Initialize cipher and Ivecs.
|
||||
// Ivecs must be run through the cipher once
|
||||
// to prep the cipher for cfb mode.
|
||||
this.cipher = Cipher.getInstance("Blowfish/ECB/NoPadding");
|
||||
this.cipher.init(Cipher.ENCRYPT_MODE, this.BFKey);
|
||||
this.cipher.update(this.iVecEnc, 0, 8, this.iVecEnc, 0);
|
||||
this.cipher.update(this.iVecDec, 0, 8, this.iVecDec, 0);
|
||||
|
||||
// Send public key to peer
|
||||
byte[] pubKeyLen = {0x00, 0x00, 0x00, 0x60}; // hex for 96
|
||||
ByteBuffer bb = ByteBuffer.wrap(pubKeyLen);
|
||||
bb.position(bb.limit());
|
||||
origin.sendBB(bb);
|
||||
bb = ByteBuffer.wrap(PubKeyEnc);
|
||||
bb.position(bb.limit());
|
||||
origin.sendBB(bb);
|
||||
} catch (Exception e) {
|
||||
Logger.error(e);
|
||||
origin.disconnect();
|
||||
return read;
|
||||
}
|
||||
/*
|
||||
* //Send Secret Key to Login Server if (PortalServer.ServerType ==
|
||||
* "Login") { byte[] keyinfo = new byte[20]; keyinfo[0] = 0x11;
|
||||
* keyinfo[1] = 0x11; keyinfo[2] = 0x11; keyinfo[3] = 0x11; for (int i =
|
||||
* 0; i < 16; i++) keyinfo[i + 4] = ShortSharedSecret[i];
|
||||
* PortalPair.HandleOutput(keyinfo, 20); }
|
||||
*/
|
||||
this.initialized = true;
|
||||
|
||||
// long endTime = System.currentTimeMillis();
|
||||
//
|
||||
// long time = endTime - startTime;
|
||||
// // Logger.debug("", "Authenticator took " + time + " ms to initialize.");
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
public synchronized void encrypt(final ByteBuffer dataIn, final ByteBuffer dataOut) {
|
||||
try {
|
||||
// Assume that if position != 0 that we need to flip.
|
||||
if (dataIn.position() != 0)
|
||||
dataIn.flip();
|
||||
|
||||
int count = dataIn.limit();
|
||||
|
||||
//Line up the iVecEncOffset.. fall through is intentional
|
||||
if (iVecEncOffset != 0)
|
||||
if ((this.iVecEncOffset + dataIn.limit()) < 8) {
|
||||
//This handles cases where the net msg + offset won't reach 8 bytes total
|
||||
//prevents BufferUnderflowException in small net messages. -
|
||||
int newEncOffset = this.iVecEncOffset + dataIn.limit();
|
||||
for (int i = this.iVecEncOffset; i < newEncOffset; i++) {
|
||||
this.iVecEnc[i] = (byte) (dataIn.get() ^ this.iVecEnc[i]);
|
||||
dataOut.put(this.iVecEnc[i]);
|
||||
}
|
||||
this.iVecEncOffset = newEncOffset;
|
||||
return;
|
||||
} else
|
||||
switch (iVecEncOffset) {
|
||||
case 1:
|
||||
this.iVecEnc[1] = (byte) (dataIn.get() ^ this.iVecEnc[1]);
|
||||
dataOut.put(this.iVecEnc[1]);
|
||||
case 2:
|
||||
this.iVecEnc[2] = (byte) (dataIn.get() ^ this.iVecEnc[2]);
|
||||
dataOut.put(this.iVecEnc[2]);
|
||||
case 3:
|
||||
this.iVecEnc[3] = (byte) (dataIn.get() ^ this.iVecEnc[3]);
|
||||
dataOut.put(this.iVecEnc[3]);
|
||||
case 4:
|
||||
this.iVecEnc[4] = (byte) (dataIn.get() ^ this.iVecEnc[4]);
|
||||
dataOut.put(this.iVecEnc[4]);
|
||||
case 5:
|
||||
this.iVecEnc[5] = (byte) (dataIn.get() ^ this.iVecEnc[5]);
|
||||
dataOut.put(this.iVecEnc[5]);
|
||||
case 6:
|
||||
this.iVecEnc[6] = (byte) (dataIn.get() ^ this.iVecEnc[6]);
|
||||
dataOut.put(this.iVecEnc[6]);
|
||||
case 7:
|
||||
this.iVecEnc[7] = (byte) (dataIn.get() ^ this.iVecEnc[7]);
|
||||
dataOut.put(this.iVecEnc[7]);
|
||||
count -= (8 - iVecEncOffset);
|
||||
this.iVecEncOffset = 0;
|
||||
this.cipher.update(this.iVecEnc, 0, 8, this.iVecEnc, 0);
|
||||
}
|
||||
|
||||
//Main loop - unrolled x8
|
||||
int loopCount = (count) >> 3;
|
||||
for (int i = 0; i < loopCount; i++) {
|
||||
|
||||
this.iVecEnc[0] = (byte) (dataIn.get() ^ this.iVecEnc[0]);
|
||||
this.iVecEnc[1] = (byte) (dataIn.get() ^ this.iVecEnc[1]);
|
||||
this.iVecEnc[2] = (byte) (dataIn.get() ^ this.iVecEnc[2]);
|
||||
this.iVecEnc[3] = (byte) (dataIn.get() ^ this.iVecEnc[3]);
|
||||
this.iVecEnc[4] = (byte) (dataIn.get() ^ this.iVecEnc[4]);
|
||||
this.iVecEnc[5] = (byte) (dataIn.get() ^ this.iVecEnc[5]);
|
||||
this.iVecEnc[6] = (byte) (dataIn.get() ^ this.iVecEnc[6]);
|
||||
this.iVecEnc[7] = (byte) (dataIn.get() ^ this.iVecEnc[7]);
|
||||
|
||||
dataOut.put(this.iVecEnc[0]);
|
||||
dataOut.put(this.iVecEnc[1]);
|
||||
dataOut.put(this.iVecEnc[2]);
|
||||
dataOut.put(this.iVecEnc[3]);
|
||||
dataOut.put(this.iVecEnc[4]);
|
||||
dataOut.put(this.iVecEnc[5]);
|
||||
dataOut.put(this.iVecEnc[6]);
|
||||
dataOut.put(this.iVecEnc[7]);
|
||||
this.cipher.update(this.iVecEnc, 0, 8, this.iVecEnc, 0);
|
||||
}
|
||||
|
||||
//Resync the iVecEncOffset to handle the remainder..
|
||||
this.iVecEncOffset = count % 8;
|
||||
for (int i = 0; i < iVecEncOffset; i++) {
|
||||
this.iVecEnc[i] = (byte) (dataIn.get() ^ this.iVecEnc[i]);
|
||||
dataOut.put(this.iVecEnc[i]);
|
||||
}
|
||||
} catch (BufferUnderflowException e) {
|
||||
if (dataIn != null && dataOut != null)
|
||||
Logger.warn("Encrypt Error: (in)" + dataIn.toString() + " :: (out)" + dataOut.toString());
|
||||
Logger.error("ClientAuth.encrypt() -> Underflow" + e);
|
||||
} catch (BufferOverflowException e) {
|
||||
if (dataIn != null && dataOut != null)
|
||||
Logger.warn("Encrypt Error: (in)" + dataIn.toString() + " :: (out)" + dataOut.toString());
|
||||
Logger.error("ClientAuth.encrypt() -> Overflow" + e);
|
||||
} catch (Exception e) {
|
||||
Logger.error("ClientAuth.encrypt()" + e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void decrypt(ByteBuffer dataIn, ByteBuffer dataOut) {
|
||||
try { // get lock
|
||||
synchronized (dataIn) { // TODO is this lock needed?
|
||||
|
||||
// Assume that if position != 0 that we need to flip.
|
||||
if (dataIn.position() != 0)
|
||||
dataIn.flip();
|
||||
|
||||
byte encryptedByte;
|
||||
byte decryptedByte;
|
||||
|
||||
for (int i = 0; i < dataIn.limit(); ++i) {
|
||||
|
||||
// Get byte out of ByteBuffer
|
||||
encryptedByte = dataIn.get();
|
||||
|
||||
// XOR it against the iVEC
|
||||
decryptedByte = (byte) (encryptedByte ^ this.iVecDec[this.iVecDecOffset]);
|
||||
|
||||
// put the decrypted byte into the outgoing ByteBuffer
|
||||
dataOut.put(decryptedByte);
|
||||
|
||||
// store the encrypted byte back into the iVEC
|
||||
this.iVecDec[this.iVecDecOffset] = encryptedByte;
|
||||
|
||||
// Increment ivecOffset
|
||||
this.iVecDecOffset++;
|
||||
|
||||
// Check to see if iVecOffset is at MAX. If so, reset
|
||||
if (this.iVecDecOffset > 7) {
|
||||
try {
|
||||
this.cipher.update(this.iVecDec, 0, 8,
|
||||
this.iVecDec, 0);
|
||||
} catch (ShortBufferException e) {
|
||||
// suck up this error
|
||||
Logger.error(e);
|
||||
}
|
||||
this.iVecDecOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.error("ClientAuth.decrypt()" + e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initiateKey(byte[] clientPublicKeyBytes) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the secretKeyBytes
|
||||
*/
|
||||
public byte[] getSecretKeyBytes() {
|
||||
return secretKeyBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the initialized
|
||||
*/
|
||||
public boolean initialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
private static final byte P_Bytes[] = {(byte) 0xFB, (byte) 0x46, (byte) 0x56, (byte) 0xB4, (byte) 0xBE, (byte) 0x81, (byte) 0xA4,
|
||||
(byte) 0x2C, (byte) 0x37, (byte) 0xC4, (byte) 0xA2, (byte) 0x61, (byte) 0x4A, (byte) 0xAC, (byte) 0x65, (byte) 0x90,
|
||||
(byte) 0x31, (byte) 0xB6, (byte) 0x83, (byte) 0x26, (byte) 0x63, (byte) 0x94, (byte) 0x08, (byte) 0x95, (byte) 0x56,
|
||||
(byte) 0x8D, (byte) 0x5E, (byte) 0xBF, (byte) 0x94, (byte) 0x10, (byte) 0x5A, (byte) 0x37, (byte) 0xB6, (byte) 0x82,
|
||||
(byte) 0x1A, (byte) 0x75, (byte) 0x2B, (byte) 0xF1, (byte) 0x94, (byte) 0xB7, (byte) 0x7E, (byte) 0x56, (byte) 0xC6,
|
||||
(byte) 0xD1, (byte) 0xF5, (byte) 0x18, (byte) 0xE1, (byte) 0xA5, (byte) 0x13, (byte) 0x9E, (byte) 0xC1, (byte) 0x85,
|
||||
(byte) 0x98, (byte) 0xB7, (byte) 0x32, (byte) 0xDB, (byte) 0x38, (byte) 0x09, (byte) 0x1A, (byte) 0xF8, (byte) 0x5C,
|
||||
(byte) 0xDA, (byte) 0x4F, (byte) 0x9F, (byte) 0x67, (byte) 0x93, (byte) 0x72, (byte) 0x8F, (byte) 0x75, (byte) 0x4F,
|
||||
(byte) 0x0B, (byte) 0xBD, (byte) 0x69, (byte) 0x61, (byte) 0x97, (byte) 0x1F, (byte) 0xEE, (byte) 0xFB, (byte) 0x5B,
|
||||
(byte) 0xB0, (byte) 0x85, (byte) 0xC4, (byte) 0x27, (byte) 0x7E, (byte) 0x41, (byte) 0x42, (byte) 0xC2, (byte) 0xF1,
|
||||
(byte) 0xDA, (byte) 0x64, (byte) 0x8F, (byte) 0x4E, (byte) 0x28, (byte) 0xFD, (byte) 0x2A, (byte) 0x63};
|
||||
|
||||
private static final BigInteger P = new BigInteger(1, P_Bytes);
|
||||
private static final BigInteger G = BigInteger.valueOf(5);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,354 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.net.client;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.gameManager.ConfigManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.job.JobScheduler;
|
||||
import engine.jobs.DisconnectJob;
|
||||
import engine.net.AbstractConnection;
|
||||
import engine.net.AbstractNetMsg;
|
||||
import engine.net.Network;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.login.LoginErrorMsg;
|
||||
import engine.objects.Account;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.session.SessionID;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ClientConnection extends AbstractConnection {
|
||||
|
||||
// Enumeration of a message's origin for logging purposes
|
||||
private enum MessageSource {
|
||||
|
||||
SOURCE_CLIENT,
|
||||
SOURCE_SERVER
|
||||
}
|
||||
|
||||
private byte cryptoInitTries = 0;
|
||||
protected SessionID sessionID = null;
|
||||
private final ClientAuthenticator crypto;
|
||||
private final String clientIpAddress;
|
||||
public String machineID;
|
||||
public long guildtreespam = 0;
|
||||
public long ordernpcspam = 0;
|
||||
public ReentrantLock trainLock = new ReentrantLock();
|
||||
public ReentrantLock sellLock = new ReentrantLock();
|
||||
public ReentrantLock buyLock = new ReentrantLock();
|
||||
|
||||
public boolean desyncDebug = false;
|
||||
|
||||
public byte[] lastByteBuffer;
|
||||
|
||||
public ClientConnection(ClientConnectionManager connMan,
|
||||
SocketChannel sockChan) {
|
||||
super(connMan, sockChan, true);
|
||||
this.crypto = new ClientAuthenticator(this);
|
||||
|
||||
this.clientIpAddress = sockChan.socket().getRemoteSocketAddress()
|
||||
.toString().replace("/", "").split(":")[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _sendMsg(AbstractNetMsg msg) {
|
||||
try {
|
||||
msg.setOrigin(this);
|
||||
ByteBuffer bb = msg.serialize();
|
||||
|
||||
// Application protocol logging toggled via
|
||||
// DevCmd: netdebug on|off
|
||||
|
||||
if (MBServerStatics.DEBUG_PROTOCOL)
|
||||
applicationProtocolLogger(msg, MessageSource.SOURCE_SERVER);
|
||||
|
||||
boolean retval = this.sendBB(bb);
|
||||
Network.byteBufferPool.putBuffer(bb);//return here.
|
||||
|
||||
return retval;
|
||||
|
||||
} catch (Exception e) { // Catch-all
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sending a NetMsg to the client involves NOT including a dataLen parameter
|
||||
* and also involves encrypting the data.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected boolean _sendBB(ByteBuffer bb) {
|
||||
boolean useCrypto = this.crypto.initialized();
|
||||
boolean retVal;
|
||||
|
||||
// Logger.debug("useCrypto: " + useCrypto + ". bb.cap(): " +
|
||||
// bb.capacity());
|
||||
if (useCrypto == false)
|
||||
retVal = super._sendBB(bb);
|
||||
else {
|
||||
if (bb == null)
|
||||
Logger.error("Incoming bb is null");
|
||||
ByteBuffer encrypted = Network.byteBufferPool.getBufferToFit(bb.capacity());
|
||||
if (encrypted == null)
|
||||
Logger.error("Encrypted bb is null");
|
||||
this.crypto.encrypt(bb, encrypted);
|
||||
retVal = super._sendBB(encrypted);
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receiving data from a client involves the initial Crypto Key Exchange,
|
||||
* waiting for a complete NetMsg to arrive using an accumulation factory and
|
||||
* decrypting the data.
|
||||
*/
|
||||
//FIXME the int return value on this means nothing! Clean it up!
|
||||
@Override
|
||||
protected int read() {
|
||||
|
||||
if (readLock.tryLock())
|
||||
try {
|
||||
|
||||
// First and foremost, check to see if we the Crypto is initted yet
|
||||
if (!this.crypto.initialized())
|
||||
this.crypto.initialize(this);
|
||||
|
||||
if (!this.crypto.initialized()) {
|
||||
++this.cryptoInitTries;
|
||||
if (this.cryptoInitTries >= MBServerStatics.MAX_CRYPTO_INIT_TRIES) {
|
||||
Logger.info("Failed to initialize after "
|
||||
+ MBServerStatics.MAX_CRYPTO_INIT_TRIES
|
||||
+ " tries. Disconnecting.");
|
||||
this.disconnect();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check to see if SessionID == null;
|
||||
if (this.sessionID == null)
|
||||
this.sessionID = new SessionID(this.crypto.getSecretKeyBytes());
|
||||
|
||||
// Get ByteBuffers out of pool.
|
||||
ByteBuffer bb = Network.byteBufferPool.getBuffer(16);
|
||||
ByteBuffer decrypted = Network.byteBufferPool.getBuffer(16);
|
||||
// ByteBuffer bb = ByteBuffer.allocate(1024 * 4);
|
||||
|
||||
int totalBytesRead = 0;
|
||||
int lastRead = 0;
|
||||
do {
|
||||
try {
|
||||
bb.clear();
|
||||
decrypted.clear();
|
||||
lastRead = this.sockChan.read(bb);
|
||||
// On EOF on the SocketChannel, disconnect.
|
||||
if (lastRead <= -1) {
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
|
||||
if (lastRead == 0)
|
||||
continue;
|
||||
|
||||
// ByteBuffer decrypted = ByteBuffer.allocate(lastRead);
|
||||
this.crypto.decrypt(bb, decrypted);
|
||||
this.factory.addData(decrypted);
|
||||
|
||||
|
||||
this.checkInternalFactory();
|
||||
|
||||
totalBytesRead += lastRead;
|
||||
|
||||
|
||||
} catch (NotYetConnectedException e) {
|
||||
Logger.error(e.getLocalizedMessage());
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
|
||||
} catch (ClosedChannelException e) {
|
||||
// TODO Should a closed channel be logged or just cleaned up?
|
||||
// this.logEXCEPTION(e);
|
||||
this.disconnect();
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
|
||||
} catch (IOException e) {
|
||||
if ( e.getLocalizedMessage() != null && (!e.getLocalizedMessage().equals(MBServerStatics.EXISTING_CONNECTION_CLOSED) && !e.getLocalizedMessage().equals(MBServerStatics.RESET_BY_PEER))){
|
||||
Logger.info("Error Reading message opcode " + this.lastOpcode);
|
||||
Logger.error(e);
|
||||
}
|
||||
this.disconnect();
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
break;
|
||||
|
||||
} catch (Exception e){
|
||||
Logger.info("Error Reading message opcode " + this.lastOpcode);
|
||||
Logger.error(e);
|
||||
totalBytesRead = -1; // Set error retVal
|
||||
this.disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (lastRead > 0);
|
||||
|
||||
Network.byteBufferPool.putBuffer(bb);
|
||||
Network.byteBufferPool.putBuffer(decrypted);
|
||||
|
||||
return totalBytesRead;
|
||||
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
else {
|
||||
Logger.debug("Another thread already has a read lock! Skipping.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
super.disconnect();
|
||||
try {
|
||||
|
||||
if (ConfigManager.serverType.equals(Enum.ServerType.WORLDSERVER))
|
||||
ConfigManager.worldServer.removeClient(this);
|
||||
else
|
||||
ConfigManager.loginServer.removeClient(this);
|
||||
|
||||
// TODO There has to be a more direct way to do this...
|
||||
SessionManager.remSession(
|
||||
SessionManager.getSession(sessionID));
|
||||
} catch (NullPointerException e) {
|
||||
Logger
|
||||
.error(
|
||||
"Tried to remove improperly initialized session. Skipping." +
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
public void forceDisconnect() {
|
||||
super.disconnect();
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters n setters
|
||||
*/
|
||||
|
||||
public SessionID getSessionID() {
|
||||
return sessionID;
|
||||
}
|
||||
|
||||
public byte[] getSecretKeyBytes() {
|
||||
return this.crypto.getSecretKeyBytes();
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience getters for SessionManager
|
||||
*/
|
||||
public Account getAccount() {
|
||||
return SessionManager.getAccount(this);
|
||||
}
|
||||
|
||||
public PlayerCharacter getPlayerCharacter() {
|
||||
return SessionManager.getPlayerCharacter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClientMsg(ClientNetMsg msg) {
|
||||
|
||||
Protocol protocolMsg = msg.getProtocolMsg();
|
||||
|
||||
switch (protocolMsg) {
|
||||
case KEEPALIVESERVERCLIENT:
|
||||
this.setLastKeepAliveTime();
|
||||
break;
|
||||
// case ClientOpcodes.OpenVault:
|
||||
// case ClientOpcodes.Random:
|
||||
// case ClientOpcodes.DoorTryOpen:
|
||||
// case ClientOpcodes.SetSelectedObect:
|
||||
// case ClientOpcodes.MoveObjectToContainer:
|
||||
// case ClientOpcodes.ToggleSitStand:
|
||||
// case ClientOpcodes.SocialChannel:
|
||||
// case ClientOpcodes.OpenFriendsCondemnList:
|
||||
case SELLOBJECT:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
case MOVETOPOINT:
|
||||
case ARCCOMBATMODEATTACKING:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
default:
|
||||
this.setLastMsgTime();
|
||||
break;
|
||||
}
|
||||
|
||||
// Application protocol logging toggled via
|
||||
// DevCmd: netdebug on|off
|
||||
|
||||
if (MBServerStatics.DEBUG_PROTOCOL)
|
||||
applicationProtocolLogger(msg, MessageSource.SOURCE_CLIENT);
|
||||
|
||||
return ConfigManager.handler.handleClientMsg(msg); // *** Refactor : Null check then call
|
||||
}
|
||||
// Method logs detailed information about application
|
||||
// protocol traffic. Toggled at runtime via the
|
||||
// DevCmd netdebug on|off
|
||||
|
||||
private void applicationProtocolLogger(AbstractNetMsg msg, MessageSource origin) {
|
||||
|
||||
String outString = "";
|
||||
PlayerCharacter tempPlayer = null;
|
||||
|
||||
// Log the protocolMsg
|
||||
if (origin == MessageSource.SOURCE_CLIENT)
|
||||
outString = " Incoming protocolMsg: ";
|
||||
else
|
||||
outString = " Outgoing protocolMsg: ";
|
||||
|
||||
Logger.info(outString
|
||||
+ Integer.toHexString(msg.getProtocolMsg().opcode)
|
||||
+ '/' + msg.getProtocolMsg());
|
||||
|
||||
// Dump message contents using reflection
|
||||
tempPlayer = this.getPlayerCharacter();
|
||||
outString = "";
|
||||
outString += (tempPlayer == null) ? "PlayerUnknown" : tempPlayer.getFirstName() + ' '
|
||||
+ msg.toString();
|
||||
Logger.info(outString);
|
||||
}
|
||||
|
||||
public void kickToLogin(int errCode, String message) {
|
||||
|
||||
LoginErrorMsg lom = new LoginErrorMsg(errCode, message);
|
||||
|
||||
if (!sendMsg(lom))
|
||||
Logger.error("Failed to send message"); // TODO Do we just accept this failure to send Msg?
|
||||
|
||||
DisconnectJob dj = new DisconnectJob(this);
|
||||
JobScheduler.getInstance().scheduleJob(dj, 250);
|
||||
|
||||
}
|
||||
|
||||
public final String getClientIpAddress() {
|
||||
return this.clientIpAddress;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client;
|
||||
|
||||
import engine.net.AbstractConnection;
|
||||
import engine.net.AbstractConnectionManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
public class ClientConnectionManager extends AbstractConnectionManager {
|
||||
|
||||
public ClientConnectionManager(String threadName, InetAddress hostAddress, int port)
|
||||
throws IOException {
|
||||
super(threadName, hostAddress, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractConnection getNewIncomingConnection(SocketChannel sockChan) {
|
||||
return new ClientConnection(this, sockChan);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractConnection getNewOutgoingConnection(SocketChannel sockChan) {
|
||||
return new ClientConnection(this, sockChan);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,338 @@
|
||||
package engine.net.client;
|
||||
|
||||
/* This class defines Magicbane's application network protocol.
|
||||
--> Name / Opcode / Message / Handler
|
||||
*/
|
||||
|
||||
import engine.net.AbstractConnection;
|
||||
import engine.net.ByteBufferReader;
|
||||
import engine.net.client.handlers.*;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.net.client.msg.chat.*;
|
||||
import engine.net.client.msg.commands.ClientAdminCommandMsg;
|
||||
import engine.net.client.msg.group.*;
|
||||
import engine.net.client.msg.guild.*;
|
||||
import engine.net.client.msg.login.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
|
||||
public enum Protocol {
|
||||
|
||||
|
||||
NONE(0x0, null, null),
|
||||
ABANDONASSET(0xFDDBB233, AbandonAssetMsg.class, AbandonAssetMsgHandler.class), // AbandonAsset
|
||||
ACTIVATECHARTER(0x296C0B22, UseCharterMsg.class, null),// Use Guild Charter
|
||||
ACTIVATENPC(0xC9AAE81E, ActivateNPCMessage.class, ActivateNPCMsgHandler.class),
|
||||
ACTIVATEPLEDGE(0x5A694DC0, SwearInMsg.class, SwearInHandler.class), // Swear In
|
||||
ADDFRIEND(0xCFA1C787,AddFriendMessage.class,null),
|
||||
ALLIANCECHANGE(0x0E7D0B57, AllianceChangeMsg.class, AllianceChangeMsgHandler.class), // Remove From Allies/Enemies List
|
||||
ALLYENEMYLIST(0xAEA443FD, AllyEnemyListMsg.class, AllyEnemyListMsgHandler.class),
|
||||
ARCCOMBATMODEATTACKING(0xD8B10579, SetCombatModeMsg.class, null), // Attack From Outside Combat Mode
|
||||
ARCHOTZONECHANGE(0xDCFF196F, null, null), //change hotzone
|
||||
ARCIGNORELISTUPDATE(0x4B1B17C2, IgnoreListMsg.class, null), //req/show ignore list
|
||||
ARCLOGINNOTIFY(0x010FED87, ArcLoginNotifyMsg.class, ArcLoginNotifyMsgHandler.class), //Client Confirms entering world
|
||||
ARCMINECHANGEPRODUCTION(0x1EAA993F, ArcMineChangeProductionMsg.class, null),
|
||||
ARCMINETOWERCRESTUPDATE(0x34164D0D, null, null),
|
||||
ARCMINEWINDOWAVAILABLETIME(0x6C909DE7, ArcMineWindowAvailableTimeMsg.class, null),
|
||||
ARCMINEWINDOWCHANGE(0x92B2148A, ArcMineWindowChangeMsg.class, null),
|
||||
ARCOWNEDMINESLIST(0x59184455, ArcOwnedMinesListMsg.class, null),
|
||||
ARCPETATTACK(0x18CD61AD, PetAttackMsg.class, null), // Pet Attack
|
||||
ARCPETCMD(0x4E80E001, PetCmdMsg.class, null), // Stop ArcPetAttack, Toggle Assist, Toggle Rest
|
||||
ARCPOWERPROJECTILE(0xA2312D3B, null, null),
|
||||
ARCPROMPTRECALL(0xE3196B6E, PromptRecallMsg.class, null), //Recall Prompt
|
||||
ARCREQUESTTRADEBUSY(0xD4BAB4DF, InvalidTradeRequestMsg.class, null), // Attempt trade with someone who is already trading
|
||||
ARCSERVERSTATUS(0x87BA4462, null, null), //Update Server Status
|
||||
ARCSIEGESPIRE(0x36A49BC6, ArcSiegeSpireMsg.class, ArcSiegeSpireMsgHandler.class), // Activate/Deactivate Spires
|
||||
ARCSUMMON(0xFD816A0A, RecvSummonsRequestMsg.class, null), // Suspect Recv Summons Request
|
||||
ARCTRACKINGLIST(0xC89CF08B, TrackWindowMsg.class, null), //Request/Send Track window
|
||||
ARCTRACKOBJECT(0x609B6BA2, TrackArrowMsg.class, null), //Send Track Arrow
|
||||
ARCUNTRAINABILITY(0x548DBF83, RefineMsg.class, null), //Refine
|
||||
ARCUNTRAINLIST(0x38879E90, RefinerScreenMsg.class, null), //Refiner screen
|
||||
ARCVIEWASSETTRANSACTIONS(0xBFA476E4, ArcViewAssetTransactionsMsg.class, ArcViewAssetTransactionsMsgHandler.class),
|
||||
ASSETSUPPORT(0xc481f89D, AssetSupportMsg.class, AssetSupportMsgHandler.class),
|
||||
BANISHMEMBER(0x31AA3368, BanishUnbanishMsg.class, BanishUnbanishHandler.class), // Banish/Unbanish
|
||||
BANKINVENTORY(0x32F3F503, ShowBankInventoryMsg.class, null), // ShowCombatInfo Bank Inventory
|
||||
BREAKFEALTY(0x479A4C19, BreakFealtyMsg.class, BreakFealtyHandler.class),
|
||||
BUYFROMNPC(0xA2B8DFA5, BuyFromNPCMsg.class, null), // Buy Item From NPC
|
||||
CANCELGUILDCREATION(0x385EA922, GuildCreationCloseMsg.class, GuildCreationCloseHandler.class), //Close the window
|
||||
CHANGEALTITUDE(0x624F08BA, ChangeAltitudeMsg.class, ChangeAltitudeHandler.class), //Change Altitude
|
||||
CHANGEGUILDLEADER(0xE40BC95D, ChangeGuildLeaderMsg.class, ChangeGuildLeaderHandler.class),
|
||||
CHANNELMUTE(0xC1BDC53A, ChatFilterMsg.class, ChannelMuteMsgHandler.class), //Chat Channels that are turned on
|
||||
CHARSELECTSCREEN(0x682C935D, null, null), // Character Selection Screen
|
||||
CHATCITY(0x9D402901, ChatCityMsg.class, null), // Chat Channel: /City
|
||||
CHATCSR(0x14EBA1C3, ChatCSRMsg.class, null), //Chat Channel: CSR
|
||||
CHATGROUP(0xA895B634, ChatGroupMsg.class, null), // Chat Channel: /group
|
||||
CHATGUILD(0xA9D92ED4, ChatGuildMsg.class, null), // Chat Channel: /guild
|
||||
CHATIC(0x00A75F35, ChatICMsg.class, null), // Chat Channel: /IC
|
||||
CHATINFO(0x9D4B61EB, ChatInfoMsg.class, null), // Chat Channel: /Info
|
||||
CHATPVP(0x14EBA570, ChatPvPMsg.class, null), // Chat Channel: PVP
|
||||
CHATSAY(0x14EA0393, ChatSayMsg.class, null), // Chat Channel: /say
|
||||
CHATSHOUT(0xA8D5B560, ChatShoutMsg.class, null), // Chat Channel: /shout
|
||||
CHATTELL(0x9D4AC896, ChatTellMsg.class, null), // Chat Channel: /tell
|
||||
CHECKUNIQUEGUILD(0x689097D7, GuildCreationOptionsMsg.class, GuildCreationOptionsHandler.class), // Set Guild Name/Motto in Use Guild Charter
|
||||
CITYASSET(0x7cae1678, CityAssetMsg.class, null),
|
||||
CITYCHOICE(0x406610BB, CityChoiceMsg.class, CityChoiceMsgHandler.class),
|
||||
CITYDATA(0xB8A947D4, WorldObjectMsg.class, null), //Realm Data - Optional(?)
|
||||
CITYZONE(0x254947F2, CityZoneMsg.class, null), //For Creating City Object Clientside(Terraform)/Rename City.
|
||||
CLAIMASSET(0x948C62CC, ClaimAssetMsg.class, ClaimAssetMsgHandler.class), // ClaimAsset
|
||||
CLAIMGUILDTREE(0xFD1C6442, ClaimGuildTreeMsg.class, ClaimGuildTreeMsgHandler.class),
|
||||
CLIENTADMINCOMMAND(0x624EAB5F, ClientAdminCommandMsg.class, null), //Admin Command
|
||||
CLIENTUPDATEVAULT( 0x66EDBECD, UpdateVaultMsg.class, null),
|
||||
COMBATMODE(0xFE4BF353, ToggleCombatMsg.class, null), //Toggle Combat mode
|
||||
CONFIRMPROMOTE(0x153BB5F9, ConfirmPromoteMsg.class, null),
|
||||
COSTTOOPENBANK(0x135BE5E8, AckBankWindowOpenedMsg.class, null), // ACK Bank Window Opened
|
||||
CREATECHAR(0x5D18B5C8, CommitNewCharacterMsg.class, null), // Commit New Character,
|
||||
CREATEPETITION(0xD489CFED, GuildCreationFinalizeMsg.class, GuildCreationFinalizeHandler.class), //Confirm guild creation
|
||||
CUSTOMERPETITION(0x7F9D7D6D, PetitionReceivedMsg.class, null),
|
||||
DELETEOBJECT(0x57F069D8, DeleteItemMsg.class, null), //Delete Item from Inventory
|
||||
DESTROYBUILDING(0x3CB6FAD3, DestroyBuildingMsg.class, DestroyBuildingHandler.class), // Destroy Building
|
||||
DISBANDGUILD(0x77AABD64, DisbandGuildMsg.class, DisbandGuildHandler.class), //Disband Guild
|
||||
DISMISSGUILD(0x8D2D3D61, DismissGuildMsg.class, DismissGuildHandler.class),
|
||||
DOORTRYOPEN(0xA83DD8C8, DoorTryOpenMsg.class, DoorTryOpenMsgHandler.class), // Open/Close Door
|
||||
ENTERWORLD(0xB9783F85, RequestEnterWorldMsg.class, RequestEnterWorldHandler.class), // Request Enter World
|
||||
EQUIP(0x3CB1AF8C, TransferItemFromInventoryToEquipMsg.class, null), // Transfer Item from Inventory to Equip
|
||||
EXPERIENCE(0xC57802A7, GrantExperienceMsg.class, null), //TODO rename once identified
|
||||
FORGETOBJECTS(0xE307A0E1, UnloadObjectsMsg.class, null), // Unload Objects
|
||||
FRIENDACCEPT(0xCA297870,AcceptFriendMsg.class,FriendAcceptHandler.class),
|
||||
FRIENDDECLINE(0xF08FC279,DeclineFriendMsg.class,FriendDeclineHandler.class),
|
||||
FURNITURE(0xCE7FA503, FurnitureMsg.class, FurnitureHandler.class),
|
||||
GAMESERVERIPRESPONSE(0x6C95CF87, GameServerIPResponseMsg.class, null), // Game Server IP Response
|
||||
GLOBALCHANNELMESSAGE(0x2bf03fd2, null, null),
|
||||
GOLDTOVAULT(0x3ABAEE49, TransferGoldFromInventoryToVaultMsg.class, null), // Transfer Gold from Inventory to Vault
|
||||
GROUPDISBAND(0xE2B85AA4, DisbandGroupMsg.class, DisbandGroupHandler.class), //Disband Group
|
||||
GROUPFOLLOW(0xC61B0476, FormationFollowMsg.class, FormationFollowHandler.class), //Toggle Follow, set Formation
|
||||
GROUPLEADERAPPOINT(0xEF778DD3, AppointGroupLeaderMsg.class, AppointGroupLeaderHandler.class), //Appoint new group leader
|
||||
GROUPREMOVE(0x6E50277C, RemoveFromGroupMsg.class, RemoveFromGroupHandler.class), //Remove from Group
|
||||
GROUPTREASURE(0x01041C66, ToggleGroupSplitMsg.class, ToggleGroupSplitHandler.class), // Toggle Group Split
|
||||
GUILDMEMBERONLINE(0x7B79EB3A, GuildEnterWorldMsg.class, null), // Send Enter World Message to Guild
|
||||
GUILDRANKCHANGE(0x0DEFB21F, ChangeRankMsg.class, ChangeRankHandler.class), // Change Rank
|
||||
GUILDTREESTATUS(0x4B95FB85, GuildTreeStatusMsg.class, null),
|
||||
HIRELINGSERVICE(0xD3D93322,HirelingServiceMsg.class,HirelingServiceMsgHandler.class),
|
||||
IGNORE(0xBD8881EE, IgnoreMsg.class, null), //client sent /ignore command
|
||||
INITIATETRADEHUDS(0x667D29D8, OpenTradeWindowMsg.class, null), // Open Trade Window
|
||||
INVITEGROUP(0x004A2012, GroupInviteMsg.class, GroupInviteHandler.class), // Send/Receive/Deny Group Invite
|
||||
INVITEGUILDFEALTY(0x0274D612, InviteToSubMsg.class, InviteToSubHandler.class), // Invite Guild to Swear
|
||||
INVITETOGUILD(0x6819062A, InviteToGuildMsg.class, InviteToGuildHandler.class), // Invite player to guild, refuse guild invite
|
||||
ITEMHEALTHUPDATE(0xB635F55E, ItemHealthUpdateMsg.class, null), //Update Durability of item
|
||||
ITEMPRODUCTION(0x3CCE8E30, ItemProductionMsg.class, ItemProductionMsgHandler.class),
|
||||
ITEMTOVAULT(0x3ABE4927, TransferItemFromInventoryToVaultMsg.class, null), // Transfer Item to Vault
|
||||
JOINFORPROVINCE(0x1FB369CD, AcceptSubInviteMsg.class, AcceptSubInviteHandler.class), //Response to invite to swear?
|
||||
JOINFORSWORN(0xF6A4170F, null, null),
|
||||
JOINGROUP(0x7EC5E636, GroupInviteResponseMsg.class, GroupInviteResponseHandler.class), // Accept Group Invite
|
||||
JOINGUILD(0xF0C5F2FF, AcceptInviteToGuildMsg.class, AcceptInviteToGuildHandler.class), // Accept guild invite
|
||||
KEEPALIVESERVERCLIENT(0x49EE129C, KeepAliveServerClientMsg.class, KeepAliveServerClientHandler.class), // Keep Alive
|
||||
LEADERBOARD(0x6F0C1386, LeaderboardMessage.class, null),
|
||||
LEADERCHANNELMESSAGE(0x17b306f9, ChatGlobalMsg.class, null),
|
||||
LEAVEGROUP(0xD8037303, LeaveGroupMsg.class, LeaveGroupHandler.class), //Leave Group
|
||||
LEAVEGUILD(0x1801EA32, LeaveGuildMsg.class, LeaveGuildHandler.class), // Leave Guild
|
||||
LEAVEREQUEST(0xC79D775C, LeaveWorldMsg.class, null), //Client Request Leave World
|
||||
LEAVEWORLD(0xB801EAEC, null, null), //Response to client for Request Leave World
|
||||
LOADCHARACTER(0x5756BC53, null, null), // Load Player/NPC/Mob, other then self
|
||||
LOADSTRUCTURE(0xB8A3A654, LoadStructureMsg.class, null), //Load Buildings and World Detail Objects
|
||||
LOCKUNLOCKDOOR(0x8D0E8C44, LockUnlockDoorMsg.class, LockUnlockDoorMsgHandler.class), // Lock/Unlock Door
|
||||
LOGIN(0x3D51E445, ClientLoginInfoMsg.class, null), // Login Information
|
||||
LOGINFAILED(0x47B867F6, null, null), // Login Error
|
||||
LOGINTOGAMESERVER(0x77910FDF, LoginToGameServerMsg.class, LoginToGameServerMsgHandler.class), // Login to Game Server
|
||||
MANAGECITYASSETS(0xCFF01225, ManageCityAssetsMsg.class, ManageCityAssetMsgHandler.class), // Manage city assets
|
||||
MANAGENPC(0x43A273FA, null, null), // Open Hireling Management Page
|
||||
MERCHANT(0x3E645EF4, MerchantMsg.class, MerchantMsgHandler.class), // Open Teleport List, Teleport, Open Shrine, Request Boon, open/manage warehouse window
|
||||
MINIONTRAINING(0xD355F528, MinionTrainingMessage.class, MinionTrainingMsgHandler.class),
|
||||
MODIFYGUILDSTATE(0x38936FEA, ToggleLfgRecruitingMsg.class, null), //Toggle LFGroup/LFGuild/Recruiting
|
||||
MOTD(0xEC841E8D, MOTDMsg.class, MOTDEditHandler.class), //Send/Rec Guild/Nation/IC MOTD Message
|
||||
MOVECORRECTION(0x47FAD1E3, null, null), //Force move to point?
|
||||
MOVEOBJECTTOCONTAINER(0xD1639F7C, LootMsg.class, null), //Send/Recv MoveObjectToContainer Msg
|
||||
MOVETOPOINT(0x49EF7241, MoveToPointMsg.class, MoveToPointHandler.class), // Move to point
|
||||
NAMEVERIFY(0x1B3BF0B1, null, null), // Invalid Name in Character Creation
|
||||
NEWWORLD(0x982E4A77, WorldDataMsg.class, null), // World Data
|
||||
OBJECTACTION(0x06855A36, ObjectActionMsg.class, ObjectActionMsgHandler.class), //Use item
|
||||
OKCOSTTOOPENBANK(0x6F97A502, null, null),
|
||||
OPENFRIENDSCONDEMNLIST(0x49E5FE4F, OpenFriendsCondemnListMsg.class, OpenFriendsCondemnListMsgHandler.class), // Friends/Con demn/Kill/Death/Heraldry List
|
||||
OPENVAULT(0xBE048E50, OpenVaultMsg.class, null), // Open Vault Window
|
||||
ORDERNPC(0x61C707B1, OrderNPCMsg.class, OrderNPCMsgHandler.class),
|
||||
PASSIVEMESSAGETRIGGER(0x2FF9E2E4, null, null), //PassiveMessageTriggerMsg
|
||||
PET(0x624F3D8C, PetMsg.class, null), //Summon Pet?
|
||||
PLACEASSET(0x940962DF, PlaceAssetMsg.class, PlaceAssetMsgHandler.class),
|
||||
PLAYERDATA(0xB206D352, SendOwnPlayerMsg.class, null), //Enter World, Own Player Data
|
||||
PLAYERFRIENDS(0xDDEF9E7D, FriendRequestMsg.class, FriendRequestHandler.class),
|
||||
POWER(0x3C97A459, PerformActionMsg.class, null), // REQ / CMD Perform Action
|
||||
POWERACTION(0xA0B27EEB, ApplyEffectMsg.class, null), // Apply Effect, add to effects icons
|
||||
POWERACTIONDD(0xD43052F8, ModifyHealthMsg.class, null), //Modify Health/Mana/Stamina using power
|
||||
POWERACTIONDDDIE(0xC27D446B, null, null), //Modify Health/Mana/Stamina using power and kill target
|
||||
POWERTARGNAME(0x5A807CCE, SendSummonsRequestMsg.class, null), // Send Summons Request
|
||||
RAISEATTR(0x5EEB65E0, ModifyStatMsg.class, null), // Modify Stat
|
||||
RANDOM(0xAC5D0135, RandomMsg.class, null), //RequestSend random roll
|
||||
READYTOENTER(0x490E4FE0, EnterWorldReceivedMsg.class, null), //Client Ack Receive Enter World
|
||||
REALMDATA(0x2399B775, null, null), //Realm Data - Optional(?)
|
||||
RECOMMENDNATION(0x6D4579E9, RecommendNationMsg.class, RecommendNationMsgHandler.class), // Recommend as Ally/Enemy, error
|
||||
RECYCLEPOWER(0x24033B67, RecyclePowerMsg.class, null), //Unlock power for reUse
|
||||
REMOVECHAR(0x5D3F9739, DeleteCharacterMsg.class, null), // Delete Character
|
||||
REMOVEFRIEND(0xE0D5DB42,RemoveFriendMessage.class,RemoveFriendHandler.class),
|
||||
REPAIRBUILDING(0xAF8C2560, RepairBuildingMsg.class, RepairBuildingMsgHandler.class),
|
||||
REPAIROBJECT(0x782219CE, RepairMsg.class, null), //Repair Window Req/Ack, RepairObject item Req/Ack
|
||||
REQUESTCONTENTS(0xA786B0A2, LootWindowRequestMsg.class, null), // MoveObjectToContainer Window Request
|
||||
REQUESTGUILDLIST(0x85DCC6D7, ReqGuildListMsg.class, RequestGuildListHandler.class),
|
||||
REQUESTMELEEATTACK(0x98C71545, AttackCmdMsg.class, null), // Attack
|
||||
REQUESTMEMBERLIST(0x3235E5EA, GuildControlMsg.class, GuildControlHandler.class), // Part of Promote/Demote, Also Player History
|
||||
REQUESTTOOPENBANK(0xF26E453F, null, null), // RequestToOpenBankMsg
|
||||
REQUESTTOTRADE(0x4D84259B, TradeRequestMsg.class, null), // Trade Request
|
||||
REQUESTTRADECANCEL(0xCB0C5735, RejectTradeRequestMsg.class, null), // Reject RequestToTrade
|
||||
REQUESTTRADEOK(0xFFD29841, AcceptTradeRequestMsg.class, null), // Accept Trade Request
|
||||
RESETAFTERDEATH(0xFDCBB98F,RespawnMsg.class, null), //Respawn Request/Response
|
||||
ROTATEMSG(0x57F2088E, RotateObjectMsg.class, null),
|
||||
SAFEMODE(0x9CF3922A, SafeModeMsg.class, null), //Tell client they're in safe mode
|
||||
SCALEOBJECT(0xE2B392D9, null, null), // Adjust scale of object
|
||||
SELECTCHAR(0x7E6A9338, GameServerIPRequestMsg.class, null), // Game Server IP Request
|
||||
SELECTCITY(0x7E6BE630, null, null),
|
||||
SELECTSERVER(0x440D28B7, ServerInfoMsg.class, null), // Server Info Request/Response
|
||||
SELLOBJECT(0x57111C67, SellToNPCMsg.class, null), //Sell to NPC
|
||||
SENDCITYENTRY(0xBC3B5E72, null, null), //Send Teleport/Repledge List
|
||||
SENDGUILDENTRY(0x6D5EF164, null, null),
|
||||
SENDMEMBERENTRY(0x6949C720, GuildListMsg.class, GuildListHandler.class), // ShowCombatInfo guild members list, I think
|
||||
SETITEMFLAG(0xE8C1B53B, null, null),
|
||||
SETMOTD(0xFD21FC7C, MOTDCommitMsg.class, MOTDCommitHandler.class), //Commit Guild/Nation/IC MOTD Message
|
||||
SETOBJVAL(0x08A50FD1, null, null),
|
||||
SETRUNE(0x888E7C64, ApplyRuneMsg.class, null), //Apply Promotion, Stat Rune (maybe disc also)
|
||||
SETSELECTEDOBECT(0x64E10938, TargetObjectMsg.class, null), // Target an object
|
||||
SHOPINFO(0x267DAB90, SellToNPCWindowMsg.class, null), //open Sell to NPC Window
|
||||
SHOPLIST(0x682DAB4D, BuyFromNPCWindowMsg.class, null), // Open Buy From NPC Window
|
||||
SHOWCOMBATINFO(0x9BF1E5EA, ShowMsg.class, null), // Request/Response /show
|
||||
SHOWVAULTINVENTORY(0xD1FB4842, null, null), // Show Vault Inventory
|
||||
SOCIALCHANNEL(0x2BF58FA6, SocialMsg.class, null), // Socials
|
||||
STANDARDALERT(0xFA0A24BB, ErrorPopupMsg.class, null), //Popup messages
|
||||
STUCK(0x3D04AF3A, StuckCommandMsg.class, null), // /Stuck Command
|
||||
SWEARINGUILD(0x389B66B1, SwearInGuildMsg.class, SwearInGuildHandler.class),
|
||||
SYNC(0x49ec109f, null, null), //Client/Server loc sync
|
||||
SYSTEMBROADCASTCHANNEL(0x2FAD89D1, ChatSystemMsg.class, null), // Chat Channel: System Message
|
||||
SYSTEMCHANNEL(0x29BB4D66, ChatSystemChannelMsg.class, null), // Chat System Channel
|
||||
TARGETEDACTION(0xB79BA48F, TargetedActionMsg.class, null), //Message sent for attacks
|
||||
TAXCITY(0xCD41EAA6, TaxCityMsg.class, TaxCityMsgHandler.class),
|
||||
TAXRESOURCES(0x4AD458AF, TaxResourcesMsg.class, TaxResourcesMsgHandler.class),
|
||||
TELEPORT(0x23E726EA, TeleportToPointMsg.class, null), // Teleport to point
|
||||
TERRITORYCHANGE(0x6B388C8C,TerritoryChangeMessage.class, null), //Hey rich, look what I found? :)
|
||||
TOGGLESITSTAND(0x624F3C0F, ToggleSitStandMsg.class, null), //Toggle Sit/Stand
|
||||
TRADEADDGOLD(0x654ACB45, AddGoldToTradeWindowMsg.class, null), // Add Gold to Trade Window
|
||||
TRADEADDOBJECT(0x55D363E9, AddItemToTradeWindowMsg.class, null), // Add an Item to the Trade Window
|
||||
TRADECLOSE(0x5008D7FC, CloseTradeWindowMsg.class, null), // Cancel trade/ACK trade complete
|
||||
TRADECONFIRM(0x6911E65E, CommitToTradeMsg.class, null), // Commit to trade
|
||||
TRADECONFIRMSTATUS(0x9F85DAFC, null, null), // Other player commit/uncommit/add item
|
||||
TRADEUNCONFIRM(0xEBE280E0, UncommitToTradeMsg.class, null), // Uncommit to trade
|
||||
TRAINERLIST(0x41FABA62, TrainerInfoMsg.class, null), //Req/Send Trainer Info/Pricing
|
||||
TRAINSKILL(0xB0BF68CD, TrainMsg.class, null), //Train skills/powers
|
||||
TRANSFERASSET(0x3EA1C4C9, TransferAssetMsg.class, TransferAssetMsgHandler.class), // Transfer Building
|
||||
TRANSFERGOLDFROMVAULTTOINVENTORY(0x011D0123, TransferGoldFromVaultToInventoryMsg.class, null), // Transfer Gold from Vault to Inventory
|
||||
TRANSFERGOLDTOFROMBUILDING(0x1B1AC8C7, TransferGoldToFromBuildingMsg.class, TransferGoldToFromBuildingMsgHandler.class), // Transfer Gold to/From Building, Transfer Error
|
||||
TRANSFERITEMFROMBANK(0x9D04977B, TransferItemFromBankToInventoryMsg.class, null), // Transfer Item from Bank to Inventory
|
||||
TRANSFERITEMFROMVAULTTOINVENTORY(0x0119A64D, TransferItemFromVaultToInventoryMsg.class, null), // Transfer Item from Vault to Inventory
|
||||
TRANSFERITEMTOBANK(0xD48C46FA, TransferItemFromInventoryToBankMsg.class, null), // Transfer Item from Inventory to Bank
|
||||
UNEQUIP(0xC6BFB907, TransferItemFromEquipToInventoryMsg.class, null), // Transfer Item from Equip to Inventory
|
||||
UNKNOWN(0x238C9259, UnknownMsg.class,null),
|
||||
UPDATECHARORMOB(0xB6D78961, null, null),
|
||||
UPDATECLIENTALLIANCES(0xF3FEB5D4, null, GuildUnknownHandler.class), //AlliancesMsg
|
||||
UPDATECLIENTINVENTORIES(0xE66F533D, UpdateInventoryMsg.class, null), //Update player inventory
|
||||
UPDATEEFFECTS(0xD4675293, null, null), //Update all effects for an item
|
||||
UPDATEFRIENDSTATUS(0x654E2255, UpdateFriendStatusMessage.class, UpdateFriendStatusHandler.class),
|
||||
UPDATEGOLDVALUE(0x6915A3FB, null, null), // Update gold in inventory and/or bank
|
||||
UPDATEGROUP(0x004E6BCE, GroupUpdateMsg.class, GroupUpdateHandler.class), // Update Group Info
|
||||
UPDATEGUILD(0x001D4DF6, GuildInfoMsg.class, GuildInfoHandler.class), // REQ / CMD Promote/Demote Screen
|
||||
UPDATEOBJECT(0x1A724739, null, null),
|
||||
UPDATESTATE(0x001A45FB, UpdateStateMsg.class, null), // REQ / CMD Toggle Run/Walk Sit/Stand :: UpdateStateMessage
|
||||
UPDATETRADEWINDOW(0x406EBDE6, UpdateTradeWindowMsg.class, null), // Trade Complete
|
||||
UPGRADEASSET(0x2B85A865, UpgradeAssetMessage.class, UpgradeAssetMsgHandler.class),
|
||||
VENDORDIALOG(0x98ACD594, VendorDialogMsg.class, null), // Send/Recv Vendor Dialog
|
||||
VERSIONINFO(0x4B7EE463, VersionInfoMsg.class, null), // Version Information
|
||||
VIEWRESOURCES(0xCEFD0346, ViewResourcesMessage.class, null),
|
||||
VISUALUPDATE(0x33402fd2, null, null),
|
||||
WEIGHTINVENTORY(0xF1B6A85C, LootWindowResponseMsg.class, null), // MoveObjectToContainer Window Response
|
||||
WHOREQUEST(0xF431CCE9, WhoRequestMsg.class, null), // Request /who
|
||||
WHORESPONSE(0xD7C36568, WhoResponseMsg.class, null), // Response /who
|
||||
REQUESTBALLLIST(0xE366FF64,RequestBallListMessage.class,RequestBallListHandler.class),
|
||||
SENDBALLENTRY(0xAC2B5EDC,SendBallEntryMessage.class,SendBallEntryHandler.class),
|
||||
UNKNOWN1(-263523523, Unknown1Msg.class,null),
|
||||
DROPGOLD(1461654160,DropGoldMsg.class,null);
|
||||
|
||||
public int opcode;
|
||||
private Class message;
|
||||
private Class handlerClass;
|
||||
public Constructor constructor;
|
||||
public AbstractClientMsgHandler handler;
|
||||
|
||||
Protocol(int opcode, Class message, Class handlerClass) {
|
||||
this.opcode = opcode;
|
||||
this.message = message;
|
||||
this.handlerClass = handlerClass;
|
||||
|
||||
// Create reference to message class constructor.
|
||||
|
||||
if (this.message != null) {
|
||||
Class[] params = {AbstractConnection.class, ByteBufferReader.class};
|
||||
|
||||
try {
|
||||
this.constructor = this.message.getConstructor(params);
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Create instance of message handler for incoming protocol messages
|
||||
|
||||
if (this.handlerClass != null) {
|
||||
try {
|
||||
handler = (AbstractClientMsgHandler) handlerClass.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static HashMap<Integer, Protocol> _protocolMsgByOpcode = new HashMap<>();
|
||||
|
||||
public static Protocol getByOpcode(int opcode) {
|
||||
|
||||
Protocol protocol = _protocolMsgByOpcode.get(opcode);
|
||||
|
||||
if (protocol != null)
|
||||
return protocol;
|
||||
|
||||
return Protocol.NONE;
|
||||
}
|
||||
|
||||
public static void initProtocolLookup() {
|
||||
|
||||
for (Protocol protocol : Protocol.values()) {
|
||||
|
||||
if (_protocolMsgByOpcode.containsKey(protocol.opcode)){
|
||||
Logger.error("Duplicate opcodes for " + protocol.name() + " and " + _protocolMsgByOpcode.get(protocol.opcode).name());
|
||||
}
|
||||
_protocolMsgByOpcode.put(protocol.opcode, protocol);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static int FindNextValidOpcode(ByteBufferReader reader){
|
||||
int startPos = reader.position();
|
||||
int bytesLeft = reader.remaining();
|
||||
|
||||
if (bytesLeft < 4)
|
||||
return startPos;
|
||||
int nextPos = startPos;
|
||||
for (int i = 1; i< bytesLeft; i++ ){
|
||||
reader.position(nextPos);
|
||||
if (reader.remaining() < 4)
|
||||
return reader.position();
|
||||
int newOpcode = reader.getInt();
|
||||
|
||||
Protocol foundProtocol = Protocol.getByOpcode(newOpcode);
|
||||
if (foundProtocol.equals(Protocol.NONE)){
|
||||
nextPos += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
//found opcode. return position - 4 to rewind back to start of opcode, so we can handle it.
|
||||
return reader.position() - 4;
|
||||
}
|
||||
|
||||
return startPos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.Enum.GuildState;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.*;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.AbandonAssetMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which processes
|
||||
* client requests to abandon a building.
|
||||
*/
|
||||
public class AbandonAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Instance variables
|
||||
|
||||
public AbandonAssetMsgHandler() {
|
||||
super(AbandonAssetMsg.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
PlayerCharacter player;
|
||||
Building building;
|
||||
AbandonAssetMsg msg;
|
||||
|
||||
// Member variable assignment
|
||||
msg = (AbandonAssetMsg) baseMsg;
|
||||
|
||||
player = origin.getPlayerCharacter();
|
||||
building = BuildingManager.getBuildingFromCache(msg.getUUID());
|
||||
|
||||
// Oops! *** Refactor: Log error
|
||||
if ((player == null) || (building == null))
|
||||
return true;
|
||||
|
||||
// Early exit if object is not owned by the player
|
||||
if (building.getOwnerUUID() != player.getObjectUUID())
|
||||
return true;
|
||||
|
||||
// Cannot abandon a building without a blueprint.
|
||||
// Players do not own rocks or shrubbery.
|
||||
if (building.getBlueprintUUID() == 0)
|
||||
return true;
|
||||
|
||||
// Players cannot abandon shrines
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to abandon shrine!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.MINE)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot abandon mine!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Blueprint.isMeshWallPiece(building.getBlueprintUUID())) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to abandon fortress asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.BARRACK)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to abandon fortress asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.BULWARK)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to abandon siege asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.SIEGETENT)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to abandon siege asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.BANESTONE)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to abandon banestone!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trees require special handling beyond an individual building
|
||||
if ((building.getBlueprint().getBuildingGroup() == BuildingGroup.TOL))
|
||||
AbandonAllCityObjects(player, building);
|
||||
else
|
||||
AbandonSingleAsset(player, building);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void AbandonSingleAsset(PlayerCharacter sourcePlayer,
|
||||
Building targetBuilding) {
|
||||
|
||||
// Transfer the building asset ownership and refresh all clients
|
||||
|
||||
DbManager.BuildingQueries.CLEAR_FRIENDS_LIST(targetBuilding.getObjectUUID());
|
||||
targetBuilding.getFriends().clear();
|
||||
|
||||
// Clear protection status but only if a seige building
|
||||
|
||||
if (targetBuilding.getBlueprint().getBuildingGroup().equals(BuildingGroup.BULWARK) ||
|
||||
targetBuilding.getBlueprint().getBuildingGroup().equals(BuildingGroup.SIEGETENT))
|
||||
targetBuilding.setProtectionState(Enum.ProtectionState.NONE);
|
||||
|
||||
DbManager.BuildingQueries.CLEAR_CONDEMNED_LIST(targetBuilding.getObjectUUID());
|
||||
targetBuilding.getCondemned().clear();
|
||||
targetBuilding.setOwner(null);
|
||||
targetBuilding.refreshGuild();
|
||||
|
||||
}
|
||||
|
||||
private void AbandonAllCityObjects(PlayerCharacter sourcePlayer,
|
||||
Building targetBuilding) {
|
||||
Guild sourceGuild;
|
||||
Zone cityZone;
|
||||
|
||||
sourceGuild = sourcePlayer.getGuild();
|
||||
|
||||
if (sourceGuild == null)
|
||||
return;
|
||||
|
||||
if (sourceGuild.getSubGuildList().size() > 0) {
|
||||
ChatManager.chatCityError(sourcePlayer, "You Cannot abandon a nation city.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
cityZone = ZoneManager.findSmallestZone(targetBuilding.getLoc());
|
||||
|
||||
// Can't abandon a tree not within a player city zone
|
||||
if (cityZone.isPlayerCity() == false)
|
||||
return;
|
||||
|
||||
if (targetBuilding.getCity() == null)
|
||||
return;
|
||||
|
||||
if (targetBuilding.getCity().getBane() != null){
|
||||
ErrorPopupMsg.sendErrorMsg(sourcePlayer, "Can't abandon Tree while a bane exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetBuilding.getCity().hasBeenTransfered == true) {
|
||||
ChatManager.chatCityError(sourcePlayer, "City can only be abandoned once per rebooting.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Guild no longer owns his tree.
|
||||
if (!DbManager.GuildQueries.SET_GUILD_OWNED_CITY(sourceGuild.getObjectUUID(), 0)) {
|
||||
Logger.error("Failed to update Owned City to Database");
|
||||
return;
|
||||
}
|
||||
|
||||
sourceGuild.setCityUUID(0);
|
||||
sourceGuild.setGuildState(GuildState.Errant);
|
||||
sourceGuild.setNation(null);
|
||||
|
||||
// Transfer the city assets
|
||||
TransferCityAssets(sourcePlayer, targetBuilding);
|
||||
|
||||
GuildManager.updateAllGuildTags(sourceGuild);
|
||||
GuildManager.updateAllGuildBinds(sourceGuild, null);
|
||||
|
||||
}
|
||||
|
||||
private void TransferCityAssets(PlayerCharacter sourcePlayer,
|
||||
Building cityTOL) {
|
||||
|
||||
Zone cityZone;
|
||||
|
||||
// Build list of buildings within this parent zone
|
||||
cityZone = ZoneManager.findSmallestZone(cityTOL.getLoc());
|
||||
|
||||
for (Building cityBuilding : cityZone.zoneBuildingSet) {
|
||||
|
||||
Blueprint cityBlueprint;
|
||||
cityBlueprint = cityBuilding.getBlueprint();
|
||||
|
||||
// Buildings without blueprints cannot be abandoned
|
||||
if (cityBlueprint == null)
|
||||
continue;
|
||||
|
||||
// Transfer ownership of valid city assets
|
||||
if ((cityBlueprint.getBuildingGroup() == BuildingGroup.TOL)
|
||||
|| (cityBlueprint.getBuildingGroup() == BuildingGroup.SPIRE)
|
||||
|| (cityBlueprint.getBuildingGroup() == BuildingGroup.BARRACK)
|
||||
|| (cityBlueprint.isWallPiece())
|
||||
|| (cityBuilding.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE))
|
||||
AbandonSingleAsset(sourcePlayer, cityBuilding);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
|
||||
/* @Summary: This is the abstract class from which all message handlers
|
||||
* for mainline application protocol derive. Namely those
|
||||
* routed and executed via ClientMessageHandler.
|
||||
*/
|
||||
|
||||
public abstract class AbstractClientMsgHandler {
|
||||
private final Class<? extends ClientNetMsg> handler;
|
||||
|
||||
public AbstractClientMsgHandler(Class<? extends ClientNetMsg> handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public boolean handleNetMsg(ClientNetMsg msg) {
|
||||
|
||||
boolean executionSucceded;
|
||||
|
||||
try {
|
||||
executionSucceded = _handleNetMsg(msg, (ClientConnection) msg.getOrigin());
|
||||
} catch (MsgSendException e) {
|
||||
e.printStackTrace();
|
||||
executionSucceded = false;
|
||||
}
|
||||
|
||||
return executionSucceded;
|
||||
}
|
||||
|
||||
protected abstract boolean _handleNetMsg(ClientNetMsg msg, ClientConnection origin) throws MsgSendException;}
|
||||
@@ -0,0 +1,122 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.GuildHistoryType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.AcceptInviteToGuildMsg;
|
||||
import engine.net.client.msg.guild.GuildInfoMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildHistory;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
public class AcceptInviteToGuildHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public AcceptInviteToGuildHandler() {
|
||||
super(AcceptInviteToGuildMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player;
|
||||
AcceptInviteToGuildMsg msg;
|
||||
Guild guild;
|
||||
|
||||
msg = (AcceptInviteToGuildMsg) baseMsg;
|
||||
|
||||
// get PlayerCharacter of person accepting invite
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
guild = (Guild) DbManager.getObject(GameObjectType.Guild, msg.getGuildUUID());
|
||||
|
||||
|
||||
if (guild == null)
|
||||
return true;
|
||||
|
||||
if (guild.getGuildType() == null){
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND);
|
||||
return true;
|
||||
}
|
||||
|
||||
// verify they accepted for the correct guild
|
||||
|
||||
if (player.getLastGuildToInvite() != msg.getGuildUUID())
|
||||
return true;
|
||||
|
||||
if ( (player.getGuild() != null) &&
|
||||
(player.getGuild().isErrant() == false)) {
|
||||
ChatManager.chatGuildError(player,
|
||||
"You already belongs to a guild!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// verify they are acceptable level for guild
|
||||
|
||||
if (player.getLevel() < guild.getRepledgeMin() || player.getLevel() > guild.getRepledgeMax())
|
||||
return true;
|
||||
|
||||
// Add player to guild
|
||||
player.setGuild(guild);
|
||||
|
||||
// Cleanup guild stuff
|
||||
player.resetGuildStatuses();
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
DispatchMessage.sendToAllInRange(player, new GuildInfoMsg(player, guild, 2));
|
||||
|
||||
player.incVer();
|
||||
|
||||
//Add to guild History
|
||||
|
||||
if (player.getGuild() != null){
|
||||
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(player.getGuildUUID(), player, DateTime.now(), GuildHistoryType.JOIN)){
|
||||
GuildHistory guildHistory = new GuildHistory(player.getGuildUUID(),player.getGuild().getName(),DateTime.now(), GuildHistoryType.JOIN) ;
|
||||
player.getGuildHistory().add(guildHistory);
|
||||
}
|
||||
}
|
||||
|
||||
// Send guild join message
|
||||
|
||||
ChatManager.chatGuildInfo(player, player.getFirstName() + " has joined the guild");
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.GuildState;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.AcceptSubInviteMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class AcceptSubInviteHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public AcceptSubInviteHandler() {
|
||||
super(AcceptSubInviteMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
AcceptSubInviteMsg msg = (AcceptSubInviteMsg) baseMsg;
|
||||
PlayerCharacter sourcePlayer;
|
||||
Guild sourceGuild;
|
||||
Guild targetGuild;
|
||||
Dispatch dispatch;
|
||||
|
||||
// get PlayerCharacter of person sending sub invite
|
||||
|
||||
sourcePlayer = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (sourcePlayer == null)
|
||||
return true;
|
||||
|
||||
sourceGuild = sourcePlayer.getGuild();
|
||||
targetGuild = (Guild) DbManager.getObject(GameObjectType.Guild, msg.guildUUID());
|
||||
|
||||
//must be source guild to sub to
|
||||
|
||||
if (targetGuild == null) {
|
||||
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 45); // Failure to swear guild
|
||||
return true;
|
||||
}
|
||||
if (sourceGuild == null) {
|
||||
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 45); // Failure to swear guild
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sourceGuild.equals(targetGuild))
|
||||
return true;
|
||||
|
||||
if (GuildStatusController.isGuildLeader(sourcePlayer.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorMsg(sourcePlayer, "Only a guild leader can accept fealty!");
|
||||
return true;
|
||||
}
|
||||
|
||||
//source guild is limited to 7 subs
|
||||
//TODO this should be based on TOL rank
|
||||
|
||||
if (!targetGuild.canSubAGuild(sourceGuild)) {
|
||||
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 45); // Failure to swear guild
|
||||
return true;
|
||||
}
|
||||
|
||||
//all tests passed, let's Handle code
|
||||
//Update Target Guild State.
|
||||
|
||||
sourceGuild.upgradeGuildState(false);
|
||||
|
||||
//Add sub so GuildMaster can Swear in.
|
||||
|
||||
ArrayList<Guild> subs = targetGuild.getSubGuildList();
|
||||
subs.add(sourceGuild);
|
||||
|
||||
targetGuild.setGuildState(GuildState.Nation);
|
||||
|
||||
|
||||
//Let's send the message back.
|
||||
|
||||
msg.setUnknown02(1);
|
||||
msg.setResponse("Your guild is now a " + sourceGuild.getGuildState().name() + '.');
|
||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
ChatManager.chatSystemInfo(sourcePlayer, "Your guild is now a " + sourceGuild.getGuildState().name() + '.');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.ItemType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.*;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ActivateNPCMessage;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ManageCityAssetsMsg;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* client's tcp connection open.
|
||||
*/
|
||||
public class ActivateNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ActivateNPCMsgHandler() {
|
||||
super(ActivateNPCMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
ActivateNPCMessage msg;
|
||||
PlayerCharacter player;
|
||||
Building building;
|
||||
Contract contract;
|
||||
CharacterItemManager itemMan;
|
||||
Zone zone;
|
||||
|
||||
msg = (ActivateNPCMessage) baseMsg;
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
building = BuildingManager.getBuildingFromCache(msg.buildingUUID());
|
||||
|
||||
if (player == null || building == null)
|
||||
return false;
|
||||
|
||||
ArrayList<Item> ItemLists = new ArrayList<>();
|
||||
|
||||
// Filter hirelings by slot type
|
||||
|
||||
for (Item hirelings : player.getInventory()) {
|
||||
if (hirelings.getItemBase().getType().equals(ItemType.CONTRACT)) {
|
||||
contract = DbManager.ContractQueries.GET_CONTRACT(hirelings.getItemBase().getUUID());
|
||||
if (contract == null)
|
||||
continue;
|
||||
if (contract.canSlotinBuilding(building))
|
||||
ItemLists.add(hirelings);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.getUnknown01() == 1) {
|
||||
//Request npc list to slot
|
||||
ActivateNPCMessage anm = new ActivateNPCMessage();
|
||||
anm.setSize(ItemLists.size());
|
||||
anm.setItemList(ItemLists);
|
||||
Dispatch dispatch = Dispatch.borrow(player, anm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
if (msg.getUnknown01() == 0) {
|
||||
|
||||
//Slot npc
|
||||
|
||||
if (building.getBlueprintUUID() == 0) {
|
||||
ChatManager.chatSystemError(player, "Unable to load Blueprint for Building Mesh " + building.getMeshUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (building.getBlueprint().getMaxSlots() == building.getHirelings().size())
|
||||
return false;
|
||||
|
||||
Vector3fImmutable NpcLoc = new Vector3fImmutable(building.getLoc());
|
||||
|
||||
Item contractItem = Item.getFromCache(msg.getUnknown04());
|
||||
|
||||
if (contractItem == null)
|
||||
return false;
|
||||
|
||||
if (!player.getCharItemManager().doesCharOwnThisItem(contractItem.getObjectUUID())) {
|
||||
Logger.error(player.getName() + "has attempted to place Hireling : " + contractItem.getName() + "without a valid contract!");
|
||||
return false;
|
||||
}
|
||||
|
||||
itemMan = player.getCharItemManager();
|
||||
|
||||
zone = ZoneManager.findSmallestZone(NpcLoc);
|
||||
|
||||
if (zone == null)
|
||||
return false;
|
||||
|
||||
contract = DbManager.ContractQueries.GET_CONTRACT(contractItem.getItemBase().getUUID());
|
||||
|
||||
if (contract == null)
|
||||
return false;
|
||||
|
||||
// Check if contract can be slotted in this building
|
||||
|
||||
if (contract.canSlotinBuilding(building) == false)
|
||||
return false;
|
||||
|
||||
if (!BuildingManager.addHireling(building, player, NpcLoc, zone, contract, contractItem))
|
||||
return false;
|
||||
|
||||
itemMan.delete(contractItem);
|
||||
itemMan.updateInventory();
|
||||
|
||||
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, building);
|
||||
|
||||
mca1.actionType = 3;
|
||||
|
||||
mca1.setTargetType(building.getObjectType().ordinal());
|
||||
mca1.setTargetID(building.getObjectUUID());
|
||||
mca1.setTargetType3(building.getObjectType().ordinal());
|
||||
mca1.setTargetID3(building.getObjectUUID());
|
||||
mca1.setAssetName1(building.getName());
|
||||
mca1.setUnknown54(1);
|
||||
Dispatch dispatch = Dispatch.borrow(player, mca1);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.AllianceType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.AllianceChangeMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* protecting and unprotecting city assets
|
||||
*/
|
||||
public class AllianceChangeMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public AllianceChangeMsgHandler() {
|
||||
super(AllianceChangeMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
AllianceChangeMsg msg;
|
||||
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (AllianceChangeMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
Guild toGuild = null;
|
||||
toGuild = Guild.getGuild(msg.getSourceGuildID());
|
||||
if (toGuild.isErrant())
|
||||
return true;
|
||||
|
||||
if (player.getGuild().isErrant())
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
switch (msg.getMsgType()){
|
||||
case AllianceChangeMsg.MAKE_ALLY:
|
||||
case 1: //allyfromRecommended
|
||||
player.getGuild().addGuildToAlliance(msg, AllianceType.Ally, toGuild, player);
|
||||
break;
|
||||
case AllianceChangeMsg.MAKE_ENEMY:
|
||||
case 2: //enemy recommend
|
||||
player.getGuild().addGuildToAlliance(msg, AllianceType.Enemy, toGuild, player);
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
player.getGuild().removeGuildFromAllAlliances(toGuild);
|
||||
break;
|
||||
|
||||
}
|
||||
msg.setMsgType(AllianceChangeMsg.INFO_SUCCESS);
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void MakeEnemy(Guild fromGuild, Guild toGuild, AllianceChangeMsg msg, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
if (fromGuild == null)
|
||||
return;
|
||||
|
||||
if (toGuild == null)
|
||||
return;
|
||||
|
||||
if (!Guild.sameGuild(origin.getPlayerCharacter().getGuild(), fromGuild)){
|
||||
msg.setMsgType(AllianceChangeMsg.ERROR_NOT_SAME_GUILD);
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GuildStatusController.isInnerCouncil(origin.getPlayerCharacter().getGuildStatus()) && !GuildStatusController.isGuildLeader(origin.getPlayerCharacter().getGuildStatus())){
|
||||
msg.setMsgType(AllianceChangeMsg.ERROR_NOT_AUTHORIZED);
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void makeAlly(Guild fromGuild, Guild toGuild, AllianceChangeMsg msg, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
if (fromGuild == null)
|
||||
return;
|
||||
|
||||
if (toGuild == null)
|
||||
return;
|
||||
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void removeFromAlliance(Guild fromGuild, Guild toGuild, AllianceChangeMsg msg, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
if (fromGuild == null)
|
||||
return;
|
||||
|
||||
if (toGuild == null)
|
||||
return;
|
||||
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.AllyEnemyListMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* protecting and unprotecting city assets
|
||||
*/
|
||||
public class AllyEnemyListMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public AllyEnemyListMsgHandler() {
|
||||
super(AllyEnemyListMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
AllyEnemyListMsg msg;
|
||||
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (AllyEnemyListMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
AllyEnemyListMsgHandler.showAllyEnemyList(player.getGuild(), Guild.getGuild(msg.getGuildID()), msg, origin);
|
||||
|
||||
|
||||
|
||||
|
||||
// dispatch = Dispatch.borrow(player, baseMsg);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void showAllyEnemyList(Guild fromGuild, Guild toGuild, AllyEnemyListMsg msg, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
if (fromGuild == null)
|
||||
return;
|
||||
|
||||
if (toGuild == null)
|
||||
return;
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
// UpdateClientAlliancesMsg ucam = new UpdateClientAlliancesMsg();
|
||||
//
|
||||
// dispatch = Dispatch.borrow(origin.getPlayerCharacter(), ucam);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.AppointGroupLeaderMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class AppointGroupLeaderHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public AppointGroupLeaderHandler() {
|
||||
super(AppointGroupLeaderMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
AppointGroupLeaderMsg msg = (AppointGroupLeaderMsg) baseMsg;
|
||||
|
||||
PlayerCharacter source = SessionManager.getPlayerCharacter(origin);
|
||||
if (source == null) {
|
||||
return false;
|
||||
}
|
||||
Group group = GroupManager.getGroup(source);
|
||||
if (group == null) {
|
||||
return false;
|
||||
}
|
||||
if (group.getGroupLead() != source) {
|
||||
return false;
|
||||
}
|
||||
PlayerCharacter target = SessionManager.getPlayerCharacterByID(msg.getTargetID());
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
if (target == source) { // Can't appoint self leader
|
||||
AppointGroupLeaderMsg reply = new AppointGroupLeaderMsg();
|
||||
reply.setResponse(1);
|
||||
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), reply);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change Group Leader
|
||||
if (!group.setGroupLead(target.getObjectUUID())) {
|
||||
return false; // failed to update group leader
|
||||
}
|
||||
// Refresh everyones group list
|
||||
GroupUpdateMsg gim = new GroupUpdateMsg();
|
||||
gim.setGroup(group);
|
||||
gim.setPlayer(target);
|
||||
gim.setMessageType(2);
|
||||
gim.addPlayer(source);
|
||||
|
||||
group.sendUpdate(gim);
|
||||
|
||||
// Disable Formation
|
||||
target.setFollow(false);
|
||||
gim = new GroupUpdateMsg();
|
||||
gim.setGroup(group);
|
||||
gim.setPlayer(target);
|
||||
gim.setMessageType(8);
|
||||
group.sendUpdate(gim);
|
||||
|
||||
String text = target.getFirstName() + " is the new group leader.";
|
||||
ChatManager.chatGroupInfo(source, text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.*;
|
||||
import engine.job.JobScheduler;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ArcLoginNotifyMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.HotzoneChangeMsg;
|
||||
import engine.net.client.msg.PetMsg;
|
||||
import engine.objects.*;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.session.Session;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
public class ArcLoginNotifyMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ArcLoginNotifyMsgHandler() {
|
||||
super(ArcLoginNotifyMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null) {
|
||||
Logger.error(ConfigManager.MB_WORLD_NAME.getValue()+ ".EnterWorld", "Unable to find player for session");
|
||||
origin.kickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Player not found.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// cancel logout Timer if exists
|
||||
if (player.getTimers().containsKey("Logout")) {
|
||||
|
||||
JobScheduler.getInstance().cancelScheduledJob(player.getTimers().get("Logout"));
|
||||
player.getTimers().remove("Logout");
|
||||
}
|
||||
player.setTimeStamp("logout", 0);
|
||||
|
||||
// refresh group window if still in group for both this player
|
||||
// and everyone else in the group
|
||||
|
||||
if (GroupManager.getGroup(player) != null) {
|
||||
GroupManager.RefreshMyGroupList(player, origin);
|
||||
GroupManager.RefreshOthersGroupList(player);
|
||||
}
|
||||
|
||||
player.setEnteredWorld(true);
|
||||
// Set player active
|
||||
player.resetRegenUpdateTime();
|
||||
player.setActive(true);
|
||||
|
||||
//player.sendAllEffects(player.getClientConnection());
|
||||
// Send Enter world message to guild
|
||||
|
||||
ChatManager.GuildEnterWorldMsg(player, origin);
|
||||
|
||||
// Send Guild, Nation and IC MOTD
|
||||
GuildManager.enterWorldMOTD(player);
|
||||
ChatManager.sendSystemMessage(player, ConfigManager.MB_WORLD_GREETING.getValue());
|
||||
|
||||
// Set player mask for QT
|
||||
if (player.getRace() != null && player.getRace().getToken() == -524731385)
|
||||
player.setObjectTypeMask(MBServerStatics.MASK_PLAYER | MBServerStatics.MASK_UNDEAD);
|
||||
else
|
||||
player.setObjectTypeMask(MBServerStatics.MASK_PLAYER);
|
||||
|
||||
// If player not already in world, then set them to bind loc and add
|
||||
// to world
|
||||
|
||||
if (player.newChar)
|
||||
player.newChar = false; // TODO Fix safe mode
|
||||
|
||||
// PowersManager.applyPower(player, player, new
|
||||
// Vector3f(0f, 0f, 0f), -1661758934, 50, false);
|
||||
|
||||
// Add player to the QT for tracking
|
||||
|
||||
player.setLoc(player.getLoc());
|
||||
|
||||
//send online status to friends.
|
||||
PlayerFriends.SendFriendsStatus(player, true);
|
||||
|
||||
// Handle too many simultaneous logins from the same forum account by disconnecting the other account(s)
|
||||
|
||||
Account thisAccount = SessionManager.getAccount(player);
|
||||
int maxAccounts = MBServerStatics.MAX_ACTIVE_GAME_ACCOUNTS_PER_DISCORD_ACCOUNT;
|
||||
|
||||
if (maxAccounts > 0) {
|
||||
|
||||
int count = 1;
|
||||
for (Account othAccount : SessionManager.getAllActiveAccounts()) {
|
||||
|
||||
if (othAccount.equals(thisAccount))
|
||||
continue;
|
||||
|
||||
if (thisAccount.discordAccount.equals(othAccount.discordAccount) == false)
|
||||
continue;
|
||||
|
||||
count++;
|
||||
|
||||
if (count > maxAccounts) {
|
||||
Session otherSession = SessionManager.getSession(othAccount);
|
||||
if (otherSession != null) {
|
||||
ClientConnection otherConn = otherSession.getConn();
|
||||
if (otherConn != null) {
|
||||
ChatManager.chatSystemInfo(player, "Only 4 accounts may be used simultaneously. Account '" + othAccount.getUname() + "' has been disconnected.");
|
||||
otherConn.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
player.setTimeStamp("logout", 0);
|
||||
|
||||
if (player.getPet() != null) {
|
||||
PetMsg pm = new PetMsg(5, player.getPet());
|
||||
Dispatch dispatch = Dispatch.borrow(player, pm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
//Send current hotzone
|
||||
Zone hotzone = ZoneManager.getHotZone();
|
||||
|
||||
if (hotzone != null) {
|
||||
HotzoneChangeMsg hcm = new HotzoneChangeMsg(hotzone.getObjectType().ordinal(), hotzone.getObjectUUID());
|
||||
Dispatch dispatch = Dispatch.borrow(player, hcm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
if (player.getGuild() != null && !player.getGuild().isErrant()) {
|
||||
Guild.UpdateClientAlliancesForPlayer(player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ArcSiegeSpireMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which requests that
|
||||
* siege spires be toggled on or off.
|
||||
*/
|
||||
|
||||
public class ArcSiegeSpireMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ArcSiegeSpireMsgHandler() {
|
||||
super(ArcSiegeSpireMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player;
|
||||
Building spire;
|
||||
ArcSiegeSpireMsg msg;
|
||||
|
||||
msg = (ArcSiegeSpireMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
spire = (Building) DbManager.getObject(GameObjectType.Building, msg.getBuildingUUID());
|
||||
|
||||
if (spire == null)
|
||||
return true;
|
||||
|
||||
if (spire.getCity() == null)
|
||||
return true;
|
||||
|
||||
spire.getCity().transactionLock.writeLock().lock();
|
||||
|
||||
try{
|
||||
|
||||
|
||||
//can't activate a spire that's not rank 1.
|
||||
|
||||
if (spire.getRank() < 1)
|
||||
return true;
|
||||
|
||||
// can't activate a spire without a city
|
||||
|
||||
if (spire.getCity() == null)
|
||||
return true;
|
||||
|
||||
// Must have management authority for the spire
|
||||
|
||||
if ((player.getGuild().equals(spire.getGuild()) == false)
|
||||
|| (GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false) )
|
||||
return true;
|
||||
|
||||
// Handle case where spire is sabotaged
|
||||
|
||||
if (spire.getTimeStamp("DISABLED") > System.currentTimeMillis()) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 174); //This siege spire cannot be toggled yet.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle case where spire's toggle delay hasn't yet passed
|
||||
|
||||
if (spire.getTimeStamp("TOGGLEDELAY") > System.currentTimeMillis()) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 174); //This siege spire cannot be toggled yet.
|
||||
return true;
|
||||
}
|
||||
|
||||
// This protocol message is a toggle. If it's currently active then disable
|
||||
// the spire.
|
||||
|
||||
if (spire.isSpireIsActive()) {
|
||||
spire.disableSpire(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be enough gold on the spire to turn it on
|
||||
|
||||
if (!spire.hasFunds(5000)){
|
||||
ErrorPopupMsg.sendErrorPopup(player, 127); // Not enough gold in strongbox
|
||||
return true;
|
||||
}
|
||||
|
||||
if (spire.getStrongboxValue() < 5000) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 127); // Not enough gold in strongbox
|
||||
return true;
|
||||
}
|
||||
|
||||
spire.transferGold(-5000,false);
|
||||
spire.enableSpire();
|
||||
|
||||
// Spire is now enabled. Reset the toggle delay
|
||||
|
||||
spire.setTimeStamp("TOGGLEDELAY", System.currentTimeMillis() + (long) 10 * 60 * 1000);
|
||||
}catch(Exception e){
|
||||
Logger.error(e);
|
||||
}finally{
|
||||
spire.getCity().transactionLock.writeLock().unlock();
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ArcViewAssetTransactionsMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.Warehouse;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which transfers
|
||||
* gold between a building's strongbox and a player character.
|
||||
*/
|
||||
|
||||
public class ArcViewAssetTransactionsMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ArcViewAssetTransactionsMsgHandler() {
|
||||
super(ArcViewAssetTransactionsMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player;
|
||||
ArcViewAssetTransactionsMsg msg;
|
||||
ArcViewAssetTransactionsMsg newMsg;
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
Dispatch dispatch;
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
msg = (ArcViewAssetTransactionsMsg) baseMsg;
|
||||
|
||||
Warehouse warehouse = Warehouse.warehouseByBuildingUUID.get(msg.getWarehouseID());
|
||||
|
||||
if (warehouse == null)
|
||||
return true;
|
||||
|
||||
newMsg = new ArcViewAssetTransactionsMsg(warehouse,msg);
|
||||
newMsg.configure();
|
||||
|
||||
dispatch = Dispatch.borrow(player, newMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.SupportMsgType;
|
||||
import engine.Enum.TaxType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* protecting and unprotecting city assets
|
||||
*/
|
||||
public class AssetSupportMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public AssetSupportMsgHandler() {
|
||||
super(AssetSupportMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
NPC vendor;
|
||||
Building targetBuilding;
|
||||
Dispatch dispatch;
|
||||
|
||||
AssetSupportMsg msg;
|
||||
CityAssetMsg outMsg;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (AssetSupportMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
vendor = NPC.getFromCache(msg.getNpcID());
|
||||
|
||||
if (msg.getMessageType() !=6 && msg.getMessageType() != 7){
|
||||
if (vendor == null)
|
||||
return true;
|
||||
|
||||
vendor.getBuilding();
|
||||
|
||||
if (vendor.getBuilding() == null)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SupportMsgType supportType = SupportMsgType.typeLookup.get(msg.getMessageType());
|
||||
|
||||
if (supportType == null) {
|
||||
supportType = Enum.SupportMsgType.NONE;
|
||||
Logger.error("No enumeration for support type" + msg.getMessageType());
|
||||
}
|
||||
switch (supportType) {
|
||||
|
||||
case PROTECT:
|
||||
targetBuilding = BuildingManager.getBuildingFromCache(msg.getProtectedBuildingID());
|
||||
protectAsset(msg,targetBuilding, vendor, origin);
|
||||
break;
|
||||
case UNPROTECT:
|
||||
targetBuilding = BuildingManager.getBuildingFromCache(msg.getProtectedBuildingID());
|
||||
unprotectAsset(targetBuilding, vendor, origin);
|
||||
break;
|
||||
case VIEWUNPROTECTED:
|
||||
outMsg = new CityAssetMsg();
|
||||
outMsg.setBuildingID(msg.getBuildingID());
|
||||
outMsg.configure();
|
||||
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
case REMOVETAX:
|
||||
targetBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (targetBuilding == null)
|
||||
return true;
|
||||
|
||||
targetBuilding.removeTaxes();
|
||||
unprotectAsset(targetBuilding, null, origin);
|
||||
|
||||
ManageCityAssetsMsg mca = new ManageCityAssetsMsg(origin.getPlayerCharacter(),targetBuilding);
|
||||
|
||||
// Action TYPE
|
||||
mca.actionType = 3;
|
||||
mca.setTargetType(targetBuilding.getObjectType().ordinal());
|
||||
mca.setTargetID(targetBuilding.getObjectUUID());
|
||||
mca.setTargetType3(targetBuilding.getObjectType().ordinal());
|
||||
mca.setTargetID3(targetBuilding.getObjectUUID());
|
||||
mca.setAssetName1(targetBuilding.getName());
|
||||
mca.setUnknown54(1);
|
||||
dispatch = Dispatch.borrow(player, mca);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
|
||||
case ACCEPTTAX: //AcceptTax
|
||||
|
||||
targetBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (targetBuilding == null)
|
||||
return true;
|
||||
|
||||
targetBuilding.acceptTaxes();
|
||||
|
||||
mca = new ManageCityAssetsMsg(origin.getPlayerCharacter(),targetBuilding);
|
||||
|
||||
// Action TYPE
|
||||
mca.actionType = 3;
|
||||
mca.setTargetType(targetBuilding.getObjectType().ordinal());
|
||||
mca.setTargetID(targetBuilding.getObjectUUID());
|
||||
mca.setTargetType3(targetBuilding.getObjectType().ordinal());
|
||||
mca.setTargetID3(targetBuilding.getObjectUUID());
|
||||
mca.setAssetName1(targetBuilding.getName());
|
||||
mca.setUnknown54(1);
|
||||
|
||||
dispatch = Dispatch.borrow(player, mca);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
dispatch = Dispatch.borrow(player, baseMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void protectAsset(AssetSupportMsg msg, Building targetBuilding, NPC vendor, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
Zone serverZone;
|
||||
City serverCity;
|
||||
ManageNPCMsg outMsg;
|
||||
int protectionSlots;
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
if (targetBuilding == null)
|
||||
return;
|
||||
|
||||
serverZone = vendor.getParentZone();
|
||||
|
||||
if (serverZone == null)
|
||||
return;
|
||||
|
||||
serverCity = City.GetCityFromCache(serverZone.getPlayerCityUUID());
|
||||
|
||||
if (serverCity == null)
|
||||
return;
|
||||
|
||||
if (!serverCity.isLocationOnCityZone(targetBuilding.getLoc())){
|
||||
ErrorPopupMsg.sendErrorMsg(origin.getPlayerCharacter(), "Structura must be on city zone for to protect.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((serverCity.getTOL() == null)|| (serverCity.getTOL().getRank() < 1))
|
||||
return;
|
||||
|
||||
if (serverCity.protectionEnforced == false) {
|
||||
ErrorPopupMsg.sendErrorMsg(origin.getPlayerCharacter(), "Runemaster can not protect structura during bane!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (serverCity.getRuneMaster() == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(origin.getPlayerCharacter(), "Runemaster is needed for to protect structura!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Enforce runemaster protection limits
|
||||
|
||||
protectionSlots = (2 * serverCity.getRuneMaster().getRank()) + 6;
|
||||
|
||||
if (serverCity.getRuneMaster().getProtectedBuildings().size() >=
|
||||
protectionSlots) {
|
||||
ErrorPopupMsg.sendErrorMsg(origin.getPlayerCharacter(), "Runemaster can only protect " + protectionSlots + " structura!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.getWeeklyTax() != 0){
|
||||
if (!serverCity.getTOL().addProtectionTax(targetBuilding, origin.getPlayerCharacter(), TaxType.WEEKLY, msg.getWeeklyTax(), msg.getEnforceKOS() == 1 ? true: false)){
|
||||
ErrorPopupMsg.sendErrorMsg(origin.getPlayerCharacter(), "Failed to add taxes to building.");
|
||||
return;
|
||||
}
|
||||
targetBuilding.setProtectionState(Enum.ProtectionState.PENDING);
|
||||
}else if (msg.getProfitTax() != 0){
|
||||
if (!serverCity.getTOL().addProtectionTax(targetBuilding, origin.getPlayerCharacter(), TaxType.PROFIT, msg.getProfitTax(), msg.getEnforceKOS() == 1 ? true: false)){
|
||||
ErrorPopupMsg.sendErrorMsg(origin.getPlayerCharacter(), "Failed to add taxes to building.");
|
||||
return;
|
||||
}
|
||||
targetBuilding.setProtectionState(Enum.ProtectionState.PENDING);
|
||||
}else
|
||||
targetBuilding.setProtectionState(Enum.ProtectionState.CONTRACT);
|
||||
|
||||
|
||||
|
||||
outMsg = new ManageNPCMsg(vendor);
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
private static void unprotectAsset(Building targetBuilding, NPC vendor, ClientConnection origin) {
|
||||
|
||||
if (targetBuilding == null)
|
||||
return;
|
||||
|
||||
// Early exit if UUID < the last database derived building UUID.
|
||||
|
||||
if (targetBuilding.getProtectionState() == Enum.ProtectionState.NPC) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetBuilding.getProtectionState() == engine.Enum.ProtectionState.NONE)
|
||||
return;
|
||||
|
||||
if (GuildStatusController.isInnerCouncil(origin.getPlayerCharacter().getGuildStatus()) == false)
|
||||
return;
|
||||
|
||||
targetBuilding.removeTaxes();
|
||||
|
||||
targetBuilding.setProtectionState(engine.Enum.ProtectionState.NONE);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GuildHistoryType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.BanishUnbanishMsg;
|
||||
import engine.net.client.msg.guild.GuildListMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildHistory;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
public class BanishUnbanishHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public BanishUnbanishHandler() {
|
||||
super(BanishUnbanishMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
BanishUnbanishMsg msg = (BanishUnbanishMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
int target = msg.getTarget();
|
||||
PlayerCharacter source = origin.getPlayerCharacter();
|
||||
|
||||
if(source == null || source.getGuild().isErrant() || source.getGuild().getObjectUUID() == 0)
|
||||
return true;
|
||||
|
||||
if (GuildStatusController.isGuildLeader(source.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(source.getGuildStatus()) == false)
|
||||
return true;
|
||||
|
||||
if (source.getObjectUUID() == target) {
|
||||
ErrorPopupMsg.sendErrorPopup(source, 103); // You may not banish this char
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
Guild guild = source.getGuild();
|
||||
PlayerCharacter realizedTarget = PlayerCharacter.getFromCache(target);
|
||||
|
||||
if(realizedTarget != null) {
|
||||
// Guild leader can't leave guild. must pass GL or disband
|
||||
if ( GuildStatusController.isGuildLeader(realizedTarget.getGuildStatus()) == false) {
|
||||
//ICs cannot banish other ICs
|
||||
if (!(GuildStatusController.isInnerCouncil(realizedTarget.getGuildStatus()) && GuildStatusController.isGuildLeader(source.getGuildStatus()) == false)) {
|
||||
success = true;
|
||||
if (msg.getMsgType() == 1){
|
||||
if (!DbManager.GuildQueries.ADD_TO_BANISHED_FROM_GUILDLIST(guild.getObjectUUID(), realizedTarget.getObjectUUID())){
|
||||
ChatManager.chatGuildError(source, "Failed To unbanish " + realizedTarget.getName());
|
||||
return true;
|
||||
}
|
||||
guild.getBanishList().remove(realizedTarget);
|
||||
}
|
||||
|
||||
|
||||
else{
|
||||
|
||||
if (!DbManager.GuildQueries.ADD_TO_BANISHED_FROM_GUILDLIST(guild.getObjectUUID(), realizedTarget.getObjectUUID())){
|
||||
ChatManager.chatGuildError(source, "Failed To Banish " + realizedTarget.getName());
|
||||
return true;
|
||||
}
|
||||
guild.removePlayer(realizedTarget, GuildHistoryType.BANISHED);
|
||||
guild.getBanishList().add(realizedTarget); //TODO we might encapsulate this a bit better; also not sure that a list of PC objects is really ideal
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (guild.getGuildLeaderUUID() != target) {
|
||||
PlayerCharacter toBanish = PlayerCharacter.getPlayerCharacter(target);
|
||||
if (toBanish == null)
|
||||
return true;
|
||||
//already added previously.
|
||||
if (SessionManager.getPlayerCharacterByID(toBanish.getObjectUUID()) != null)
|
||||
return true;
|
||||
|
||||
if(DbManager.GuildQueries.BANISH_FROM_GUILD_OFFLINE(target, GuildStatusController.isGuildLeader(source.getGuildStatus())) != 0) {
|
||||
|
||||
success = true;
|
||||
|
||||
//Set guild history
|
||||
|
||||
if (DbManager.GuildQueries.ADD_TO_GUILDHISTORY(guild.getObjectUUID(), toBanish, DateTime.now(), GuildHistoryType.BANISHED)){
|
||||
GuildHistory guildHistory = new GuildHistory(toBanish.getGuildUUID(),toBanish.getGuild().getName(),DateTime.now(), GuildHistoryType.BANISHED) ;
|
||||
toBanish.getGuildHistory().add(guildHistory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(success) {
|
||||
//TODO re enable this once we get unbanish working!!!!
|
||||
//DbManager.GuildQueries.ADD_TO_BANISHED_FROM_GUILDLIST(guild.getobjectUUID(), target);
|
||||
|
||||
// Send left guild message to rest of guild
|
||||
String targetName = PlayerCharacter.getFirstName(target);
|
||||
ChatManager.chatGuildInfo(guild,
|
||||
targetName + " has been banished from " + guild.getName() + '.');
|
||||
GuildListMsg guildListMsg = new GuildListMsg(guild);
|
||||
dispatch = Dispatch.borrow(source, guildListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
} else {
|
||||
ErrorPopupMsg.sendErrorPopup(source, 103); // You may not banish this char
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.BreakFealtyMsg;
|
||||
import engine.net.client.msg.guild.SendGuildEntryMsg;
|
||||
import engine.objects.*;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.session.Session;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BreakFealtyHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public BreakFealtyHandler() {
|
||||
super(BreakFealtyMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
BreakFealtyMsg bfm;
|
||||
PlayerCharacter player;
|
||||
Guild toBreak;
|
||||
Guild guild;
|
||||
Dispatch dispatch;
|
||||
|
||||
bfm = (BreakFealtyMsg) baseMsg;
|
||||
|
||||
// get PlayerCharacter of person accepting invite
|
||||
|
||||
player = SessionManager.getPlayerCharacter(
|
||||
origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
toBreak = (Guild) DbManager.getObject(GameObjectType.Guild, bfm.getGuildUUID());
|
||||
|
||||
if (toBreak == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
guild = player.getGuild();
|
||||
|
||||
if (guild == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You do not belong to a guild!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (toBreak.isNPCGuild()){
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Only guild leader can break fealty!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (!DbManager.GuildQueries.UPDATE_PARENT(guild.getObjectUUID(),MBServerStatics.worldUUID)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (guild.getGuildState()) {
|
||||
case Sworn:
|
||||
guild.setNation(null);
|
||||
GuildManager.updateAllGuildTags(guild);
|
||||
GuildManager.updateAllGuildBinds(guild, null);
|
||||
break;
|
||||
case Province:
|
||||
guild.setNation(guild);
|
||||
GuildManager.updateAllGuildTags(guild);
|
||||
GuildManager.updateAllGuildBinds(guild, guild.getOwnedCity());
|
||||
break;
|
||||
}
|
||||
|
||||
guild.downgradeGuildState();
|
||||
|
||||
SendGuildEntryMsg msg = new SendGuildEntryMsg(player);
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
//Update Map.
|
||||
|
||||
final Session s = SessionManager.getSession(player);
|
||||
|
||||
City.lastCityUpdate = System.currentTimeMillis();
|
||||
|
||||
|
||||
ArrayList<PlayerCharacter> guildMembers = SessionManager.getActivePCsInGuildID(guild.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : guildMembers) {
|
||||
ChatManager.chatGuildInfo(member, guild.getName() + " has broke fealty from " + toBreak.getName() + '!');
|
||||
}
|
||||
|
||||
ArrayList<PlayerCharacter> breakFealtyMembers = SessionManager.getActivePCsInGuildID(toBreak.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : breakFealtyMembers) {
|
||||
ChatManager.chatGuildInfo(member, guild.getName() + " has broken fealty from " + toBreak.getName() + '!');
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!toBreak.getSubGuildList().contains(guild)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Failure to break fealty!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Only guild leader can break fealty!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Bane.getBaneByAttackerGuild(guild) != null)
|
||||
{
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You may break fealty with active bane!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!DbManager.GuildQueries.UPDATE_PARENT(guild.getObjectUUID(),MBServerStatics.worldUUID)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (guild.getGuildState()) {
|
||||
case Sworn:
|
||||
guild.setNation(null);
|
||||
GuildManager.updateAllGuildTags(guild);
|
||||
GuildManager.updateAllGuildBinds(guild, null);
|
||||
break;
|
||||
case Province:
|
||||
guild.setNation(guild);
|
||||
GuildManager.updateAllGuildTags(guild);
|
||||
GuildManager.updateAllGuildBinds(guild, guild.getOwnedCity());
|
||||
break;
|
||||
}
|
||||
|
||||
guild.downgradeGuildState();
|
||||
toBreak.getSubGuildList().remove(guild);
|
||||
|
||||
if (toBreak.getSubGuildList().isEmpty())
|
||||
toBreak.downgradeGuildState();
|
||||
|
||||
SendGuildEntryMsg msg = new SendGuildEntryMsg(player);
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
//Update Map.
|
||||
|
||||
final Session s = SessionManager.getSession(player);
|
||||
|
||||
City.lastCityUpdate = System.currentTimeMillis();
|
||||
|
||||
|
||||
ArrayList<PlayerCharacter> guildMembers = SessionManager.getActivePCsInGuildID(guild.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : guildMembers) {
|
||||
ChatManager.chatGuildInfo(member, guild.getName() + " has broke fealty from " + toBreak.getName() + '!');
|
||||
}
|
||||
|
||||
ArrayList<PlayerCharacter> breakFealtyMembers = SessionManager.getActivePCsInGuildID(toBreak.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : breakFealtyMembers) {
|
||||
ChatManager.chatGuildInfo(member, guild.getName() + " has broken fealty from " + toBreak.getName() + '!');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ChangeAltitudeMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.objects.AbstractCharacter;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.Regions;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
public class ChangeAltitudeHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ChangeAltitudeHandler() {
|
||||
super(ChangeAltitudeMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
ChangeAltitudeMsg msg = (ChangeAltitudeMsg) baseMsg;
|
||||
|
||||
PlayerCharacter pc = origin.getPlayerCharacter();
|
||||
if (pc == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AbstractCharacter.CanFly(pc))
|
||||
return false;
|
||||
|
||||
if (pc.isSwimming())
|
||||
return false;
|
||||
if (pc.getRegion() != null && !pc.getRegion().isOutside())
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Find out if we already have an altitude timer running and if so
|
||||
// do not process more alt change requests
|
||||
|
||||
if (pc.getTakeOffTime() != 0)
|
||||
return false;
|
||||
|
||||
|
||||
// remove all movement timers and jobs
|
||||
//TODO: test if they can fly
|
||||
|
||||
float targetAlt;
|
||||
float amount = msg.getAmountToMove();
|
||||
if (amount != 10 && amount != 60)
|
||||
return false;
|
||||
if (pc.getAltitude() == 60 && msg.up())
|
||||
return true;
|
||||
if (pc.getAltitude() == 0 && !msg.up())
|
||||
return true;
|
||||
|
||||
pc.update();
|
||||
pc.stopMovement(pc.getLoc());
|
||||
msg.setStartAlt(pc.getAltitude());
|
||||
if (msg.up()) {
|
||||
|
||||
pc.landingRegion = null;
|
||||
if (pc.getAltitude() == 0){
|
||||
Regions upRegion = pc.getRegion();
|
||||
if (upRegion != null){
|
||||
float startAlt = 0;
|
||||
Building regionBuilding = Regions.GetBuildingForRegion(upRegion);
|
||||
if (upRegion != null)
|
||||
startAlt = upRegion.lerpY(pc) - regionBuilding.getLoc().y;
|
||||
float rounded = startAlt *.10f;
|
||||
|
||||
rounded = ((int)rounded) * 10;
|
||||
|
||||
if (rounded < 0)
|
||||
rounded = 0;
|
||||
|
||||
|
||||
msg.setStartAlt(startAlt);
|
||||
targetAlt = rounded + amount;
|
||||
|
||||
if (targetAlt > 60)
|
||||
targetAlt = 60;
|
||||
|
||||
pc.setAltitude(startAlt);
|
||||
pc.setDesiredAltitude(targetAlt);
|
||||
}else{
|
||||
msg.setStartAlt(pc.getAltitude());
|
||||
targetAlt = pc.getAltitude() + amount;
|
||||
if (targetAlt > 60)
|
||||
targetAlt = 60;
|
||||
}
|
||||
}else{
|
||||
msg.setStartAlt(pc.getAltitude());
|
||||
|
||||
targetAlt = pc.getAltitude() + amount;
|
||||
if (targetAlt > 60)
|
||||
targetAlt = 60;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
msg.setStartAlt(pc.getAltitude());
|
||||
targetAlt = pc.getAltitude() - amount;
|
||||
if (targetAlt < 0)
|
||||
targetAlt = 0;
|
||||
}
|
||||
msg.setTargetAlt(targetAlt);
|
||||
if (pc.getAltitude() < 1 && targetAlt > pc.getAltitude()) {
|
||||
// char is on the ground and is about to start flight
|
||||
if (pc.getStamina() < 10) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (MBServerStatics.MOVEMENT_SYNC_DEBUG) {
|
||||
Logger.info ("Changing Altitude, moving=" + pc.isMoving() +
|
||||
" Current Loc " + pc.getLoc().getX() + ' ' + pc.getLoc().getZ() +
|
||||
" End Loc " + pc.getEndLoc().getX() + ' ' + pc.getEndLoc().getZ());
|
||||
}
|
||||
|
||||
if (msg.up()){
|
||||
pc.update();
|
||||
pc.setDesiredAltitude(targetAlt);
|
||||
pc.setTakeOffTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
else{
|
||||
Regions region = PlayerCharacter.InsideBuildingRegionGoingDown(pc);
|
||||
|
||||
|
||||
|
||||
if (region != null){
|
||||
float landingAltitude = 0;
|
||||
Building building = Regions.GetBuildingForRegion(region);
|
||||
if (building != null)
|
||||
landingAltitude = region.lerpY(pc) - building.getLoc().y;
|
||||
|
||||
if (landingAltitude >= targetAlt){
|
||||
pc.landingRegion = region;
|
||||
pc.landingAltitude = landingAltitude;
|
||||
pc.setDesiredAltitude(landingAltitude);
|
||||
}else{
|
||||
pc.landingRegion = null;
|
||||
pc.setDesiredAltitude(targetAlt);
|
||||
}
|
||||
|
||||
|
||||
}else
|
||||
pc.setDesiredAltitude(targetAlt);
|
||||
|
||||
pc.update();
|
||||
|
||||
|
||||
pc.setTakeOffTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add timer for height change cooldown, this also tells getLoc we are not moving
|
||||
//MovementManager.addChangeAltitudeTimer(pc, msg.getStartAlt(), msg.getTargetAlt(), (int)((MBServerStatics.HEIGHT_CHANGE_TIMER_MS * amount) + 100 ) );
|
||||
|
||||
// Add flight timer job to check stam and ground you when you run out
|
||||
//MovementManager.addFlightTimer(pc, msg, MBServerStatics.FLY_FREQUENCY_MS);
|
||||
//Send change altitude to all in range
|
||||
DispatchMessage.dispatchMsgToInterestArea(pc, msg, DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ChangeGuildLeaderMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.GuildInfoMsg;
|
||||
import engine.net.client.msg.guild.GuildListMsg;
|
||||
import engine.objects.City;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class ChangeGuildLeaderHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ChangeGuildLeaderHandler() {
|
||||
super(ChangeGuildLeaderMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
ChangeGuildLeaderMsg msg;
|
||||
PlayerCharacter sourcePlayer;
|
||||
PlayerCharacter targetPlayer;
|
||||
City city;
|
||||
|
||||
msg = (ChangeGuildLeaderMsg) baseMsg;
|
||||
sourcePlayer = origin.getPlayerCharacter();
|
||||
if (sourcePlayer == null)
|
||||
return true;
|
||||
if (GuildStatusController.isGuildLeader(sourcePlayer.getGuildStatus()) == false)
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
Guild glGuild = sourcePlayer.getGuild();
|
||||
|
||||
if (glGuild == null)
|
||||
return true;
|
||||
|
||||
if (!glGuild.isGuildLeader(sourcePlayer.getObjectUUID()))
|
||||
return true;
|
||||
targetPlayer = (PlayerCharacter) DbManager.getObject(GameObjectType.PlayerCharacter, msg.getTargetID());
|
||||
|
||||
|
||||
if (targetPlayer == null)
|
||||
return true;
|
||||
|
||||
if (GuildStatusController.isGuildLeader(targetPlayer.getGuildStatus()))
|
||||
return true;
|
||||
|
||||
if (!Guild.sameGuild(sourcePlayer.getGuild(),targetPlayer.getGuild()))
|
||||
return false;
|
||||
|
||||
|
||||
//updateSource will generate a new promote/demote screen for sourcePlayer
|
||||
//updateTarget will sync guild info for the target and all players in range
|
||||
|
||||
|
||||
|
||||
|
||||
String targetName = null;
|
||||
boolean isMale = true;
|
||||
boolean updateTarget;
|
||||
|
||||
Enum.GuildType t = Enum.GuildType.getGuildTypeFromInt(sourcePlayer.getGuild().getCharter());
|
||||
|
||||
|
||||
if (!DbManager.GuildQueries.SET_GUILD_LEADER(targetPlayer.getObjectUUID(), glGuild.getObjectUUID())){
|
||||
ChatManager.chatGuildError(sourcePlayer, "Failed to change guild leader!");
|
||||
return false;
|
||||
}
|
||||
|
||||
glGuild.setGuildLeader(targetPlayer);
|
||||
|
||||
|
||||
|
||||
if (glGuild.getOwnedCity() != null){
|
||||
city = glGuild.getOwnedCity();
|
||||
if (!city.transferGuildLeader(targetPlayer)){
|
||||
ChatManager.chatGuildError(sourcePlayer, "Failed to Transfer City Objects. Contact CCR!");
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
targetPlayer.setGuildLeader(true);
|
||||
targetPlayer.setInnerCouncil(true);
|
||||
targetPlayer.setFullMember(true);
|
||||
targetPlayer.incVer();
|
||||
targetName = targetPlayer.getFirstName();
|
||||
updateTarget = true;
|
||||
|
||||
|
||||
ChatManager.chatGuildInfo(sourcePlayer.getGuild(),
|
||||
targetName + " has been promoted to "
|
||||
+ "guild leader!");
|
||||
|
||||
//These values record a change, not the new value...
|
||||
|
||||
|
||||
|
||||
//updateOldGuildLeader
|
||||
sourcePlayer.setInnerCouncil(true);
|
||||
sourcePlayer.setFullMember(true);
|
||||
sourcePlayer.setGuildLeader(false);
|
||||
sourcePlayer.incVer();
|
||||
|
||||
GuildInfoMsg guildInfoMsg = new GuildInfoMsg(sourcePlayer, sourcePlayer.getGuild(), 2);
|
||||
Dispatch dispatch = Dispatch.borrow(sourcePlayer, guildInfoMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
GuildListMsg guildListMsg = new GuildListMsg(sourcePlayer.getGuild());
|
||||
|
||||
dispatch = Dispatch.borrow(sourcePlayer, guildListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
|
||||
if (targetPlayer != null) {
|
||||
if (updateTarget)
|
||||
DispatchMessage.sendToAllInRange(targetPlayer, new GuildInfoMsg(targetPlayer, targetPlayer.getGuild(), 2));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.ChangeRankMsg;
|
||||
import engine.net.client.msg.guild.GuildInfoMsg;
|
||||
import engine.net.client.msg.guild.GuildListMsg;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class ChangeRankHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ChangeRankHandler() {
|
||||
super(ChangeRankMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
ChangeRankMsg msg;
|
||||
PlayerCharacter sourcePlayer;
|
||||
PlayerCharacter targetPlayer;
|
||||
|
||||
msg = (ChangeRankMsg) baseMsg;
|
||||
sourcePlayer = origin.getPlayerCharacter();
|
||||
|
||||
targetPlayer = (PlayerCharacter) DbManager.getObject(GameObjectType.PlayerCharacter, msg.getPlayerUUID());
|
||||
|
||||
if (msg.getPlayerUUID() == 0)
|
||||
targetPlayer = sourcePlayer;
|
||||
|
||||
//updateSource will generate a new promote/demote screen for sourcePlayer
|
||||
//updateTarget will sync guild info for the target and all players in range
|
||||
|
||||
boolean updateSource = false, updateTarget = false;
|
||||
|
||||
if (sourcePlayer == null ||GuildStatusController.isInnerCouncil(sourcePlayer.getGuildStatus()) == false)
|
||||
return true;
|
||||
|
||||
if (targetPlayer != null && (targetPlayer.getGuild().equals(sourcePlayer.getGuild()) == false))
|
||||
return true;
|
||||
|
||||
String targetName = null;
|
||||
boolean isMale;
|
||||
|
||||
if (msg.getPreviousRank() != msg.getNewRank()) {
|
||||
Enum.GuildType t = Enum.GuildType.getGuildTypeFromInt(sourcePlayer.getGuild().getCharter());
|
||||
|
||||
if (targetPlayer != null) {
|
||||
targetPlayer.setGuildTitle(msg.getNewRank());
|
||||
|
||||
targetName = targetPlayer.getFirstName();
|
||||
isMale = targetPlayer.getRace().getRaceType().getCharacterSex().equals(Enum.CharacterSex.MALE);
|
||||
} else {
|
||||
DbManager.GuildQueries.UPDATE_GUILD_RANK_OFFLINE(msg.getPlayerUUID(), msg.getNewRank(), sourcePlayer.getGuild().getObjectUUID());
|
||||
|
||||
targetName = PlayerCharacter.getFirstName(msg.getPlayerUUID());
|
||||
isMale = true;
|
||||
}
|
||||
|
||||
ChatManager.chatGuildInfo(sourcePlayer.getGuild(),
|
||||
targetName + " has been "
|
||||
+ ((msg.getNewRank() > msg.getPreviousRank()) ? "pro" : "de") + "moted to "
|
||||
+ t.getRankForGender(msg.getNewRank(), isMale) + '!');
|
||||
updateSource = true;
|
||||
}
|
||||
|
||||
//These values record a change, not the new value...
|
||||
boolean icUpdate = false, recruitUpdate = false, taxUpdate = false;
|
||||
|
||||
//Handle the offline case..
|
||||
if (targetPlayer == null) {
|
||||
int updateMask = DbManager.GuildQueries.UPDATE_GUILD_STATUS_OFFLINE(msg.getPlayerUUID(),
|
||||
msg.getIc() > 0,
|
||||
msg.getRec() > 0,
|
||||
msg.getTax() > 0,
|
||||
sourcePlayer.getGuild().getObjectUUID());
|
||||
|
||||
//These values come from the updateIsStatusOffline function
|
||||
icUpdate = (updateMask & 4) > 0;
|
||||
recruitUpdate = (updateMask & 2) > 0;
|
||||
taxUpdate = (updateMask & 1) > 0;
|
||||
|
||||
if (targetName == null && updateMask > 0)
|
||||
targetName = PlayerCharacter.getFirstName(msg.getPlayerUUID());
|
||||
} else {
|
||||
icUpdate = (GuildStatusController.isInnerCouncil(targetPlayer.getGuildStatus()) != (msg.getIc() > 0)) && GuildStatusController.isGuildLeader(sourcePlayer.getGuildStatus());
|
||||
recruitUpdate = (GuildStatusController.isRecruiter(targetPlayer.getGuildStatus()) != (msg.getRec() > 0)) && GuildStatusController.isGuildLeader(sourcePlayer.getGuildStatus());
|
||||
taxUpdate = (GuildStatusController.isTaxCollector(targetPlayer.getGuildStatus()) != (msg.getTax() > 0)) && GuildStatusController.isGuildLeader(sourcePlayer.getGuildStatus());
|
||||
|
||||
//This logic branch only executes if targetPlayer has passed a null check...
|
||||
if (icUpdate){
|
||||
targetPlayer.setInnerCouncil(msg.getIc() > 0);
|
||||
targetPlayer.setFullMember(true);
|
||||
targetPlayer.incVer();
|
||||
}
|
||||
|
||||
if (recruitUpdate)
|
||||
targetPlayer.setRecruiter(msg.getRec() > 0);
|
||||
|
||||
if (taxUpdate)
|
||||
targetPlayer.setTaxCollector(msg.getTax() > 0);
|
||||
|
||||
if (targetName == null)
|
||||
targetName = targetPlayer.getFirstName();
|
||||
}
|
||||
|
||||
if (icUpdate) {
|
||||
ChatManager.chatGuildInfo(sourcePlayer.getGuild(),
|
||||
(msg.getIc() > 0)
|
||||
? targetName + " has been appointed to the inner council."
|
||||
: targetName + " is no longer a member of the inner council.");
|
||||
|
||||
updateSource = true;
|
||||
updateTarget = true;
|
||||
}
|
||||
|
||||
if (recruitUpdate) {
|
||||
updateSource = true;
|
||||
updateTarget = true;
|
||||
}
|
||||
|
||||
if (taxUpdate) {
|
||||
updateSource = true;
|
||||
updateTarget = true;
|
||||
}
|
||||
|
||||
if (targetPlayer != null) {
|
||||
targetPlayer.incVer();
|
||||
if (updateTarget)
|
||||
DispatchMessage.sendToAllInRange(targetPlayer, new GuildInfoMsg(targetPlayer, targetPlayer.getGuild(), 2));
|
||||
}
|
||||
|
||||
if (updateSource) {
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(sourcePlayer, new GuildInfoMsg(sourcePlayer, sourcePlayer.getGuild(), 2));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
dispatch = Dispatch.borrow(sourcePlayer, new GuildListMsg(sourcePlayer.getGuild()));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.Enum.GuildState;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ChatFilterMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which processes
|
||||
* client requests to abandon a building.
|
||||
*/
|
||||
public class ChannelMuteMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Instance variables
|
||||
|
||||
public ChannelMuteMsgHandler() {
|
||||
super(ChatFilterMsg.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void AbandonSingleAsset(PlayerCharacter sourcePlayer,
|
||||
Building targetBuilding) {
|
||||
|
||||
// Transfer the building asset ownership and refresh all clients
|
||||
|
||||
DbManager.BuildingQueries.CLEAR_FRIENDS_LIST(targetBuilding.getObjectUUID());
|
||||
targetBuilding.getFriends().clear();
|
||||
|
||||
DbManager.BuildingQueries.CLEAR_CONDEMNED_LIST(targetBuilding.getObjectUUID());
|
||||
targetBuilding.getCondemned().clear();
|
||||
targetBuilding.setOwner(null);
|
||||
targetBuilding.refreshGuild();
|
||||
}
|
||||
|
||||
private void AbandonAllCityObjects(PlayerCharacter sourcePlayer,
|
||||
Building targetBuilding) {
|
||||
Guild sourceGuild;
|
||||
Zone cityZone;
|
||||
|
||||
sourceGuild = sourcePlayer.getGuild();
|
||||
|
||||
if (sourceGuild == null)
|
||||
return;
|
||||
|
||||
if (sourceGuild.getSubGuildList().size() > 0) {
|
||||
ChatManager.chatCityError(sourcePlayer, "You Cannot abandon a nation city.");
|
||||
return;
|
||||
}
|
||||
|
||||
cityZone = ZoneManager.findSmallestZone(targetBuilding.getLoc());
|
||||
|
||||
// Can't abandon a tree not within a player city zone
|
||||
if (cityZone.isPlayerCity() == false)
|
||||
return;
|
||||
|
||||
if (targetBuilding.getCity().hasBeenTransfered == true) {
|
||||
ChatManager.chatCityError(sourcePlayer, "City can only be abandoned once per rebooting.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Guild no longer owns his tree.
|
||||
if (!DbManager.GuildQueries.SET_GUILD_OWNED_CITY(sourceGuild.getObjectUUID(), 0)) {
|
||||
Logger.error( "Failed to update Owned City to Database");
|
||||
return;
|
||||
}
|
||||
|
||||
sourceGuild.setCityUUID(0);
|
||||
sourceGuild.setGuildState(GuildState.Errant);
|
||||
sourceGuild.setNation(null);
|
||||
|
||||
// Transfer the city assets
|
||||
TransferCityAssets(sourcePlayer, targetBuilding);
|
||||
|
||||
GuildManager.updateAllGuildTags(sourceGuild);
|
||||
GuildManager.updateAllGuildBinds(sourceGuild, null);
|
||||
|
||||
}
|
||||
|
||||
private void TransferCityAssets(PlayerCharacter sourcePlayer,
|
||||
Building cityTOL) {
|
||||
|
||||
Zone cityZone;
|
||||
|
||||
// Build list of buildings within this parent zone
|
||||
cityZone = ZoneManager.findSmallestZone(cityTOL.getLoc());
|
||||
|
||||
for (Building cityBuilding : cityZone.zoneBuildingSet) {
|
||||
|
||||
Blueprint cityBlueprint;
|
||||
cityBlueprint = cityBuilding.getBlueprint();
|
||||
|
||||
// Buildings without blueprints cannot be abandoned
|
||||
if (cityBlueprint == null)
|
||||
continue;
|
||||
|
||||
// Transfer ownership of valid city assets
|
||||
if ((cityBlueprint.getBuildingGroup() == BuildingGroup.TOL)
|
||||
|| (cityBlueprint.getBuildingGroup() == BuildingGroup.SPIRE)
|
||||
|| (cityBlueprint.getBuildingGroup() == BuildingGroup.BARRACK)
|
||||
|| (cityBlueprint.isWallPiece())
|
||||
|| (cityBuilding.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE))
|
||||
AbandonSingleAsset(sourcePlayer, cityBuilding);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.CityChoiceMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.TeleportRepledgeListMsg;
|
||||
import engine.objects.City;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* client's tcp connection open.
|
||||
*/
|
||||
|
||||
public class CityChoiceMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public CityChoiceMsgHandler() {
|
||||
super(CityChoiceMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
Dispatch dispatch;
|
||||
|
||||
CityChoiceMsg msg = (CityChoiceMsg) baseMsg;
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
switch (msg.getMsgType()) {
|
||||
case 5:
|
||||
TeleportRepledgeListMsg trlm = new TeleportRepledgeListMsg(player, false);
|
||||
trlm.configure();
|
||||
dispatch = Dispatch.borrow(player, trlm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case 3:
|
||||
City city = City.getCity(msg.getCityID());
|
||||
|
||||
if (city == null)
|
||||
return true;
|
||||
|
||||
Guild cityGuild = city.getGuild();
|
||||
|
||||
if (cityGuild == null)
|
||||
return true;
|
||||
|
||||
if (player.getLevel() < cityGuild.getRepledgeMin() || player.getLevel() > cityGuild.getRepledgeMax())
|
||||
return true;
|
||||
|
||||
//if repledge, reguild the player but set his building now.
|
||||
|
||||
GuildManager.joinGuild(player, cityGuild, city.getObjectUUID(), Enum.GuildHistoryType.JOIN);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.db.archive.CityRecord;
|
||||
import engine.db.archive.DataWarehouse;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClaimAssetMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.objects.Blueprint;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import static engine.math.FastMath.sqr;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* client's tcp connection open.
|
||||
*/
|
||||
public class ClaimAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Instance variables
|
||||
|
||||
private final ReentrantReadWriteLock claimLock = new ReentrantReadWriteLock();
|
||||
|
||||
public ClaimAssetMsgHandler() {
|
||||
super(ClaimAssetMsg.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
this.claimLock.writeLock().lock();
|
||||
|
||||
try{
|
||||
PlayerCharacter sourcePlayer;
|
||||
Building targetBuilding;
|
||||
Blueprint blueprint;
|
||||
ClaimAssetMsg msg;
|
||||
int targetUUID;
|
||||
|
||||
msg = (ClaimAssetMsg) baseMsg;
|
||||
targetUUID = msg.getUUID();
|
||||
|
||||
sourcePlayer = origin.getPlayerCharacter();
|
||||
targetBuilding = BuildingManager.getBuildingFromCache(targetUUID);
|
||||
|
||||
// Oops! *** Refactor: Log error
|
||||
|
||||
if ((sourcePlayer == null) ||
|
||||
(targetBuilding == null))
|
||||
return true;
|
||||
|
||||
// Player must be reasonably close to building in order to claim
|
||||
|
||||
if (sourcePlayer.getLoc().distanceSquared2D(targetBuilding.getLoc()) > sqr(100))
|
||||
return true;
|
||||
|
||||
// Early exit if object to be claimed is not errant
|
||||
|
||||
if (targetBuilding.getOwnerUUID() != 0)
|
||||
return true;
|
||||
|
||||
|
||||
// Early exit if UUID < the last database derived building UUID.
|
||||
|
||||
if (targetBuilding.getProtectionState() == Enum.ProtectionState.NPC) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Early exit if claiming player does not
|
||||
// have a guild.
|
||||
|
||||
// Errant players cannot claim
|
||||
|
||||
if (sourcePlayer.getGuild().isErrant())
|
||||
return true;
|
||||
|
||||
// Can't claim an object without a blueprint
|
||||
|
||||
if (targetBuilding.getBlueprintUUID() == 0)
|
||||
return true;
|
||||
|
||||
blueprint = targetBuilding.getBlueprint();
|
||||
|
||||
//cant claim mine this way.
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.MINE)
|
||||
return true;
|
||||
|
||||
// Players cannot claim shrines
|
||||
|
||||
if ((targetBuilding.getBlueprint().getBuildingGroup() == BuildingGroup.SHRINE))
|
||||
return true;
|
||||
|
||||
// Can't claim a tree if your guild already owns one
|
||||
// *** Refactor : Send error to player here
|
||||
|
||||
if ((sourcePlayer.getGuild().isNation()) &&
|
||||
(blueprint.getBuildingGroup() == BuildingGroup.TOL))
|
||||
return true;
|
||||
|
||||
// Process the transfer of the building(s)
|
||||
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.TOL) {
|
||||
targetBuilding.getCity().claim(sourcePlayer);
|
||||
|
||||
// Push transfer of city to data warehouse
|
||||
CityRecord cityRecord = CityRecord.borrow(targetBuilding.getCity(), Enum.RecordEventType.TRANSFER);
|
||||
DataWarehouse.pushToWarehouse(cityRecord);
|
||||
|
||||
} else
|
||||
targetBuilding.claim(sourcePlayer);
|
||||
|
||||
} catch(Exception e){
|
||||
Logger.error("ClaimAssetMsgHandler", e.getMessage());
|
||||
}finally{
|
||||
this.claimLock.writeLock().unlock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* client's tcp connection open.
|
||||
*/
|
||||
public class ClaimGuildTreeMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Instance variables
|
||||
|
||||
private final ReentrantReadWriteLock claimLock = new ReentrantReadWriteLock();
|
||||
private static final int RENAME_TREE = 2;
|
||||
private static final int BIND_TREE = 3;
|
||||
private static final int OPEN_CITY = 4;
|
||||
private static final int CLOSE_CITY = 5;
|
||||
|
||||
public ClaimGuildTreeMsgHandler() {
|
||||
super(ClaimGuildTreeMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
this.claimLock.writeLock().lock();
|
||||
|
||||
try{
|
||||
PlayerCharacter sourcePlayer;
|
||||
Building building;
|
||||
Blueprint blueprint;
|
||||
Zone playerZone= null;
|
||||
City playerCity= null;
|
||||
ClaimGuildTreeMsg msg;
|
||||
int targetUUID;
|
||||
Dispatch dispatch;
|
||||
|
||||
msg = (ClaimGuildTreeMsg) baseMsg;
|
||||
targetUUID = msg.getTargetID();
|
||||
|
||||
sourcePlayer = origin.getPlayerCharacter();
|
||||
building = BuildingManager.getBuildingFromCache(targetUUID);
|
||||
|
||||
if (building != null)
|
||||
playerZone = building.getParentZone();
|
||||
|
||||
if (playerZone != null)
|
||||
playerCity = City.getCity(playerZone.getPlayerCityUUID());
|
||||
|
||||
// Oops! *** Refactor: Log error
|
||||
switch (msg.getMessageType()){
|
||||
case RENAME_TREE:
|
||||
if ((sourcePlayer == null) ||
|
||||
(building == null) || playerZone == null ||playerCity == null)
|
||||
return true;
|
||||
|
||||
// Early exit if object to be claimed is not errant
|
||||
|
||||
if (building.getOwnerUUID() == 0)
|
||||
return true;
|
||||
|
||||
// Errant players cannot rename
|
||||
|
||||
if (sourcePlayer.getGuild().isErrant())
|
||||
return true;
|
||||
|
||||
// Can't rename an object without a blueprint
|
||||
|
||||
if (building.getBlueprintUUID() == 0)
|
||||
return true;
|
||||
|
||||
blueprint = building.getBlueprint();
|
||||
|
||||
//can only rename tree this way.
|
||||
if (blueprint.getBuildingGroup() != BuildingGroup.TOL)
|
||||
return true;
|
||||
|
||||
//dont rename if guild is null
|
||||
if (building.getGuild().isErrant())
|
||||
return true;
|
||||
|
||||
if (!ManageCityAssetMsgHandler.playerCanManageNotFriends(sourcePlayer, building))
|
||||
return true;
|
||||
|
||||
|
||||
if (!playerCity.renameCity(msg.getTreeName())){
|
||||
ChatManager.chatSystemError(sourcePlayer, "Failed to rename city!");
|
||||
return true;
|
||||
}
|
||||
|
||||
GuildTreeStatusMsg gtsm = new GuildTreeStatusMsg(building,sourcePlayer);
|
||||
gtsm.configure();
|
||||
dispatch = Dispatch.borrow(sourcePlayer, gtsm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
CityZoneMsg czm = new CityZoneMsg(2,playerZone.getLoc().x, playerZone.getLoc().y, playerZone.getLoc().z, playerCity.getCityName(),playerZone, Enum.CityBoundsType.ZONE.extents, Enum.CityBoundsType.ZONE.extents);
|
||||
DispatchMessage.dispatchMsgToAll(czm);
|
||||
|
||||
break;
|
||||
case BIND_TREE:
|
||||
|
||||
Guild pcGuild = sourcePlayer.getGuild();
|
||||
|
||||
//test tree is valid for binding, same guild or same nation
|
||||
if (!Guild.sameNation(pcGuild, building.getGuild())) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (building.getGuild().isErrant())
|
||||
return true;
|
||||
|
||||
|
||||
//get bind city
|
||||
Zone zone =building.getParentZone();
|
||||
|
||||
if (zone == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(sourcePlayer, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (playerCity == null && building.getGuild() != null)
|
||||
playerCity = building.getGuild().getOwnedCity();
|
||||
|
||||
if (playerCity == null)
|
||||
return true;
|
||||
|
||||
|
||||
sourcePlayer.setBindBuildingID(building.getObjectUUID());
|
||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case OPEN_CITY:
|
||||
case CLOSE_CITY:
|
||||
if ((sourcePlayer == null) ||
|
||||
(building == null) || playerZone == null ||playerCity == null)
|
||||
return true;
|
||||
|
||||
if (!ManageCityAssetMsgHandler.playerCanManageNotFriends(sourcePlayer, building))
|
||||
return true;
|
||||
|
||||
boolean open = (msg.getMessageType() == OPEN_CITY);
|
||||
|
||||
if (!playerCity.openCity(open)){
|
||||
ErrorPopupMsg.sendErrorMsg(sourcePlayer, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} catch(Exception e){
|
||||
Logger.error( e.getMessage());
|
||||
}finally{
|
||||
try{
|
||||
this.claimLock.writeLock().unlock();
|
||||
}catch(Exception e){
|
||||
Logger.info("failClaimsync");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.DestroyBuildingMsg;
|
||||
import engine.objects.Blueprint;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.City;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message where the
|
||||
* client is requesting a building be destroyed.
|
||||
*/
|
||||
|
||||
public class DestroyBuildingHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public DestroyBuildingHandler() {
|
||||
super(DestroyBuildingMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter pc = origin.getPlayerCharacter();
|
||||
|
||||
DestroyBuildingMsg msg;
|
||||
msg = (DestroyBuildingMsg) baseMsg;
|
||||
|
||||
int buildingUUID = msg.getUUID();
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(buildingUUID);
|
||||
;
|
||||
if (pc == null || building == null)
|
||||
return true;
|
||||
|
||||
Blueprint blueprint;
|
||||
|
||||
blueprint = building.getBlueprint();
|
||||
|
||||
// Can't destroy buildings without a blueprint.
|
||||
|
||||
if (blueprint == null)
|
||||
return true;
|
||||
|
||||
// Cannot destroy Oblivion database derived buildings.
|
||||
|
||||
if (building.getProtectionState() == Enum.ProtectionState.NPC) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(building, pc))
|
||||
return true;
|
||||
|
||||
// Can't destroy a tree of life
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.TOL)
|
||||
return true;
|
||||
|
||||
// Can't destroy a shrine
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.SHRINE)
|
||||
return true;
|
||||
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.MINE)
|
||||
return true;
|
||||
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.RUNEGATE)
|
||||
return true;
|
||||
|
||||
// Turn off spire if destoying
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.SPIRE)
|
||||
building.disableSpire(true);
|
||||
|
||||
if (blueprint.getBuildingGroup() == BuildingGroup.WAREHOUSE) {
|
||||
|
||||
City city = building.getCity();
|
||||
|
||||
if (city != null)
|
||||
city.setWarehouseBuildingID(0);
|
||||
}
|
||||
|
||||
building.setRank(-1);
|
||||
WorldGrid.RemoveWorldObject(building);
|
||||
WorldGrid.removeObject(building);
|
||||
building.getParentZone().zoneBuildingSet.remove(building);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.DisbandGroupMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class DisbandGroupHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public DisbandGroupHandler() {
|
||||
super(DisbandGroupMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter source = SessionManager.getPlayerCharacter(origin);
|
||||
if (source == null) {
|
||||
return false;
|
||||
}
|
||||
Group group = GroupManager.getGroup(source);
|
||||
if (group == null) {
|
||||
return false;
|
||||
}
|
||||
if (group.getGroupLead() != source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear all group member lists
|
||||
GroupUpdateMsg gim = new GroupUpdateMsg();
|
||||
gim.setGroup(group);
|
||||
gim.setMessageType(4);
|
||||
|
||||
// send the disbanded popup to everyone in group
|
||||
group.sendUpdate(gim);
|
||||
|
||||
// cleanup group
|
||||
GroupManager.deleteGroup(group);
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GuildHistoryType;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.db.archive.DataWarehouse;
|
||||
import engine.db.archive.GuildRecord;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.DisbandGuildMsg;
|
||||
import engine.net.client.msg.guild.LeaveGuildMsg;
|
||||
import engine.objects.Bane;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class DisbandGuildHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public DisbandGuildHandler() {
|
||||
super(DisbandGuildMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player;
|
||||
Guild guild;
|
||||
Dispatch dispatch;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
//don't allow non guild leaders to disband guild.
|
||||
|
||||
if (player == null || GuildStatusController.isGuildLeader(player.getGuildStatus()) == false)
|
||||
return true;
|
||||
|
||||
guild = player.getGuild();
|
||||
|
||||
if (guild == null || guild.isErrant())
|
||||
return true;
|
||||
|
||||
// Don't allow disbanding if a city is owned
|
||||
// *** Refactor: We should allow this by abandoning the tree first.
|
||||
|
||||
if (guild.getOwnedCity() != null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You cannot disband a soverign guild!");
|
||||
return true;
|
||||
}
|
||||
|
||||
Bane guildBane = Bane.getBaneByAttackerGuild(guild);
|
||||
|
||||
if (guildBane != null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You cannot disband a guild with an active bane!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (guild.getSubGuildList().size() > 0) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You cannot disband a nation!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send message to guild (before kicking everyone out of it)
|
||||
|
||||
ChatManager.chatGuildInfo(guild, guild.getName() + " has been disbanded!");
|
||||
|
||||
// Log event to data warehous
|
||||
|
||||
GuildRecord guildRecord = GuildRecord.borrow(guild, Enum.RecordEventType.DISBAND);
|
||||
DataWarehouse.pushToWarehouse(guildRecord);
|
||||
|
||||
// Remove us as a subguild of our nation
|
||||
|
||||
if (guild.getNation() != null && Guild.sameGuild(guild, guild.getNation()) == false && guild.getNation().isErrant() == false)
|
||||
guild.getNation().removeSubGuild(guild);
|
||||
|
||||
// Update all online guild players
|
||||
|
||||
for (PlayerCharacter pcs : Guild.GuildRoster(guild)) {
|
||||
|
||||
guild.removePlayer(pcs,GuildHistoryType.DISBAND);
|
||||
}
|
||||
|
||||
//Save Guild data
|
||||
|
||||
player.setGuildLeader(false);
|
||||
player.setInnerCouncil(false);
|
||||
guild.setGuildLeaderUUID(0);
|
||||
guild.setNation(null);
|
||||
|
||||
DbManager.GuildQueries.DELETE_GUILD(guild);
|
||||
|
||||
DbManager.removeFromCache(guild);
|
||||
WorldGrid.removeObject(guild, player);
|
||||
|
||||
// Send message back to client
|
||||
|
||||
LeaveGuildMsg leaveGuildMsg = new LeaveGuildMsg();
|
||||
leaveGuildMsg.setMessage("You guild has been disbanded!");
|
||||
dispatch = Dispatch.borrow(player, leaveGuildMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.DismissGuildMsg;
|
||||
import engine.net.client.msg.guild.SendGuildEntryMsg;
|
||||
import engine.objects.*;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.session.Session;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DismissGuildHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public DismissGuildHandler() {
|
||||
super(DismissGuildMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
DismissGuildMsg dismissMsg;
|
||||
PlayerCharacter player;
|
||||
Guild toDismiss;
|
||||
Guild nation;
|
||||
Dispatch dispatch;
|
||||
|
||||
dismissMsg = (DismissGuildMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
toDismiss = (Guild) DbManager.getObject(GameObjectType.Guild, dismissMsg.getGuildID());
|
||||
|
||||
if (toDismiss == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
nation = player.getGuild();
|
||||
|
||||
if (nation == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Nothing to disband, your guild is not a nation!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!nation.getSubGuildList().contains(toDismiss)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You do not have authority to dismiss this guild!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Only a guild leader can dismiss a subguild!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Restriction on active bane desubbing
|
||||
|
||||
if (Bane.getBaneByAttackerGuild(toDismiss) != null)
|
||||
{
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You may not dismiss subguild with active bane!");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (toDismiss.getGuildState()) {
|
||||
case Sworn:
|
||||
|
||||
if (!DbManager.GuildQueries.UPDATE_PARENT(toDismiss.getObjectUUID(), MBServerStatics.worldUUID)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
nation.getSubGuildList().remove(toDismiss);
|
||||
toDismiss.downgradeGuildState();
|
||||
toDismiss.setNation(null);
|
||||
GuildManager.updateAllGuildBinds(toDismiss, null);
|
||||
|
||||
break;
|
||||
case Province:
|
||||
if (!DbManager.GuildQueries.UPDATE_PARENT(toDismiss.getObjectUUID(),MBServerStatics.worldUUID)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
nation.getSubGuildList().remove(toDismiss);
|
||||
toDismiss.downgradeGuildState();
|
||||
toDismiss.setNation(toDismiss);
|
||||
|
||||
break;
|
||||
case Petitioner:
|
||||
nation.getSubGuildList().remove(toDismiss);
|
||||
toDismiss.downgradeGuildState();
|
||||
break;
|
||||
case Protectorate:
|
||||
nation.getSubGuildList().remove(toDismiss);
|
||||
toDismiss.downgradeGuildState();
|
||||
break;
|
||||
}
|
||||
|
||||
GuildManager.updateAllGuildTags(toDismiss);
|
||||
|
||||
if (nation.getSubGuildList().isEmpty())
|
||||
nation.downgradeGuildState();
|
||||
|
||||
SendGuildEntryMsg msg = new SendGuildEntryMsg(player);
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
final Session s = SessionManager.getSession(player);
|
||||
|
||||
City.lastCityUpdate = System.currentTimeMillis();
|
||||
|
||||
|
||||
ArrayList<PlayerCharacter> guildMembers = SessionManager.getActivePCsInGuildID(nation.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : guildMembers) {
|
||||
ChatManager.chatGuildInfo(member, toDismiss.getName() + " has been dismissed as a subguild!");
|
||||
}
|
||||
|
||||
ArrayList<PlayerCharacter> dismissedMembers = SessionManager.getActivePCsInGuildID(toDismiss.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : dismissedMembers) {
|
||||
ChatManager.chatGuildInfo(member, nation.getName() + "has dismissed you as a sub!");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DoorState;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.DoorTryOpenMsg;
|
||||
import engine.objects.AbstractWorldObject;
|
||||
import engine.objects.Blueprint;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handle
|
||||
* open and close door requests to and from the client.
|
||||
*
|
||||
*/
|
||||
public class DoorTryOpenMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public DoorTryOpenMsgHandler() {
|
||||
super(DoorTryOpenMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
DoorTryOpenMsg msg;
|
||||
Building targetBuilding;
|
||||
int doorNumber;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (DoorTryOpenMsg)baseMsg;
|
||||
player = origin.getPlayerCharacter();
|
||||
targetBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingUUID());
|
||||
|
||||
if (player == null || targetBuilding == null) {
|
||||
Logger.error("Player or Building returned NULL in OpenCloseDoor handling.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Must be within x distance from door to manipulate it
|
||||
|
||||
if (player.getLoc().distanceSquared2D(targetBuilding.getLoc()) > MBServerStatics.OPENCLOSEDOORDISTANCE * MBServerStatics.OPENCLOSEDOORDISTANCE)
|
||||
return true;
|
||||
|
||||
doorNumber = Blueprint.getDoorNumberbyMesh(msg.getDoorID());
|
||||
|
||||
if ((targetBuilding.isDoorLocked(doorNumber) == true) && msg.getToggle() == 0x01) {
|
||||
msg.setUnk1(2);
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
return true; //don't open a locked door
|
||||
}
|
||||
|
||||
if (msg.getToggle() == 0x01) {
|
||||
targetBuilding.setDoorState(doorNumber, DoorState.OPEN);
|
||||
targetBuilding.submitOpenDoorJob(msg.getDoorID());
|
||||
} else {
|
||||
targetBuilding.setDoorState(doorNumber, DoorState.CLOSED);
|
||||
}
|
||||
|
||||
HashSet<AbstractWorldObject> container = WorldGrid.getObjectsInRangePartial(targetBuilding, MBServerStatics.CHARACTER_LOAD_RANGE,
|
||||
MBServerStatics.MASK_PLAYER);
|
||||
|
||||
for (AbstractWorldObject awo : container) {
|
||||
PlayerCharacter playerCharacter = (PlayerCharacter)awo;
|
||||
Dispatch dispatch = Dispatch.borrow(playerCharacter, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.FormationFollowMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class FormationFollowHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public FormationFollowHandler() {
|
||||
super(FormationFollowMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin)
|
||||
throws MsgSendException {
|
||||
FormationFollowMsg msg = (FormationFollowMsg) baseMsg;
|
||||
|
||||
PlayerCharacter source = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (source == null)
|
||||
return false;
|
||||
|
||||
Group group = GroupManager.getGroup(source);
|
||||
|
||||
if (group == null)
|
||||
return false;
|
||||
|
||||
if (msg.isFollow()) {// Toggle follow
|
||||
source.toggleFollow();
|
||||
if (group.getGroupLead() == source) {
|
||||
if (source.getFollow()) {
|
||||
ChatManager.chatGroupInfo(source, "falls into formation");
|
||||
} else {
|
||||
ChatManager.chatGroupInfo(source, "breaks formation");
|
||||
}
|
||||
} else {
|
||||
if (source.getFollow()) {
|
||||
ChatManager.chatGroupInfo(source, source.getFirstName() + " falls into formation");
|
||||
} else {
|
||||
ChatManager.chatGroupInfo(source, source.getFirstName() + " breaks formation");
|
||||
}
|
||||
}
|
||||
GroupUpdateMsg gum = new GroupUpdateMsg();
|
||||
gum.setGroup(group);
|
||||
gum.setPlayer(source);
|
||||
gum.setMessageType(8);
|
||||
|
||||
group.sendUpdate(gum);
|
||||
} else {// Set Formation
|
||||
if (group.getGroupLead() != source) {
|
||||
return false;
|
||||
}
|
||||
group.setFormation(msg.getFormation());
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.AcceptFriendMsg;
|
||||
import engine.net.client.msg.AddFriendMessage;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.PlayerFriends;
|
||||
|
||||
public class FriendAcceptHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public FriendAcceptHandler() {
|
||||
super(AcceptFriendMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
AcceptFriendMsg msg = (AcceptFriendMsg)baseMsg;
|
||||
|
||||
|
||||
HandleAcceptFriend(player,msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//change to Request
|
||||
public static void HandleAcceptFriend(PlayerCharacter player, AcceptFriendMsg msg){
|
||||
PlayerCharacter sourceFriend = SessionManager.getPlayerCharacterByLowerCaseName(msg.sourceName);
|
||||
|
||||
if (sourceFriend == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Could not find player " + msg.sourceName);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerFriends.AddToFriends(sourceFriend.getObjectUUID(), player.getObjectUUID());
|
||||
PlayerFriends.AddToFriends(player.getObjectUUID(), sourceFriend.getObjectUUID());
|
||||
|
||||
|
||||
AddFriendMessage outMsg = new AddFriendMessage(player);
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(sourceFriend, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
outMsg = new AddFriendMessage(sourceFriend);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
ChatManager.chatSystemInfo(sourceFriend, player.getFirstName() + " has agreed to be your friend.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.DeclineFriendMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class FriendDeclineHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public FriendDeclineHandler() {
|
||||
super(DeclineFriendMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
DeclineFriendMsg msg = (DeclineFriendMsg)baseMsg;
|
||||
|
||||
|
||||
HandleDeclineFriend(player,msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//change to Request
|
||||
public static void HandleDeclineFriend(PlayerCharacter player, DeclineFriendMsg msg){
|
||||
PlayerCharacter sourceFriend = SessionManager.getPlayerCharacterByLowerCaseName(msg.sourceName);
|
||||
|
||||
if (sourceFriend == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Could not find player " + msg.sourceName);
|
||||
return;
|
||||
}
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(sourceFriend, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.FriendRequestMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class FriendRequestHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public FriendRequestHandler() {
|
||||
super(FriendRequestMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
FriendRequestMsg msg = (FriendRequestMsg)baseMsg;
|
||||
|
||||
HandleRequestFriend(player,msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void HandleRequestFriend(PlayerCharacter player, FriendRequestMsg msg){
|
||||
PlayerCharacter targetFriend = SessionManager.getPlayerCharacterByLowerCaseName(msg.friendName);
|
||||
|
||||
if (targetFriend == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Could not find player " + msg.friendName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetFriend.equals(player))
|
||||
return;
|
||||
|
||||
|
||||
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(targetFriend, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
ChatManager.chatSystemInfo(player, "Your friend request has been sent.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.FurnitureMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class FurnitureHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public FurnitureHandler() {
|
||||
super(FurnitureMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
FurnitureMsg msg = (FurnitureMsg) baseMsg;
|
||||
|
||||
PlayerCharacter pc = origin.getPlayerCharacter();
|
||||
if (pc == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (msg.getType() == 1)
|
||||
msg.setType(2);
|
||||
|
||||
if (msg.getType() == 3)
|
||||
msg.setType(2);
|
||||
Dispatch dispatch = Dispatch.borrow(pc, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.GroupInviteMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class GroupInviteHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GroupInviteHandler() {
|
||||
super(GroupInviteMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
GroupInviteMsg msg = (GroupInviteMsg) baseMsg;
|
||||
PlayerCharacter source = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (source == null)
|
||||
return false;
|
||||
|
||||
Group group = GroupManager.getGroup(source);
|
||||
|
||||
// Group is new, create it.
|
||||
|
||||
if (group == null)
|
||||
group = GroupInviteHandler.createGroup(source, origin);
|
||||
|
||||
if (group == null)
|
||||
return false;
|
||||
|
||||
if (!group.isGroupLead(source)) // person doing invite must be group lead
|
||||
return true;
|
||||
|
||||
PlayerCharacter target = null;
|
||||
|
||||
if (msg.getInvited() == 1) { // Use name for invite
|
||||
target = SessionManager.getPlayerCharacterByLowerCaseName(msg.getName().toLowerCase());
|
||||
} else { // Use ID for invite
|
||||
target = SessionManager.getPlayerCharacterByID(msg.getTargetID());
|
||||
}
|
||||
|
||||
if (target == null)
|
||||
return false;
|
||||
|
||||
// Client must be online
|
||||
|
||||
if (SessionManager.getClientConnection(target) == null)
|
||||
return false;
|
||||
|
||||
if (source == target) // Inviting self, so we're done
|
||||
return false;
|
||||
|
||||
|
||||
//Skip invite if target is ignoring source
|
||||
|
||||
if (target.isIgnoringPlayer(source))
|
||||
return false;
|
||||
|
||||
|
||||
// dont block invites to people already in a group and
|
||||
// dont check for pending invites, the client does it
|
||||
// Send invite message to target
|
||||
|
||||
msg.setSourceType(GameObjectType.PlayerCharacter.ordinal());
|
||||
msg.setSourceID(source.getObjectUUID());
|
||||
msg.setTargetType(0);
|
||||
msg.setTargetID(0);
|
||||
msg.setGroupType(GameObjectType.Group.ordinal());
|
||||
msg.setGroupID(group.getObjectUUID());
|
||||
msg.setInvited(1);
|
||||
msg.setName(source.getFirstName());
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(target, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// this can only be called if you already know you are not in a group
|
||||
// and have issued an invite
|
||||
|
||||
private static Group createGroup(PlayerCharacter pc, ClientConnection origin) {
|
||||
|
||||
if (pc == null)
|
||||
return null;
|
||||
|
||||
Group group = new Group(pc, GroupManager.incrGroupCount());
|
||||
group.addGroupMember(pc);
|
||||
GroupManager.addNewGroup(group);
|
||||
|
||||
pc.setFollow(false);
|
||||
// Send add self to group message
|
||||
GroupUpdateMsg msg = new GroupUpdateMsg();
|
||||
msg.setGroup(group);
|
||||
msg.setPlayer(pc);
|
||||
msg.setMessageType(1);
|
||||
Dispatch dispatch = Dispatch.borrow(pc, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
group.addUpdateGroupJob();
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.GroupInviteResponseMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static engine.net.client.handlers.KeyCloneAudit.KEYCLONEAUDIT;
|
||||
|
||||
public class GroupInviteResponseHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GroupInviteResponseHandler() {
|
||||
super(GroupInviteResponseMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
GroupInviteResponseMsg msg = (GroupInviteResponseMsg) baseMsg;
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
// if we are already in a group we are leaving it
|
||||
|
||||
Group currGroup = GroupManager.getGroup(player);
|
||||
|
||||
if (currGroup != null) // if we are already in a group we are leaving it
|
||||
GroupManager.LeaveGroup(player);
|
||||
|
||||
// not sure we need to test for invites to wrong grp as only
|
||||
// 1 invite can be on screen at a time
|
||||
//if (invitesPending.get(player) != msg.getGroupID()) // Can't accept
|
||||
// invite to
|
||||
// wrong group
|
||||
// return;
|
||||
|
||||
Group group = GroupManager.getGroup(msg.getGroupID());
|
||||
|
||||
if (group == null)
|
||||
return false;
|
||||
|
||||
if (group.addGroupMember(player) == false)
|
||||
return false;
|
||||
{
|
||||
player.setFollow(true);
|
||||
GroupManager.addPlayerGroupMapping(player, group);
|
||||
Set<PlayerCharacter> members = group.getMembers();
|
||||
GroupUpdateMsg groupUpdateMsg;
|
||||
|
||||
// Send all group members to player added
|
||||
for (PlayerCharacter groupMember : members) {
|
||||
|
||||
groupUpdateMsg = new GroupUpdateMsg();
|
||||
groupUpdateMsg.setGroup(group);
|
||||
groupUpdateMsg.setMessageType(1);
|
||||
|
||||
if (groupMember == null)
|
||||
continue;
|
||||
|
||||
if (groupMember.equals(player))
|
||||
continue;
|
||||
|
||||
groupUpdateMsg.setPlayer(groupMember);
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, groupUpdateMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
}
|
||||
|
||||
// send new group member to everyone in group.
|
||||
groupUpdateMsg = new GroupUpdateMsg();
|
||||
groupUpdateMsg.setGroup(group);
|
||||
groupUpdateMsg.setMessageType(1);
|
||||
groupUpdateMsg.setPlayer(player);
|
||||
group.sendUpdate(groupUpdateMsg);
|
||||
|
||||
String text = player.getFirstName() + " has joined the group.";
|
||||
ChatManager.chatGroupInfo(player, text);
|
||||
|
||||
// Run Keyclone Audit
|
||||
|
||||
KEYCLONEAUDIT.audit(player, group);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
|
||||
public class GroupUpdateHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GroupUpdateHandler() {
|
||||
super(GroupUpdateMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
//GroupUpdateMsg msg = (GroupUpdateMsg) baseMsg;
|
||||
// not sure what to do with these as we spend our time sending them
|
||||
// to the whole group ourselves
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.GuildControlMsg;
|
||||
import engine.net.client.msg.guild.GuildListMsg;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class GuildControlHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GuildControlHandler() {
|
||||
super(GuildControlMsg.class);
|
||||
}
|
||||
|
||||
// TODO Don't think this protocolMsg (0x3235E5EA) is actually player history. so
|
||||
// take further look at it.
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
GuildControlMsg msg = (GuildControlMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
// until we know what it's for, just echo it back.
|
||||
msg.setUnknown05((byte) 1);
|
||||
|
||||
//Send a GuildList msg
|
||||
if(msg.getUnknown01() == 1) {
|
||||
|
||||
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
||||
//TODO figure out why GL can't be changed and IC can't be banished
|
||||
//Bounce back the rank options
|
||||
msg.setGM((byte) (GuildStatusController.isGuildLeader(player.getGuildStatus()) ? 1 : 0));
|
||||
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
if (GuildStatusController.isInnerCouncil(player.getGuildStatus()) || GuildStatusController.isGuildLeader(player.getGuildStatus())) {
|
||||
dispatch = Dispatch.borrow(player, new GuildListMsg(player.getGuild()));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
} else
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Only guild leader and inner council have such authority!");
|
||||
|
||||
|
||||
} else if(msg.getUnknown01() == 2) {
|
||||
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
//If we don't get a valid PC for whatever reason.. just ignore it.
|
||||
PlayerCharacter pc = PlayerCharacter.getFromCache(msg.getUnknown03());
|
||||
|
||||
if(pc != null) {
|
||||
dispatch = Dispatch.borrow(player,new GuildListMsg(pc));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.GuildCreationCloseMsg;
|
||||
|
||||
public class GuildCreationCloseHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GuildCreationCloseHandler() {
|
||||
super(GuildCreationCloseMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
// GuildCreationCloseMsg msg = (GuildCreationCloseMsg) baseMsg;
|
||||
// origin.sendMsg(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.Enum.GuildHistoryType;
|
||||
import engine.Enum.ItemType;
|
||||
import engine.Enum.OwnerType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.GuildCreationFinalizeMsg;
|
||||
import engine.net.client.msg.guild.GuildInfoMsg;
|
||||
import engine.objects.*;
|
||||
import engine.util.StringUtils;
|
||||
|
||||
public class GuildCreationFinalizeHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GuildCreationFinalizeHandler() {
|
||||
super(GuildCreationFinalizeMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player;
|
||||
GuildCreationFinalizeMsg msg;
|
||||
Enum.GuildType charterType;
|
||||
Guild newGuild;
|
||||
ItemBase itemBase;
|
||||
Item charter;
|
||||
Dispatch dispatch;
|
||||
|
||||
msg = (GuildCreationFinalizeMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
boolean isGuildLeader = GuildStatusController.isGuildLeader(player.getGuildStatus());
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) || player.getGuild() != null && player.getGuild().getGuildLeaderUUID() == player.getObjectUUID()) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.MUST_LEAVE_GUILD);
|
||||
return true;
|
||||
}
|
||||
|
||||
//Validate the Charter
|
||||
|
||||
charter = msg.getCharter();
|
||||
|
||||
if (charter == null || charter.getOwnerType() != OwnerType.PlayerCharacter || charter.getOwnerID() != player.getObjectUUID()) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
itemBase = charter.getItemBase();
|
||||
|
||||
|
||||
// Item must be a valid charterType (type 10 in db)
|
||||
|
||||
if (itemBase == null || (itemBase.getType().equals(ItemType.GUILDCHARTER) == false)) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND);
|
||||
return true;
|
||||
}
|
||||
charterType = Enum.GuildType.getGuildTypeFromCharter(itemBase);
|
||||
|
||||
|
||||
|
||||
if (charterType == null){
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.NO_CHARTER_FOUND);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//Validate Guild Tags
|
||||
|
||||
if (!msg.getGuildTag().isValid()) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.CREST_RESERVED);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validation passes. Leave current guild and create new one.
|
||||
|
||||
if (player.getGuild() != null && player.getGuild().getObjectUUID() != 0)
|
||||
player.getGuild().removePlayer(player,GuildHistoryType.LEAVE);
|
||||
|
||||
|
||||
|
||||
int leadershipType = ((msg.getICVoteFlag() << 1) | msg.getMemberVoteFlag());
|
||||
|
||||
newGuild = new Guild( msg.getName(),null, charterType.ordinal(),
|
||||
charterType.getLeadershipType(leadershipType), msg.getGuildTag(),
|
||||
StringUtils.truncate(msg.getMotto(), 120));
|
||||
|
||||
newGuild.setGuildLeaderForCreate(player);
|
||||
|
||||
synchronized (this) {
|
||||
if (!DbManager.GuildQueries.IS_NAME_UNIQUE(msg.getName())) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.UNIQUE_NAME);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!DbManager.GuildQueries.IS_CREST_UNIQUE(msg.getGuildTag())) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.UNIQUE_CREST);
|
||||
return true;
|
||||
}
|
||||
|
||||
newGuild = DbManager.GuildQueries.SAVE_TO_DATABASE(newGuild);
|
||||
}
|
||||
|
||||
if (newGuild == null) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, GuildManager.FAILURE_TO_SWEAR_GUILD);
|
||||
return true;
|
||||
}
|
||||
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
GuildManager.joinGuild(player, newGuild, GuildHistoryType.CREATE);
|
||||
|
||||
newGuild.setGuildLeader(player);
|
||||
player.setGuildLeader(true);
|
||||
player.setInnerCouncil(true);
|
||||
player.setFullMember(true);
|
||||
player.setGuildTitle(charterType.getNumberOfRanks() - 1);
|
||||
player.getCharItemManager().delete(charter);
|
||||
player.getCharItemManager().updateInventory();
|
||||
player.incVer();
|
||||
|
||||
DispatchMessage.sendToAllInRange(player, new GuildInfoMsg(player, newGuild, 2));
|
||||
|
||||
ChatManager.chatSystemInfo(player, msg.getName() + " has arrived on Grief server!");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.GuildCreationOptionsMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class GuildCreationOptionsHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GuildCreationOptionsHandler() {
|
||||
super(GuildCreationOptionsMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
GuildCreationOptionsMsg msg = (GuildCreationOptionsMsg) baseMsg;
|
||||
PlayerCharacter sourcePlayer = origin.getPlayerCharacter();
|
||||
Dispatch dispatch;
|
||||
|
||||
if(msg.getScreenType() == 1) {
|
||||
msg.setScreenType(3);
|
||||
} else if(msg.getScreenType() == 2) {
|
||||
msg.setScreenType(4);
|
||||
}
|
||||
|
||||
if (sourcePlayer == null)
|
||||
return true;
|
||||
|
||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.GuildInfoMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class GuildInfoHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GuildInfoHandler() {
|
||||
super(GuildInfoMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
GuildInfoMsg msg = (GuildInfoMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
// get source player
|
||||
PlayerCharacter sourcePlayer = SessionManager
|
||||
.getPlayerCharacter(origin);
|
||||
|
||||
if (sourcePlayer == null)
|
||||
return true;
|
||||
|
||||
if(msg.getMsgType() == 1) {
|
||||
dispatch = Dispatch.borrow(sourcePlayer, new GuildInfoMsg(sourcePlayer, sourcePlayer.getGuild(), 4));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
} else if(msg.getMsgType() == 5) {
|
||||
|
||||
if(msg.getObjectType() == GameObjectType.PlayerCharacter.ordinal()) {
|
||||
PlayerCharacter pc = PlayerCharacter.getPlayerCharacter(msg.getObjectID());
|
||||
dispatch = Dispatch.borrow(sourcePlayer, new GuildInfoMsg(pc, pc.getGuild(), 5));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
} else {
|
||||
//TODO Change this to a null object when we make a null object.
|
||||
|
||||
dispatch = Dispatch.borrow(sourcePlayer,new GuildInfoMsg(sourcePlayer, sourcePlayer.getGuild(), 1));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
}
|
||||
|
||||
// Send PromoteDemoteScreen info message response. 0x001D4DF6
|
||||
|
||||
// Send guild member list? 0x6949C720
|
||||
// GuildList(source, origin);
|
||||
|
||||
// send 0x3235E5EA? See what that is
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.GuildListMsg;
|
||||
|
||||
public class GuildListHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GuildListHandler() {
|
||||
super(GuildListMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
// GuildListMsg msg = (GuildListMsg) baseMsg;
|
||||
|
||||
// GuildListMsg msg = new GuildListMsg(origin);
|
||||
// GuildTableList gtl = new GuildTableList();
|
||||
// gtl.setUUID(pc.getUUID()); gtl.setName(pc.getName());
|
||||
// msg.add(gtl);
|
||||
// origin.sendMsg(msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.GuildUnknownMsg;
|
||||
|
||||
public class GuildUnknownHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public GuildUnknownHandler() {
|
||||
super(GuildUnknownMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
// GuildUnknownMsg msg = (GuildUnknownMsg) baseMsg;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.HirelingServiceMsg;
|
||||
import engine.net.client.msg.ManageNPCMsg;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.NPC;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class HirelingServiceMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public HirelingServiceMsgHandler() {
|
||||
super(HirelingServiceMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player;
|
||||
HirelingServiceMsg msg;
|
||||
|
||||
msg = (HirelingServiceMsg) baseMsg;
|
||||
|
||||
// get PlayerCharacter of person accepting invite
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
switch (msg.messageType){
|
||||
case HirelingServiceMsg.SETREPAIRCOST:
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.buildingID);
|
||||
|
||||
if (building == null)
|
||||
return true;
|
||||
|
||||
NPC npc = NPC.getFromCache(msg.npcID);
|
||||
|
||||
if (npc == null)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.playerCanManage(player, building))
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
npc.setRepairCost(msg.repairCost);
|
||||
ManageNPCMsg outMsg = new ManageNPCMsg(npc);
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.InviteToGuildMsg;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class InviteToGuildHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public InviteToGuildHandler() {
|
||||
super(InviteToGuildMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
InviteToGuildMsg msg;
|
||||
PlayerCharacter sourcePlayer;
|
||||
PlayerCharacter targetPlayer;
|
||||
Dispatch dispatch;
|
||||
|
||||
msg = (InviteToGuildMsg) baseMsg;
|
||||
|
||||
// First see if this is a refusal to another guild invite
|
||||
|
||||
if (msg.getResponse() == 4)
|
||||
return true; // Player refused invite
|
||||
|
||||
// get sourcePlayer player
|
||||
|
||||
sourcePlayer = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (sourcePlayer == null)
|
||||
return true;
|
||||
|
||||
if (msg.getTargetUUID() == 0) {
|
||||
// get targetPlayer player by name
|
||||
targetPlayer = SessionManager.getPlayerCharacterByLowerCaseName(msg.getTargetName());
|
||||
|
||||
if (targetPlayer == null) {
|
||||
ChatManager.chatGuildError(sourcePlayer,
|
||||
"No such player exists!");
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
if (msg.getTargetType() == GameObjectType.PlayerCharacter.ordinal()) {
|
||||
|
||||
targetPlayer = SessionManager.getPlayerCharacterByID(msg.getTargetUUID());
|
||||
|
||||
if (targetPlayer == null) {
|
||||
ChatManager.chatGuildError(sourcePlayer,
|
||||
"No such player exists!");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
ChatManager.chatGuildError(sourcePlayer,
|
||||
"You cannot invite that character!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// get sourcePlayer guild. Verify sourcePlayer player is in guild
|
||||
|
||||
if (sourcePlayer.getGuild().getObjectUUID() == 0 || sourcePlayer.getGuild().isErrant()) {
|
||||
ChatManager.chatGuildError(sourcePlayer,
|
||||
"You cannot invite someone for errant!");
|
||||
return true;
|
||||
}
|
||||
|
||||
Enum.GuildType guildType = Enum.GuildType.values()[sourcePlayer.getGuild().getCharter()];
|
||||
|
||||
if (guildType == null){
|
||||
ErrorPopupMsg.sendErrorPopup(sourcePlayer, GuildManager.NO_CHARTER_FOUND);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// verify sourcePlayer player is full member so they can invite
|
||||
|
||||
if (GuildStatusController.isFullMember(sourcePlayer.getGuildStatus()) == false) {
|
||||
ChatManager.chatGuildError(sourcePlayer,
|
||||
"You do not have authority to invite!");
|
||||
return true;
|
||||
}
|
||||
|
||||
//block invite is targetPlayer is ignoring sourcePlayer
|
||||
|
||||
if (targetPlayer.isIgnoringPlayer(sourcePlayer))
|
||||
return true;
|
||||
|
||||
if ((targetPlayer.getGuild().isErrant() == false)) {
|
||||
ChatManager.chatGuildError(sourcePlayer,
|
||||
targetPlayer.getFirstName() + " already belongs to a guild!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// verify targetPlayer player is not on banish list
|
||||
|
||||
if (sourcePlayer.getGuild().getBanishList().contains(targetPlayer)) {
|
||||
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 135);// Character is considered BANISHED by guild leadership
|
||||
return true;
|
||||
}
|
||||
|
||||
//verify targetPlayer meets level requirements of guild
|
||||
|
||||
if ((targetPlayer.getLevel() < sourcePlayer.getGuild().getRepledgeMin()) || targetPlayer.getLevel() > sourcePlayer.getGuild().getRepledgeMax()) {
|
||||
ErrorPopupMsg.sendErrorPopup(sourcePlayer, 135);// you do not meet the level required for this SWORN guild
|
||||
return true;
|
||||
}
|
||||
|
||||
targetPlayer.setLastGuildToInvite(sourcePlayer.getGuild().getObjectUUID());
|
||||
|
||||
// setup guild invite message to send to targetPlayer
|
||||
|
||||
msg.setSourceType(sourcePlayer.getObjectType().ordinal());
|
||||
msg.setSourceUUID(sourcePlayer.getObjectUUID());
|
||||
msg.setTargetType(targetPlayer.getObjectType().ordinal());
|
||||
|
||||
msg.setTargetUUID(targetPlayer.getObjectUUID());
|
||||
msg.setGuildTag(sourcePlayer.getGuild().getGuildTag());
|
||||
msg.setGuildName(sourcePlayer.getGuild().getName());
|
||||
msg.setGuildType(sourcePlayer.getGuild().getObjectType().ordinal());
|
||||
msg.setGuildUUID(sourcePlayer.getGuild().getObjectUUID());
|
||||
msg.setTargetName("");
|
||||
|
||||
dispatch = Dispatch.borrow(targetPlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.InviteToSubMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class InviteToSubHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public InviteToSubHandler() {
|
||||
super(InviteToSubMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter source;
|
||||
PlayerCharacter target;
|
||||
Guild sourceGuild;
|
||||
Guild targetGuild;
|
||||
InviteToSubMsg msg = (InviteToSubMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
source = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (source == null)
|
||||
return true;
|
||||
|
||||
target = (PlayerCharacter) DbManager.getObject(GameObjectType.PlayerCharacter, msg.getTargetUUID());
|
||||
|
||||
if (target == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(source, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
//Ignore invites to sub if ignoring player
|
||||
|
||||
if (target.isIgnoringPlayer(source))
|
||||
return true;
|
||||
|
||||
sourceGuild = source.getGuild();
|
||||
targetGuild = target.getGuild();
|
||||
|
||||
//source must be in guild
|
||||
|
||||
if (sourceGuild == null) {
|
||||
sendChat(source, "You must be in a guild to invite to sub.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sourceGuild.isErrant()){
|
||||
sendChat(source, "You must be in a guild to invite to sub.");
|
||||
return true;
|
||||
}
|
||||
|
||||
//source must be GL or IC
|
||||
|
||||
if (GuildStatusController.isInnerCouncil(source.getGuildStatus()) == false) {
|
||||
sendChat(source, "Only guild leadership can invite to sub.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sourceGuild.getNation().isErrant())
|
||||
return true;
|
||||
|
||||
//target must be in a guild
|
||||
|
||||
if (targetGuild == null)
|
||||
return true;
|
||||
|
||||
if (sourceGuild.equals(targetGuild))
|
||||
return true;
|
||||
|
||||
//target must be GL or IC
|
||||
|
||||
if (GuildStatusController.isInnerCouncil(target.getGuildStatus()) == false && GuildStatusController.isGuildLeader(target.getGuildStatus()) == false) {
|
||||
sendChat(source, "Target player is not guild leadership.");
|
||||
return true;
|
||||
}
|
||||
|
||||
//Can't already be same nation or errant
|
||||
//source guild is limited to 7 subs
|
||||
//TODO this should be based on TOL rank
|
||||
|
||||
|
||||
if (!sourceGuild.canSubAGuild(targetGuild)) {
|
||||
sendChat(source, "This Guild can't be subbed.");
|
||||
return true;
|
||||
}
|
||||
|
||||
//all tests passed, let's send invite.
|
||||
|
||||
if (target.getClientConnection() != null) {
|
||||
msg.setGuildTag(sourceGuild.getGuildTag());
|
||||
msg.setGuildName(sourceGuild.getName());
|
||||
msg.setGuildUUID(sourceGuild.getObjectUUID());
|
||||
msg.setUnknown02(1);
|
||||
|
||||
dispatch = Dispatch.borrow(target, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
} else {
|
||||
sendChat(source, "Failed to send sub invite to target.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void sendChat(PlayerCharacter source, String msg) {
|
||||
ChatManager.chatGuildError(source, msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,521 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.ItemType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.ItemProductionMsg;
|
||||
import engine.net.client.msg.ManageNPCMsg;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/*
|
||||
* @Summary: Processes application protocol message which modifies
|
||||
* hireling inventory through rolling, junking or depositing.
|
||||
*/
|
||||
public class ItemProductionMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
private static final int ACTION_PRODUCE = 1;
|
||||
private static final int ACTION_JUNK = 2;
|
||||
private static final int ACTION_RECYCLE = 3;
|
||||
private static final int ACTION_COMPLETE = 4;
|
||||
private static final int ACTION_DEPOSIT = 6;
|
||||
private static final int ACTION_SETPRICE = 5;
|
||||
private static final int ACTION_TAKE = 7;
|
||||
private static final int ACTION_CONFIRM_SETPRICE = 9; // Unsure. Sent by client
|
||||
private static final int ACTION_CONFIRM_DEPOSIT = 10; // Unsure. Sent by client
|
||||
private static final int ACTION_CONFIRM_TAKE = 11; // Unsure. Sent by client
|
||||
|
||||
public ItemProductionMsgHandler() {
|
||||
super(ItemProductionMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
NPC vendorNPC;
|
||||
ItemProductionMsg msg;
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (ItemProductionMsg) baseMsg;
|
||||
player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
// Grab reference to vendor we are interacting with
|
||||
|
||||
vendorNPC = (NPC) DbManager.getObject(engine.Enum.GameObjectType.NPC, msg.getNpcUUID());
|
||||
|
||||
// Oops?
|
||||
|
||||
if (vendorNPC == null)
|
||||
return true;
|
||||
|
||||
// Process Request
|
||||
|
||||
switch (msg.getActionType()) {
|
||||
|
||||
case ACTION_PRODUCE:
|
||||
boolean isRandom = false;
|
||||
if (msg.getUnknown03() != 0 && msg.getpToken() == 0 && msg.getsToken() == 0)
|
||||
isRandom = true;
|
||||
//Create Multiple Item Function.. Fill all empty slots
|
||||
if (msg.isMultiple()){
|
||||
int emptySlots = vendorNPC.getRank() - vendorNPC.getRolling().size();
|
||||
if (emptySlots > 0){
|
||||
for (int i = 0;i<emptySlots;i++){
|
||||
vendorNPC.produceItem(player.getObjectUUID(),msg.getTotalProduction(),isRandom,msg.getpToken(),msg.getsToken(),msg.getName(),msg.getItemUUID());
|
||||
}
|
||||
}
|
||||
}else
|
||||
vendorNPC.produceItem(player.getObjectUUID(),msg.getTotalProduction(),isRandom,msg.getpToken(),msg.getsToken(),msg.getName(),msg.getItemUUID());
|
||||
break;
|
||||
case ACTION_JUNK:
|
||||
junkItem(msg.getItemUUID(), vendorNPC, origin);
|
||||
break;
|
||||
case ACTION_RECYCLE:
|
||||
recycleItem(msg.getItemIDtoTypeMap(), vendorNPC, origin);
|
||||
msg.setActionType(7);
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case ACTION_COMPLETE:
|
||||
|
||||
vendorNPC.completeItem(msg.getItemUUID());
|
||||
|
||||
// ManageNPCMsg outMsg = new ManageNPCMsg(vendorNPC);
|
||||
// outMsg.setMessageType(1);
|
||||
//
|
||||
// dispatch = Dispatch.borrow(player, outMsg);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
break;
|
||||
case ACTION_DEPOSIT:
|
||||
depositItem(msg.getItemUUID(), vendorNPC, origin);
|
||||
break;
|
||||
case ACTION_SETPRICE:
|
||||
setItemPrice(msg.getItemType(),msg.getItemUUID(), msg.getItemPrice(), vendorNPC, origin);
|
||||
break;
|
||||
case ACTION_TAKE:
|
||||
takeItem(msg.getItemIDtoTypeMap(), vendorNPC, origin);
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method sets the price on an item in the vendor inventory
|
||||
|
||||
private static void setItemPrice(int itemType, int itemUUID, int itemPrice, NPC vendor, ClientConnection origin) {
|
||||
|
||||
Item targetItem;
|
||||
ItemProductionMsg outMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (itemType == GameObjectType.Item.ordinal())
|
||||
targetItem = Item.getFromCache(itemUUID);
|
||||
else if (itemType == GameObjectType.MobLoot.ordinal())
|
||||
targetItem = MobLoot.getFromCache(itemUUID);
|
||||
else
|
||||
targetItem = null;
|
||||
|
||||
|
||||
if (targetItem == null)
|
||||
return;
|
||||
|
||||
if (targetItem.getObjectType() == GameObjectType.Item){
|
||||
if (!DbManager.ItemQueries.UPDATE_VALUE(targetItem, itemPrice)) {
|
||||
ChatManager.chatInfoError(origin.getPlayerCharacter(), "Failed to set price! Contact CCR For help.");
|
||||
return;
|
||||
}
|
||||
targetItem.setValue(itemPrice);
|
||||
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_DEPOSIT, true);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_SETPRICE, true);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}else if (targetItem.getObjectType() == GameObjectType.MobLoot){
|
||||
MobLoot mobLoot = (MobLoot)targetItem;
|
||||
if (!DbManager.NPCQueries.UPDATE_ITEM_PRICE(mobLoot.getObjectUUID(), vendor.getObjectUUID(), itemPrice)) {
|
||||
ChatManager.chatInfoError(origin.getPlayerCharacter(), "Failed to set price! Contact CCR For help.");
|
||||
return;
|
||||
}
|
||||
targetItem.setValue(itemPrice);
|
||||
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_DEPOSIT, true);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_SETPRICE, true);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
// Set item's price
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Method adds an item from the players inventory to the vendor.
|
||||
|
||||
private static void depositItem(int itemUUID, NPC vendor, ClientConnection origin) {
|
||||
|
||||
Item targetItem;
|
||||
ItemProductionMsg outMsg;
|
||||
CharacterItemManager itemMan;
|
||||
Dispatch dispatch;
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (origin.sellLock.tryLock()) {
|
||||
try {
|
||||
targetItem = Item.getFromCache(itemUUID);
|
||||
|
||||
if (targetItem == null)
|
||||
return;
|
||||
|
||||
if (targetItem.getItemBase().getType() == ItemType.GOLD)
|
||||
return;
|
||||
|
||||
if (!vendor.getCharItemManager().hasRoomInventory(targetItem.getItemBase().getWeight())){
|
||||
|
||||
ErrorPopupMsg.sendErrorPopup(player, 21);
|
||||
return;
|
||||
}
|
||||
|
||||
itemMan = origin.getPlayerCharacter().getCharItemManager();
|
||||
|
||||
if (itemMan == null)
|
||||
return;
|
||||
|
||||
if (vendor.getCharItemManager().getInventoryWeight() > 500) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 21);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!targetItem.validForInventory(origin, player, itemMan)){
|
||||
ErrorPopupMsg.sendErrorPopup(player, 19);
|
||||
return;
|
||||
}
|
||||
|
||||
// Transfer item from player to vendor's inventory
|
||||
|
||||
if (!itemMan.sellToNPC(targetItem, vendor)){
|
||||
ErrorPopupMsg.sendErrorPopup(player, 109);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_DEPOSIT, true);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_CONFIRM_DEPOSIT, true);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
origin.getPlayerCharacter().getCharItemManager().updateInventory();
|
||||
}catch (Exception e){
|
||||
Logger.error(e);
|
||||
}finally {
|
||||
origin.sellLock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Method completes an item that has been previously rolled
|
||||
// adding it to the NPC's inventory
|
||||
|
||||
private static void completeItem(int itemUUID, NPC vendor, ClientConnection origin, ItemProductionMsg msg) {
|
||||
|
||||
Item targetItem;
|
||||
ManageNPCMsg outMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (origin.buyLock.tryLock()) {
|
||||
try {
|
||||
targetItem = Item.getFromCache(itemUUID);
|
||||
|
||||
if (targetItem == null)
|
||||
return;
|
||||
|
||||
|
||||
if (!vendor.getCharItemManager().forgeContains(targetItem, vendor))
|
||||
return;
|
||||
|
||||
boolean worked = DbManager.ItemQueries.UPDATE_FORGE_TO_INVENTORY(targetItem);
|
||||
if (!worked) {
|
||||
Guild guild = vendor.getGuild();
|
||||
if (guild == null)
|
||||
return;
|
||||
//ChatManager.chatGuildInfo(guild, "Failed to complete Item " + targetItem.getName());
|
||||
return;
|
||||
}
|
||||
|
||||
targetItem.containerType = Enum.ItemContainerType.INVENTORY;
|
||||
targetItem.setOwner(vendor);
|
||||
vendor.getCharItemManager().addItemToInventory(targetItem);
|
||||
|
||||
vendor.removeItemFromForge(targetItem);
|
||||
|
||||
outMsg = new ManageNPCMsg(vendor);
|
||||
outMsg.setMessageType(ACTION_PRODUCE);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
} finally {
|
||||
origin.buyLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Method handles recycling of an item
|
||||
|
||||
private static void recycleItem(HashMap<Integer, Integer> itemList, NPC vendor, ClientConnection origin) {
|
||||
|
||||
Item targetItem;
|
||||
ItemProductionMsg outMsg;
|
||||
int totalValue = 0;
|
||||
int currentStrongbox;
|
||||
Dispatch dispatch;
|
||||
|
||||
if (vendor.getBuilding() == null)
|
||||
return;
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (itemList == null)
|
||||
return;
|
||||
|
||||
if (origin.sellLock.tryLock()) {
|
||||
try {
|
||||
|
||||
|
||||
|
||||
for (int itemUUID : itemList.keySet()) {
|
||||
int itemValue = 0;
|
||||
|
||||
int type = itemList.get(itemUUID);
|
||||
|
||||
if (type == GameObjectType.Item.ordinal())
|
||||
targetItem = Item.getFromCache(itemUUID);
|
||||
else
|
||||
targetItem = MobLoot.getFromCache(itemUUID);
|
||||
|
||||
if (targetItem == null)
|
||||
continue;
|
||||
|
||||
if (targetItem.getItemBase().getType() == ItemType.GOLD)
|
||||
return;
|
||||
|
||||
if (!vendor.getCharItemManager().doesCharOwnThisItem(targetItem.getObjectUUID()))
|
||||
continue;
|
||||
if (vendor.getCharItemManager().inventoryContains(targetItem) == false)
|
||||
continue;
|
||||
|
||||
itemValue = targetItem.getBaseValue();
|
||||
|
||||
if (vendor.getBuilding().getStrongboxValue() + itemValue > vendor.getBuilding().getMaxGold()) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 201);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (targetItem.getItemBase().getType()) {
|
||||
case CONTRACT:
|
||||
case GUILDCHARTER:
|
||||
case DEED:
|
||||
case REALMCHARTER:
|
||||
case SCROLL:
|
||||
case TEARS:
|
||||
itemValue = 0;
|
||||
continue;
|
||||
}
|
||||
totalValue += itemValue;
|
||||
long start = System.currentTimeMillis();
|
||||
vendor.getCharItemManager().recycle(targetItem);
|
||||
long end = System.currentTimeMillis();
|
||||
long timetook = end - start;
|
||||
|
||||
// ChatManager.chatSystemInfo(player, "Took " + timetook + " ms to finish");
|
||||
|
||||
outMsg = new ItemProductionMsg(vendor.getBuilding(), vendor, targetItem, ACTION_TAKE, true);
|
||||
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
// Refund a portion of the gold
|
||||
|
||||
if (!vendor.getBuilding().transferGold(totalValue,false))
|
||||
return;
|
||||
|
||||
|
||||
|
||||
}catch (Exception e){
|
||||
Logger.error(e);
|
||||
}finally {
|
||||
|
||||
origin.sellLock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Refresh vendor's inventory to client
|
||||
|
||||
}
|
||||
|
||||
// Method junks an item that has been rolled but not completed
|
||||
|
||||
private static void junkItem(int itemUUID, NPC vendor, ClientConnection origin) {
|
||||
|
||||
MobLoot targetItem;
|
||||
ManageNPCMsg outMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
if (origin.sellLock.tryLock()) {
|
||||
try {
|
||||
targetItem = MobLoot.getFromCache(itemUUID);
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
// Can't junk nothing!
|
||||
|
||||
if (targetItem == null)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
if (!vendor.getCharItemManager().forgeContains(targetItem, vendor))
|
||||
return;
|
||||
|
||||
// Cannot junk items without a forge!
|
||||
|
||||
if (vendor.getBuilding() == null)
|
||||
return;
|
||||
|
||||
// Delete the item and cancel any pending rolling timer jobs
|
||||
|
||||
targetItem.recycle(vendor);
|
||||
vendor.removeItemFromForge(targetItem);
|
||||
|
||||
// Refresh vendor's inventory to client
|
||||
|
||||
outMsg = new ManageNPCMsg(vendor);
|
||||
outMsg.setMessageType(1);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
;
|
||||
} finally {
|
||||
origin.sellLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Method removes item from an NPC's inventory and transferes it to a player
|
||||
|
||||
private static void takeItem(HashMap<Integer, Integer> itemList, NPC vendor, ClientConnection origin) {
|
||||
|
||||
Item targetItem;
|
||||
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
for (int itemUUID : itemList.keySet()) {
|
||||
|
||||
int type = itemList.get(itemUUID);
|
||||
if (type == GameObjectType.Item.ordinal()){
|
||||
targetItem = Item.getFromCache(itemUUID);
|
||||
|
||||
}
|
||||
else{
|
||||
targetItem = MobLoot.getFromCache(itemUUID);
|
||||
|
||||
}
|
||||
|
||||
if (targetItem == null)
|
||||
return;
|
||||
|
||||
|
||||
if (targetItem.getItemBase().getType() == ItemType.GOLD)
|
||||
return;
|
||||
if (vendor.getCharItemManager().inventoryContains(targetItem) == false)
|
||||
return;
|
||||
|
||||
if (player.getCharItemManager().hasRoomInventory(targetItem.getItemBase().getWeight()) == false)
|
||||
return;
|
||||
|
||||
player.getCharItemManager().buyFromNPC(targetItem, vendor);
|
||||
|
||||
}
|
||||
|
||||
player.getCharItemManager().updateInventory();
|
||||
|
||||
// Update NPC inventory to client
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Method handles rolling item requests from the client
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.KeepAliveServerClientMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* client's tcp connection open.
|
||||
*/
|
||||
|
||||
public class KeepAliveServerClientHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public KeepAliveServerClientHandler() {
|
||||
super(KeepAliveServerClientMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter pc = origin.getPlayerCharacter();
|
||||
|
||||
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
KeepAliveServerClientMsg msg;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (KeepAliveServerClientMsg) baseMsg;
|
||||
|
||||
|
||||
// Send ping to client
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(pc, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
public enum KeyCloneAudit {
|
||||
KEYCLONEAUDIT;
|
||||
|
||||
void audit(PlayerCharacter player, Group group) {
|
||||
|
||||
int machineCount = 0;
|
||||
String machineID;
|
||||
|
||||
machineID = player.getClientConnection().machineID;
|
||||
|
||||
for (PlayerCharacter member : group.getMembers())
|
||||
if (machineID.equals(member.getClientConnection().machineID))
|
||||
machineCount = machineCount + 1;
|
||||
|
||||
// (int) ConfigManager.WORLDSERVER.config.get("keyclone")
|
||||
if (machineCount > 4) {
|
||||
Logger.error("Keyclone detected from: " + player.getAccount().getUname() +
|
||||
" with machine count of: " + machineCount);
|
||||
DbManager.AccountQueries.SET_TRASH(machineID);
|
||||
}
|
||||
// Refactor to separate file to log keyclones
|
||||
// DbManager.AccountQueries.EMPTY_TRASH(machineID);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.LeaveGroupMsg;
|
||||
|
||||
public class LeaveGroupHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public LeaveGroupHandler() {
|
||||
super(LeaveGroupMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
GroupManager.LeaveGroup(origin);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.GuildHistoryType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.LeaveGuildMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class LeaveGuildHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public LeaveGuildHandler() {
|
||||
super(LeaveGuildMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
LeaveGuildMsg msg = (LeaveGuildMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
// get PlayerCharacter of person leaving invite
|
||||
|
||||
PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (sourcePlayer == null)
|
||||
return true;
|
||||
|
||||
// Guild leader can't leave guild. must pass GL or disband
|
||||
|
||||
if (GuildStatusController.isGuildLeader(sourcePlayer.getGuildStatus())) {
|
||||
msg.setMessage("You must switch leadership of your guild before leaving!");
|
||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
// get old Guild
|
||||
Guild oldGuild = sourcePlayer.getGuild();
|
||||
|
||||
if (oldGuild == null || oldGuild.isErrant()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send left guild message to rest of guild
|
||||
ChatManager.chatGuildInfo(oldGuild, sourcePlayer.getFirstName() + " has left the guild.");
|
||||
|
||||
oldGuild.removePlayer(sourcePlayer, GuildHistoryType.LEAVE);
|
||||
|
||||
// Send message back to client
|
||||
msg.setMessage("You have left the guild.");
|
||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.LockUnlockDoorMsg;
|
||||
import engine.objects.Blueprint;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handle
|
||||
* lock and unlock door requests to and from the client.
|
||||
*
|
||||
*/
|
||||
|
||||
public class LockUnlockDoorMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public LockUnlockDoorMsgHandler() {
|
||||
super(LockUnlockDoorMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declarations
|
||||
|
||||
PlayerCharacter player;
|
||||
Building targetBuilding;
|
||||
int doorNum;
|
||||
LockUnlockDoorMsg msg;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (LockUnlockDoorMsg) baseMsg;
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
targetBuilding = BuildingManager.getBuilding((int) msg.getTargetID());
|
||||
|
||||
if (player == null || targetBuilding == null) {
|
||||
Logger.warn("Player or Building returned NULL in LockUnlock msg handling.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.getLoc().distanceSquared2D(targetBuilding.getLoc()) > MBServerStatics.OPENCLOSEDOORDISTANCE * MBServerStatics.OPENCLOSEDOORDISTANCE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!BuildingManager.playerCanManage(player, targetBuilding)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
doorNum = Blueprint.getDoorNumberbyMesh(msg.getDoorID());
|
||||
|
||||
// Debugging code
|
||||
|
||||
// Logger.debug("DoorLockUnlock", "Door mesh: " + msg.getDoorID() + " Door number: " + doorNum);
|
||||
|
||||
boolean stateChanged;
|
||||
|
||||
if (targetBuilding.isDoorLocked(doorNum)) {
|
||||
stateChanged = targetBuilding.setDoorState(doorNum, engine.Enum.DoorState.UNLOCKED);
|
||||
} else {
|
||||
stateChanged = targetBuilding.setDoorState(doorNum, engine.Enum.DoorState.LOCKED);
|
||||
}
|
||||
|
||||
if (stateChanged == false) {
|
||||
Logger.error("WorldServerMsgHandler.LockUnlockDoor", "Failed to update db for building: " + targetBuilding.getObjectUUID() + ", door: " + msg.getDoorID());
|
||||
}
|
||||
|
||||
if (targetBuilding.isDoorLocked(doorNum)) {
|
||||
msg.setUnk1(1); // Which is this, locked or unlocaked?
|
||||
} else {
|
||||
msg.setUnk1(0);
|
||||
}
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.LoginToGameServerMsg;
|
||||
import engine.net.client.msg.login.LoginErrorMsg;
|
||||
import engine.objects.Account;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.session.CSSession;
|
||||
import engine.session.Session;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* logs the character nto the game using the CSession key generated
|
||||
* by the Login server.
|
||||
*/
|
||||
|
||||
public class LoginToGameServerMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public LoginToGameServerMsgHandler() {
|
||||
super(LoginToGameServerMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
LoginToGameServerMsg msg = (LoginToGameServerMsg) baseMsg;
|
||||
|
||||
CSSession sessionInfo = CSSession.getCrossServerSession(msg.getSecKey());
|
||||
|
||||
if (sessionInfo == null) {
|
||||
Logger.error("Failed to validate session information from " + origin.getLocalAddressAndPortAsString());
|
||||
origin.kickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Unable to validate session data");
|
||||
// TODO Evaluate if we need to delete CSSessions here. We couldn't
|
||||
// find it before, why would this attempt be different?
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Account acc = sessionInfo.getAccount();
|
||||
|
||||
if (acc == null) {
|
||||
String err = "Session returned NULL Account. Conn:" + origin.getLocalAddressAndPortAsString();
|
||||
Logger.error(err);
|
||||
origin.kickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, err);
|
||||
return true;
|
||||
}
|
||||
|
||||
PlayerCharacter pc = sessionInfo.getPlayerCharacter();
|
||||
|
||||
if (pc == null) {
|
||||
String err = "Session returned NULL PlayerCharacter. Conn:" + origin.getLocalAddressAndPortAsString();
|
||||
|
||||
Logger.error(err);
|
||||
origin.kickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, err);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If account is suspended, kick
|
||||
|
||||
if (acc.status.equals(Enum.AccountStatus.BANNED)) {
|
||||
origin.kickToLogin(MBServerStatics.LOGINERROR_NO_MORE_PLAYTIME_ON_ACCOUNT, "Account banned.");
|
||||
return true;
|
||||
}
|
||||
|
||||
ClientConnection old = SessionManager.getClientConnection(acc);
|
||||
|
||||
if (old != null)
|
||||
if (old != origin) {
|
||||
Logger.info("Disconnecting other client connection Using Same Account " + old.getRemoteAddressAndPortAsString());
|
||||
old.disconnect();
|
||||
}
|
||||
|
||||
// Set machine ID here from CSS info
|
||||
origin.machineID = sessionInfo.getMachineID();
|
||||
|
||||
// Send response
|
||||
msg.setSecKey("");
|
||||
|
||||
if (!origin.sendMsg(msg)) {
|
||||
Logger.error("Failed to send message");
|
||||
origin.kickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Unable to send ValidateGameServer to client.");
|
||||
return true;
|
||||
}
|
||||
|
||||
//# Why was this all changed?
|
||||
// CLEAN UP OTHER INSTANCES OF THIS CHARACTER
|
||||
|
||||
Session toKill = SessionManager.getSession(sessionInfo.getPlayerCharacter());
|
||||
|
||||
if (toKill != null) {
|
||||
if (toKill.getConn() != null) {
|
||||
LoginErrorMsg lom = new LoginErrorMsg(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "You may not login the same character twice!");
|
||||
ClientConnection conn = toKill.getConn();
|
||||
if (conn != null && !conn.sendMsg(lom))
|
||||
Logger.error("Failed to send message"); // TODO Do we just accept this failure to send Msg?
|
||||
}
|
||||
SessionManager.remSession(toKill);
|
||||
WorldGrid.RemoveWorldObject(sessionInfo.getPlayerCharacter());
|
||||
}
|
||||
Session s = SessionManager.getNewSession(sessionInfo.getAccount(), origin);
|
||||
SessionManager.setPlayerCharacter(s, sessionInfo.getPlayerCharacter());
|
||||
|
||||
Logger.info("Login from Account: " + sessionInfo.getAccount().getUname() + " Character: " +
|
||||
sessionInfo.getPlayerCharacter().getName() + " machineID: " + sessionInfo.getMachineID());
|
||||
|
||||
DbManager.AccountQueries.SET_ACCOUNT_LOGIN(sessionInfo.getAccount(), sessionInfo.getPlayerCharacter().getName(), origin.getClientIpAddress(), sessionInfo.getMachineID());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.guild.MOTDCommitMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class MOTDCommitHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public MOTDCommitHandler() {
|
||||
super(MOTDCommitMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
MOTDCommitMsg msg = (MOTDCommitMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
// get source player
|
||||
PlayerCharacter sourcePlayer = SessionManager.getPlayerCharacter(
|
||||
origin);
|
||||
|
||||
if (sourcePlayer == null)
|
||||
return true;
|
||||
|
||||
int type = msg.getType();
|
||||
|
||||
if (type == 0 || type == 1 || type == 3) {
|
||||
|
||||
if (GuildStatusController.isInnerCouncil(sourcePlayer.getGuildStatus()) == false)
|
||||
return true;
|
||||
|
||||
Guild guild = sourcePlayer.getGuild();
|
||||
|
||||
if (guild == null)
|
||||
return true;
|
||||
|
||||
if (type == 1) { // Guild MOTD
|
||||
guild.setMOTD(msg.getMessage());
|
||||
ChatManager.chatGuildMOTD(sourcePlayer, msg.getMessage(),
|
||||
true);
|
||||
} else if (type == 3) { // IC MOTD
|
||||
guild.setICMOTD(msg.getMessage());
|
||||
ChatManager
|
||||
.chatICMOTD(sourcePlayer, msg.getMessage(), true);
|
||||
} else if (type == 0) { // Nation MOTD
|
||||
Guild nation = guild.getNation();
|
||||
if (nation == null)
|
||||
return true;
|
||||
if (nation.isNation()) { // only
|
||||
// nation's
|
||||
// primary guild can
|
||||
// set nation motd
|
||||
nation.setMOTD(msg.getMessage());
|
||||
ChatManager.chatNationMOTD(sourcePlayer,
|
||||
msg.getMessage(), true);
|
||||
}
|
||||
}
|
||||
dispatch = Dispatch.borrow(sourcePlayer, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.LeaveGuildMsg;
|
||||
import engine.net.client.msg.guild.MOTDMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class MOTDEditHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public MOTDEditHandler() {
|
||||
super(MOTDMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
MOTDMsg msg = (MOTDMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
// get source player
|
||||
PlayerCharacter playerCharacter = SessionManager.getPlayerCharacter(
|
||||
origin);
|
||||
|
||||
if (playerCharacter == null)
|
||||
return true;
|
||||
|
||||
int type = msg.getType();
|
||||
|
||||
msg.setResponse((byte) 1);
|
||||
if (type == 0 || type == 1 || type == 3) {
|
||||
if (GuildStatusController.isInnerCouncil(playerCharacter.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorMsg(playerCharacter, "You do not have such authority!");
|
||||
return true;
|
||||
}
|
||||
|
||||
Guild guild = playerCharacter.getGuild();
|
||||
|
||||
if (guild == null || guild.getObjectUUID() == 0) {
|
||||
|
||||
LeaveGuildMsg leaveGuildMsg = new LeaveGuildMsg();
|
||||
leaveGuildMsg.setMessage("You do not belong to a guild!");
|
||||
dispatch = Dispatch.borrow(playerCharacter, leaveGuildMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == 1) // Guild MOTD
|
||||
msg.setMessage(guild.getMOTD());
|
||||
else if (type == 3) // IC MOTD
|
||||
msg.setMessage(guild.getICMOTD());
|
||||
else if (type == 0) { // Nation MOTD
|
||||
Guild nation = guild.getNation();
|
||||
if (nation == null || !nation.isNation()) {
|
||||
ErrorPopupMsg.sendErrorMsg(playerCharacter, "You do not have such authority!");
|
||||
return true;
|
||||
}
|
||||
msg.setMessage(nation.getMOTD());
|
||||
}
|
||||
dispatch = Dispatch.borrow(playerCharacter, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.math.Bounds;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.ManageCityAssetsMsg;
|
||||
import engine.net.client.msg.PlaceAssetMsg;
|
||||
import engine.objects.*;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which opens
|
||||
* and processes the various building asset management windows.
|
||||
*/
|
||||
public class ManageCityAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ManageCityAssetMsgHandler() {
|
||||
super(ManageCityAssetsMsg.class);
|
||||
}
|
||||
|
||||
public static boolean playerCanManageNotFriends(PlayerCharacter player, Building building){
|
||||
|
||||
//Player Can only Control Building if player is in Same Guild as Building and is higher rank than IC.
|
||||
|
||||
if (player == null)
|
||||
return false;
|
||||
|
||||
if (building.getRank() == -1)
|
||||
return false;
|
||||
|
||||
if (BuildingManager.IsOwner(building, player))
|
||||
return true;
|
||||
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false && GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
|
||||
return false;
|
||||
|
||||
//Somehow guild leader check fails above? lets check if Player is true Guild GL.
|
||||
if (building.getGuild() != null && building.getGuild().isGuildLeader(player.getObjectUUID()))
|
||||
return true;
|
||||
|
||||
return Guild.sameGuild(building.getGuild(), player.getGuild());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
ManageCityAssetsMsg msg;
|
||||
PlayerCharacter player;
|
||||
ManageCityAssetsMsg outMsg;
|
||||
Building building;
|
||||
|
||||
msg = (ManageCityAssetsMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
building = BuildingManager.getBuildingFromCache(msg.getTargetID());
|
||||
|
||||
if (building == null){
|
||||
if (msg.actionType == 14) {
|
||||
|
||||
Zone zone = ZoneManager.findSmallestZone(player.getLoc());
|
||||
|
||||
if (!zone.isPlayerCity()){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command.");
|
||||
return true;
|
||||
}
|
||||
|
||||
City city = City.GetCityFromCache(zone.getPlayerCityUUID());
|
||||
|
||||
if (city == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Unable to find city to command.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!city.getGuild().equals(player.getGuild())){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You are not in the correct guild to command this city.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!GuildStatusController.isInnerCouncil(player.getGuildStatus()) && !GuildStatusController.isGuildLeader(player.getGuildStatus())){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You must be an Inner Council or Guild leader to access city commands.");
|
||||
return true;
|
||||
}
|
||||
ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building);
|
||||
mca.actionType = 15;
|
||||
Dispatch dispatch = Dispatch.borrow(player, mca);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
outMsg = new ManageCityAssetsMsg(player, building);
|
||||
|
||||
if (player.isSafeMode()){
|
||||
outMsg.actionType = 4;
|
||||
outMsg.setTargetType(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID(building.getObjectUUID());
|
||||
outMsg.setAssetName(building.getName());
|
||||
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msg.actionType == 2 || msg.actionType == 22) {
|
||||
|
||||
if (building.getBlueprint() != null && building.getBlueprint().getBuildingGroup() == engine.Enum.BuildingGroup.BANESTONE) {
|
||||
|
||||
outMsg.actionType = 18;
|
||||
outMsg.setTargetType(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID(building.getObjectUUID());
|
||||
|
||||
} else if (BuildingManager.playerCanManage(player, building)) { //TODO allow Friends list.
|
||||
configWindowState(player, building, outMsg);
|
||||
outMsg.actionType = 3;
|
||||
outMsg.setTargetType(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID(building.getObjectUUID());
|
||||
outMsg.setTargetType3(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID3(building.getObjectUUID());
|
||||
outMsg.setUnknown54(1);
|
||||
|
||||
} else {
|
||||
|
||||
if (building.getBlueprintUUID() != 0)
|
||||
switch (building.getBlueprint().getBuildingGroup()) {
|
||||
case SHRINE:
|
||||
if (building.getRank() == -1) {
|
||||
if (!Bounds.collide(player.getLoc(), building)) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 64);
|
||||
return true;
|
||||
}
|
||||
|
||||
Shrine shrine = Shrine.shrinesByBuildingUUID.get(building.getObjectUUID());
|
||||
|
||||
if (shrine == null)
|
||||
return true;
|
||||
|
||||
if (shrine.getFavors() == 0) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 166); // There is no more favor in this shrine to loot
|
||||
return true;
|
||||
}
|
||||
|
||||
BuildingManager.lootBuilding(player, building);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case WAREHOUSE:
|
||||
//TODO check
|
||||
if (building.getRank() == -1) {
|
||||
if (!Bounds.collide(player.getLoc(), building)) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 64);
|
||||
return true;
|
||||
}
|
||||
|
||||
Warehouse warehouse = Warehouse.warehouseByBuildingUUID.get(building.getObjectUUID());
|
||||
|
||||
if (warehouse == null)
|
||||
return true;
|
||||
|
||||
if (warehouse.isEmpty()) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 167); // no more resources.
|
||||
return true;
|
||||
}
|
||||
|
||||
BuildingManager.lootBuilding(player, building);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (building.getRank() == -1)
|
||||
return true;
|
||||
|
||||
AbstractCharacter owner = building.getOwner();
|
||||
|
||||
//no owner, send building info
|
||||
if (owner == null) {
|
||||
msg.actionType = 4;
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
outMsg.actionType = 4;
|
||||
outMsg.setTargetType(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID(building.getObjectUUID());
|
||||
outMsg.setAssetName(building.getName());
|
||||
|
||||
}
|
||||
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msg.actionType == 13) {
|
||||
outMsg.actionType = 13;
|
||||
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Rename Building.
|
||||
|
||||
if (msg.actionType == 5) {
|
||||
|
||||
//TODO we need to check names before allowing
|
||||
building.setName(msg.getAssetName());
|
||||
configWindowState(player, building, outMsg);
|
||||
|
||||
outMsg.actionType = 3;
|
||||
outMsg.setTargetType(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID(building.getObjectUUID());
|
||||
outMsg.setTargetType3(GameObjectType.Building.ordinal());
|
||||
outMsg.setTargetID3(building.getObjectUUID());
|
||||
outMsg.setAssetName1(building.getName());
|
||||
outMsg.setUnknown54(1);
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
|
||||
//TOL, update city name also
|
||||
//TODO update city and zone in database
|
||||
//TODO update city map data in game server
|
||||
}
|
||||
|
||||
if (msg.actionType == 14) {
|
||||
ManageCityAssetsMsg mca = new ManageCityAssetsMsg(player, building);
|
||||
mca.actionType = 15;
|
||||
Dispatch dispatch = Dispatch.borrow(player, mca);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msg.actionType == 20) {
|
||||
|
||||
Zone baneZone = building.getParentZone();
|
||||
|
||||
if (baneZone == null)
|
||||
return true;
|
||||
|
||||
City banedCity = City.getCity(baneZone.getPlayerCityUUID());
|
||||
|
||||
if (banedCity == null)
|
||||
return true;
|
||||
|
||||
Bane bane = banedCity.getBane();
|
||||
|
||||
if (bane == null || bane.getLiveDate() != null || player.getGuild() != banedCity.getGuild() || GuildStatusController.isInnerCouncil(player.getGuildStatus()) == false)
|
||||
return true;
|
||||
|
||||
int baneHour = msg.getBaneHour();
|
||||
|
||||
if (baneHour < 16 || baneHour > 24) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(origin, 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
DateTime baneLive = new DateTime(bane.getPlacementDate());
|
||||
baneLive = baneHour == 24 ? baneLive.plusDays(3) : baneLive.plusDays(2);
|
||||
baneLive = baneHour == 24 ? baneLive.hourOfDay().setCopy(0) : baneLive.hourOfDay().setCopy(baneHour);
|
||||
baneLive = baneLive.minuteOfHour().setCopy(0);
|
||||
baneLive = baneLive.secondOfMinute().setCopy(1);
|
||||
bane.setLiveDate(baneLive);
|
||||
outMsg.actionType = 18;
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void configWindowState(PlayerCharacter player, Building building, ManageCityAssetsMsg manageCityAssetsMsg) {
|
||||
|
||||
// Tests to turn on upgrade button if a building is not
|
||||
// at it's maximum allowed rank or currently ranking
|
||||
|
||||
|
||||
// Owner is obviously allowed to upgrade his own buildings
|
||||
|
||||
if (building.getOwner().equals(player)) {
|
||||
|
||||
// Players cannot destroy or transfer a TOL.
|
||||
|
||||
if (building.getBlueprint() == null){
|
||||
manageCityAssetsMsg.buttonDestroy = 0;
|
||||
manageCityAssetsMsg.buttonTransfer = 0;
|
||||
manageCityAssetsMsg.buttonAbandon = 0;
|
||||
manageCityAssetsMsg.buttonUpgrade = 0;
|
||||
}
|
||||
else
|
||||
if (building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.TOL) {
|
||||
manageCityAssetsMsg.buttonDestroy = 0;
|
||||
manageCityAssetsMsg.buttonTransfer = 0;
|
||||
manageCityAssetsMsg.buttonAbandon = 1;
|
||||
manageCityAssetsMsg.buttonUpgrade = 1;
|
||||
}
|
||||
else if (building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.MINE) {
|
||||
manageCityAssetsMsg.buttonDestroy = 0;
|
||||
manageCityAssetsMsg.buttonTransfer = 0;
|
||||
manageCityAssetsMsg.buttonAbandon = 0;
|
||||
manageCityAssetsMsg.buttonUpgrade = 0; // Cannot upgrade a mine
|
||||
}
|
||||
else{
|
||||
manageCityAssetsMsg.buttonDestroy = 1;
|
||||
manageCityAssetsMsg.buttonTransfer = 1;
|
||||
manageCityAssetsMsg.buttonAbandon = 1;
|
||||
manageCityAssetsMsg.buttonUpgrade = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Inner Council of the same guild can also upgrade
|
||||
|
||||
if ((player.getGuild().equals(building.getGuild())) &&
|
||||
GuildStatusController.isInnerCouncil(player.getGuildStatus()))
|
||||
manageCityAssetsMsg.buttonUpgrade = 1;
|
||||
|
||||
// Disable upgrade button if at max rank.
|
||||
|
||||
if (building.getBlueprint() == null)
|
||||
manageCityAssetsMsg.buttonUpgrade = 0;
|
||||
else
|
||||
if (building.getRank() >= building.getBlueprint().getMaxRank())
|
||||
manageCityAssetsMsg.buttonUpgrade = 0;;
|
||||
|
||||
// If a building is not protected we can exit here
|
||||
|
||||
if (building.assetIsProtected() == false)
|
||||
return;
|
||||
|
||||
// Protection is displayed as "UNDER SIEGE" if
|
||||
// an active bane is invalidating the protection
|
||||
// contracts of the city.
|
||||
|
||||
if ((building.getCity() != null) &&
|
||||
(building.getCity().protectionEnforced == false)) {
|
||||
manageCityAssetsMsg.labelProtected = 0;
|
||||
manageCityAssetsMsg.labelSiege = 1;
|
||||
manageCityAssetsMsg.labelCeaseFire = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Building is currently protected by a TOL
|
||||
|
||||
manageCityAssetsMsg.labelProtected = 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,465 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GuildHistoryType;
|
||||
import engine.InterestManagement.RealmMap;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.*;
|
||||
import engine.job.JobScheduler;
|
||||
import engine.jobs.TeleportJob;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.*;
|
||||
import engine.powers.PowersBase;
|
||||
import engine.server.MBServerStatics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes a variety of windows the client can open
|
||||
* such as realm blessings and warehouse deposits.
|
||||
*/
|
||||
|
||||
public class MerchantMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public MerchantMsgHandler() {
|
||||
super(MerchantMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
MerchantMsg msg;
|
||||
PlayerCharacter player;
|
||||
NPC npc;
|
||||
int msgType;
|
||||
Building warehouse;
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
msg = (MerchantMsg) baseMsg;
|
||||
npc = NPC.getNPC(msg.getNPCID());
|
||||
|
||||
// Early exit if something goes awry
|
||||
|
||||
if ((player == null) || (npc == null))
|
||||
return true;
|
||||
|
||||
// Player must be within talking range
|
||||
|
||||
if (player.getLoc().distanceSquared2D(npc.getLoc()) > MBServerStatics.NPC_TALK_RANGE * MBServerStatics.NPC_TALK_RANGE) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 14);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Process application protocol message
|
||||
|
||||
msgType = msg.getType();
|
||||
|
||||
switch (msgType) {
|
||||
case 3:
|
||||
break;
|
||||
case 5:
|
||||
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
requestSwearAsSubGuild(msg, origin, player, npc);
|
||||
break;
|
||||
case 10:
|
||||
teleportRepledgeScreen(msg, origin, player, false, npc);
|
||||
break;
|
||||
case 11:
|
||||
teleportRepledge(msg, origin, player, false, npc);
|
||||
break;
|
||||
case 12:
|
||||
teleportRepledgeScreen(msg, origin, player, true, npc);
|
||||
break;
|
||||
case 13:
|
||||
teleportRepledge(msg, origin, player, true, npc);
|
||||
break;
|
||||
case 14:
|
||||
if (isHermit(npc))
|
||||
requestHermitBlessing(msg, origin, player, npc);
|
||||
else
|
||||
requestBoon(msg, origin, player, npc);
|
||||
break;
|
||||
case 15:
|
||||
LeaderboardMessage lbm = new LeaderboardMessage();
|
||||
dispatch = Dispatch.borrow(player, lbm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case 16:
|
||||
ViewResourcesMessage vrm = new ViewResourcesMessage(player);
|
||||
warehouse = npc.getBuilding();
|
||||
vrm.setGuild(player.getGuild());
|
||||
vrm.setWarehouseBuilding(warehouse);
|
||||
vrm.configure();
|
||||
dispatch = Dispatch.borrow(player, vrm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case 17:
|
||||
Warehouse.warehouseWithdraw(msg, player, npc, origin);
|
||||
break;
|
||||
case 18:
|
||||
Warehouse.warehouseDeposit(msg, player, npc, origin);
|
||||
break;
|
||||
case 19:
|
||||
Warehouse.warehouseLock(msg, player, npc, origin);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void requestSwearAsSubGuild(MerchantMsg msg, ClientConnection origin, PlayerCharacter player, NPC npc) {
|
||||
|
||||
boolean Disabled = true;
|
||||
|
||||
if (Disabled){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Swearing to Safeholds have been temporary disabled."); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.getGuild().isErrant()){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You do not belong to a guild!"); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.getGuild().getNation() != null && !player.getGuild().getNation().isErrant()){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You already belong to a nation!"); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.getGuild().getGuildLeaderUUID() != player.getObjectUUID()){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You must be a Guild Leader to Swear your guild as a Sub Guild!"); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GuildStatusController.isGuildLeader(player.getGuildStatus())){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You must be a Guild Leader to Swear your guild as a Sub Guild!"); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!npc.getGuild().isNPCGuild()){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Runemaster does not belong to a safehold!"); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
if (npc.getGuild().getRepledgeMin() > player.getLevel()){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You are too low of a level to sub to this guild!"); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
if (npc.getGuild().getRepledgeMax() < 75){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Runemaster Guild Cannot Swear in your guild!"); //Cannot sub as errant guild.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (!DbManager.GuildQueries.UPDATE_PARENT(player.getGuild().getObjectUUID(), npc.getGuild().getObjectUUID())) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
GuildManager.updateAllGuildBinds(player.getGuild(), npc.getGuild().getOwnedCity());
|
||||
|
||||
|
||||
|
||||
//update Guild state.
|
||||
player.getGuild().setNation(npc.getGuild());
|
||||
GuildManager.updateAllGuildTags(player.getGuild());
|
||||
|
||||
//update state twice, errant to petitioner, to sworn.
|
||||
player.getGuild().upgradeGuildState(false);//to petitioner
|
||||
player.getGuild().upgradeGuildState(false);//to sworn
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void requestHermitBlessing(MerchantMsg msg, ClientConnection origin, PlayerCharacter player, NPC npc) {
|
||||
|
||||
Guild guild;
|
||||
Realm realm;
|
||||
City city;
|
||||
Building tol;
|
||||
|
||||
// Validate player can obtain blessing
|
||||
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 173); // You must be the leader of a guild to receive a blessing
|
||||
return;
|
||||
}
|
||||
|
||||
guild = player.getGuild();
|
||||
city = guild.getOwnedCity();
|
||||
|
||||
if (city == null) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 179); // Only landed guilds may claim a territory
|
||||
return;
|
||||
}
|
||||
tol = city.getTOL();
|
||||
|
||||
if (tol.getRank() != 7) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 181); // Your tree must be rank 7 before claiming a territory
|
||||
return;
|
||||
}
|
||||
|
||||
realm = RealmMap.getRealmForCity(city);
|
||||
|
||||
if (realm.getCanBeClaimed() == false) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 180); // This territory cannot be ruled by anyone
|
||||
return;
|
||||
}
|
||||
|
||||
if (realm.isRuled() == true) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 178); // This territory is already claimed
|
||||
return;
|
||||
}
|
||||
|
||||
// Everything should be good, apply boon for this hermit
|
||||
|
||||
PowersManager.applyPower(player, player, player.getLoc(), getPowerforHermit(npc).getToken(), 40, false);
|
||||
|
||||
}
|
||||
|
||||
private static void requestBoon(MerchantMsg msg, ClientConnection origin, PlayerCharacter player, NPC npc) {
|
||||
|
||||
Building shrineBuilding;
|
||||
Shrine shrine;
|
||||
|
||||
if (npc.getGuild() != player.getGuild())
|
||||
return;
|
||||
|
||||
shrineBuilding = npc.getBuilding();
|
||||
|
||||
if (shrineBuilding == null)
|
||||
return;
|
||||
|
||||
if (shrineBuilding.getBlueprint() != null && shrineBuilding.getBlueprint().getBuildingGroup() != engine.Enum.BuildingGroup.SHRINE)
|
||||
return;
|
||||
|
||||
if (shrineBuilding.getRank() == -1)
|
||||
return;
|
||||
|
||||
shrine = Shrine.shrinesByBuildingUUID.get(shrineBuilding.getObjectUUID());
|
||||
|
||||
if (shrine == null)
|
||||
return;
|
||||
|
||||
if (shrine.getFavors() == 0) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 172);
|
||||
return;
|
||||
}
|
||||
|
||||
//already haz boon.
|
||||
|
||||
if (player.containsEffect(shrine.getShrineType().getPowerToken())) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 199);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Shrine.canTakeFavor(player, shrine))
|
||||
return;
|
||||
|
||||
if (!shrine.takeFavor(player))
|
||||
return;
|
||||
|
||||
PowersBase shrinePower = PowersManager.getPowerByToken(shrine.getShrineType().getPowerToken());
|
||||
|
||||
if (shrinePower == null) {
|
||||
ChatManager.chatSystemError(player, "FAILED TO APPLY POWER!");
|
||||
return;
|
||||
}
|
||||
|
||||
int rank = shrine.getRank();
|
||||
//R8 trees always get atleast rank 2 boons. rank uses index, where 0 is first place, 1 is second, etc...
|
||||
if (shrineBuilding.getCity() != null && shrineBuilding.getCity().getTOL() != null && shrineBuilding.getCity().getTOL().getRank() == 8)
|
||||
if (rank != 0)
|
||||
rank = 1;
|
||||
int trains = 40 - (rank * 10);
|
||||
if (trains < 0)
|
||||
trains = 0;
|
||||
|
||||
//System.out.println(trains);
|
||||
PowersManager.applyPower(player, player, player.getLoc(), shrinePower.getToken(), trains, false);
|
||||
ChatManager.chatGuildInfo(player.getGuild(), player.getName() + " has recieved a boon costing " + 1 + " point of favor.");
|
||||
shrineBuilding.addEffectBit(1000000 << 2);
|
||||
shrineBuilding.updateEffects();
|
||||
|
||||
//remove the effect so players loading shrines dont see the effect go off.
|
||||
shrineBuilding.removeEffectBit(1000000 << 2);
|
||||
}
|
||||
|
||||
private static void teleportRepledgeScreen(MerchantMsg msg, ClientConnection origin, PlayerCharacter pc, boolean isTeleport, NPC npc) {
|
||||
|
||||
Dispatch dispatch;
|
||||
TeleportRepledgeListMsg trlm;
|
||||
|
||||
//verify npc is runemaster
|
||||
|
||||
Contract contract = npc.getContract();
|
||||
|
||||
if (contract == null || !contract.isRuneMaster())
|
||||
return;
|
||||
|
||||
if (!isTeleport)
|
||||
trlm = new TeleportRepledgeListMsg(pc, false);
|
||||
else
|
||||
trlm = new TeleportRepledgeListMsg(pc, true);
|
||||
|
||||
trlm.configure();
|
||||
|
||||
dispatch = Dispatch.borrow(pc, trlm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
private static void teleportRepledge(MerchantMsg msg, ClientConnection origin, PlayerCharacter player, boolean isTeleport, NPC npc) {
|
||||
|
||||
//verify npc is runemaster
|
||||
|
||||
Contract contract = npc.getContract();
|
||||
Dispatch dispatch;
|
||||
|
||||
if (contract == null || !contract.isRuneMaster())
|
||||
return;
|
||||
|
||||
//get city to teleport/repledge to and verify valid
|
||||
|
||||
ArrayList<City> cities;
|
||||
|
||||
City targetCity = null;
|
||||
|
||||
if (isTeleport)
|
||||
cities = City.getCitiesToTeleportTo(player);
|
||||
else
|
||||
cities = City.getCitiesToRepledgeTo(player);
|
||||
for (City city : cities) {
|
||||
if (city.getObjectUUID() == msg.getCityID()) {
|
||||
targetCity = city;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCity == null)
|
||||
return;
|
||||
|
||||
//verify level required to teleport or repledge
|
||||
|
||||
Guild toGuild = targetCity.getGuild();
|
||||
|
||||
if (toGuild != null)
|
||||
if (isTeleport) {
|
||||
if (player.getLevel() < toGuild.getTeleportMin() || player.getLevel() > toGuild.getTeleportMax())
|
||||
return;
|
||||
}
|
||||
else if (player.getLevel() < toGuild.getRepledgeMin() || player.getLevel() > toGuild.getRepledgeMax())
|
||||
return;
|
||||
|
||||
boolean joinedGuild = false;
|
||||
|
||||
//if repledge, reguild the player
|
||||
|
||||
if (!isTeleport)
|
||||
joinedGuild = GuildManager.joinGuild(player, targetCity.getGuild(), targetCity.getObjectUUID(), GuildHistoryType.JOIN);
|
||||
|
||||
int time;
|
||||
|
||||
if (!isTeleport) //repledge
|
||||
time = MBServerStatics.REPLEDGE_TIME_IN_SECONDS;
|
||||
else
|
||||
time = MBServerStatics.TELEPORT_TIME_IN_SECONDS;
|
||||
|
||||
//resend message
|
||||
msg.setTeleportTime(time);
|
||||
|
||||
if ((!isTeleport && joinedGuild) || (isTeleport)) {
|
||||
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
//teleport player to city
|
||||
|
||||
Vector3fImmutable teleportLoc;
|
||||
|
||||
if (targetCity.getTOL().getRank() == 8)
|
||||
teleportLoc = targetCity.getTOL().getStuckLocation();
|
||||
else
|
||||
teleportLoc = Vector3fImmutable.getRandomPointOnCircle(targetCity.getTOL().getLoc(), MBServerStatics.TREE_TELEPORT_RADIUS);
|
||||
|
||||
if (time > 0) {
|
||||
//TODO add timer to teleport
|
||||
TeleportJob tj = new TeleportJob(player, npc, teleportLoc, origin, true);
|
||||
JobScheduler.getInstance().scheduleJob(tj, time * 1000);
|
||||
}
|
||||
else if (joinedGuild) {
|
||||
player.teleport(teleportLoc);
|
||||
player.setSafeMode();
|
||||
}
|
||||
}
|
||||
|
||||
private static PowersBase getPowerforHermit(NPC npc) {
|
||||
|
||||
int contractID;
|
||||
PowersBase power;
|
||||
Contract contract;
|
||||
|
||||
contract = npc.getContract();
|
||||
contractID = contract.getContractID();
|
||||
power = null;
|
||||
|
||||
switch (contractID) {
|
||||
case 435579:
|
||||
power = PowersManager.getPowerByIDString("BLS-POWER");
|
||||
break;
|
||||
case 435580:
|
||||
power = PowersManager.getPowerByIDString("BLS-FORTUNE");
|
||||
break;
|
||||
case 435581:
|
||||
power = PowersManager.getPowerByIDString("BLS-WISDOM");
|
||||
break;
|
||||
|
||||
}
|
||||
return power;
|
||||
}
|
||||
|
||||
private static boolean isHermit(NPC npc) {
|
||||
|
||||
int contractID;
|
||||
boolean retValue = false;
|
||||
|
||||
contractID = npc.getContractID();
|
||||
|
||||
switch (contractID) {
|
||||
case 435579:
|
||||
case 435580:
|
||||
case 435581:
|
||||
retValue = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.ai.MobileFSM;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.*;
|
||||
import engine.server.MBServerStatics;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which
|
||||
* processes training of minions in guard barracks
|
||||
*/
|
||||
|
||||
public class MinionTrainingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public static HashMap<Integer, ArrayList<Integer>> _minionsByCaptain = null;
|
||||
|
||||
public MinionTrainingMsgHandler() {
|
||||
super(MinionTrainingMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
MinionTrainingMessage minionMsg = (MinionTrainingMessage) baseMsg;
|
||||
|
||||
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
if (minionMsg.getNpcType() == Enum.GameObjectType.NPC.ordinal()){
|
||||
|
||||
NPC npc = NPC.getFromCache(minionMsg.getNpcID());
|
||||
|
||||
if (npc == null)
|
||||
return true;
|
||||
|
||||
Building b = BuildingManager.getBuildingFromCache(minionMsg.getBuildingID());
|
||||
|
||||
if (b == null)
|
||||
return true;
|
||||
|
||||
//clear minion
|
||||
|
||||
if (npc.minionLock.writeLock().tryLock()) {
|
||||
try {
|
||||
if (minionMsg.getType() == 2) {
|
||||
|
||||
Mob toRemove = Mob.getFromCache(minionMsg.getUUID());
|
||||
|
||||
if (!npc.getSiegeMinionMap().containsKey(toRemove))
|
||||
return true;
|
||||
|
||||
toRemove.setState(MobileFSM.STATE.Disabled);
|
||||
npc.getSiegeMinionMap().remove(toRemove);
|
||||
|
||||
//toRemove.disableIntelligence();
|
||||
WorldGrid.RemoveWorldObject(toRemove);
|
||||
|
||||
if (toRemove.getParentZone() != null)
|
||||
toRemove.getParentZone().zoneMobSet.remove(toRemove);
|
||||
|
||||
DbManager.removeFromCache(toRemove);
|
||||
PlayerCharacter petOwner = toRemove.getOwner();
|
||||
|
||||
if (petOwner != null) {
|
||||
petOwner.setPet(null);
|
||||
toRemove.setOwner(null);
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
// we Found the move to remove, lets break the for loop so it doesnt look for more.
|
||||
|
||||
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, b);
|
||||
mca1.actionType = 3;
|
||||
mca1.setTargetType(b.getObjectType().ordinal());
|
||||
mca1.setTargetID(b.getObjectUUID());
|
||||
|
||||
mca1.setTargetType3(npc.getObjectType().ordinal());
|
||||
mca1.setTargetID3(npc.getObjectUUID());
|
||||
mca1.setAssetName1(b.getName());
|
||||
mca1.setUnknown54(1);
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, mca1);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
//Add Minion
|
||||
}
|
||||
else {
|
||||
Zone zone = npc.getParentZone();
|
||||
|
||||
if (zone == null)
|
||||
return true;
|
||||
|
||||
int maxSlots = 3;
|
||||
|
||||
if (npc.getContractID() == 842)
|
||||
maxSlots = 1;
|
||||
|
||||
if (npc.getSiegeMinionMap().size() == maxSlots)
|
||||
return true;
|
||||
|
||||
int mobBase;
|
||||
|
||||
switch (minionMsg.getMinion()){
|
||||
case 9:
|
||||
mobBase = 13171;
|
||||
break;
|
||||
case 2:
|
||||
mobBase = 13758;
|
||||
break;
|
||||
case 3:
|
||||
mobBase = 13757;
|
||||
break;
|
||||
case 4:
|
||||
mobBase = 2111;
|
||||
break;
|
||||
case 5:
|
||||
mobBase = 12402;
|
||||
break;
|
||||
case 6:
|
||||
mobBase = 2113;
|
||||
break;
|
||||
default:
|
||||
mobBase = minionMsg.getMinion();
|
||||
}
|
||||
|
||||
if (mobBase == 0)
|
||||
return true;
|
||||
|
||||
Mob toCreate = npc.createSiegeMob(mobBase, npc.getGuild(), zone, b.getLoc(), (short) 1);
|
||||
|
||||
if (toCreate == null)
|
||||
return true;
|
||||
|
||||
// toCreate.despawn();
|
||||
if (toCreate != null) {
|
||||
toCreate.setSpawnTime(60 * 15);
|
||||
toCreate.setTimeToSpawnSiege(System.currentTimeMillis() + (60 * 15 * 1000));
|
||||
toCreate.setDeathTime(System.currentTimeMillis());
|
||||
toCreate.setState(MobileFSM.STATE.Respawn);
|
||||
}
|
||||
}
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
mnm.setMessageType(1);
|
||||
Dispatch dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
} finally {
|
||||
npc.minionLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}else if (minionMsg.getNpcType() == Enum.GameObjectType.Mob.ordinal()){
|
||||
|
||||
Mob npc = Mob.getFromCache(minionMsg.getNpcID());
|
||||
|
||||
if (npc == null)
|
||||
return true;
|
||||
|
||||
Building b = BuildingManager.getBuildingFromCache(minionMsg.getBuildingID());
|
||||
|
||||
if (b == null)
|
||||
return true;
|
||||
|
||||
//clear minion
|
||||
|
||||
if (npc.minionLock.writeLock().tryLock()) {
|
||||
try {
|
||||
if (minionMsg.getType() == 2) {
|
||||
|
||||
Mob toRemove = Mob.getFromCache(minionMsg.getUUID());
|
||||
if (!npc.getSiegeMinionMap().containsKey(toRemove))
|
||||
return true;
|
||||
|
||||
if (!DbManager.MobQueries.REMOVE_FROM_GUARDS(npc.getObjectUUID(), toRemove.getMobBaseID(), npc.getSiegeMinionMap().get(toRemove)))
|
||||
return true;
|
||||
|
||||
toRemove.setState(MobileFSM.STATE.Disabled);
|
||||
npc.getSiegeMinionMap().remove(toRemove);
|
||||
|
||||
//toRemove.disableIntelligence();
|
||||
WorldGrid.RemoveWorldObject(toRemove);
|
||||
|
||||
if (toRemove.getParentZone() != null)
|
||||
toRemove.getParentZone().zoneMobSet.remove(toRemove);
|
||||
|
||||
DbManager.removeFromCache(toRemove);
|
||||
PlayerCharacter petOwner = toRemove.getOwner();
|
||||
|
||||
if (petOwner != null) {
|
||||
petOwner.setPet(null);
|
||||
toRemove.setOwner(null);
|
||||
PetMsg petMsg = new PetMsg(5, null);
|
||||
Dispatch dispatch = Dispatch.borrow(petOwner, petMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
// we Found the move to remove, lets break the for loop so it doesnt look for more.
|
||||
|
||||
ManageCityAssetsMsg mca1 = new ManageCityAssetsMsg(player, b);
|
||||
mca1.actionType = 3;
|
||||
mca1.setTargetType(b.getObjectType().ordinal());
|
||||
mca1.setTargetID(b.getObjectUUID());
|
||||
|
||||
mca1.setTargetType3(npc.getObjectType().ordinal());
|
||||
mca1.setTargetID3(npc.getObjectUUID());
|
||||
mca1.setAssetName1(b.getName());
|
||||
mca1.setUnknown54(1);
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, mca1);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);;
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
//Add Minion
|
||||
}
|
||||
else {
|
||||
Zone zone = npc.getParentZone();
|
||||
|
||||
if (zone == null)
|
||||
return true;
|
||||
|
||||
int maxSlots = 5;
|
||||
|
||||
if (npc.getContract().getContractID() == 842)
|
||||
maxSlots = 1;
|
||||
|
||||
switch (npc.getRank()){
|
||||
case 1:
|
||||
case 2:
|
||||
maxSlots = 1;
|
||||
break;
|
||||
case 3:
|
||||
maxSlots = 2;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
maxSlots = 3;
|
||||
break;
|
||||
case 6:
|
||||
maxSlots = 4;
|
||||
break;
|
||||
case 7:
|
||||
maxSlots = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
if (npc.getSiegeMinionMap().size() == maxSlots)
|
||||
return true;
|
||||
|
||||
int mobBase = npc.getMobBaseID();
|
||||
|
||||
if (mobBase == 0)
|
||||
return true;
|
||||
|
||||
String pirateName = NPC.getPirateName(mobBase);
|
||||
|
||||
if (!DbManager.MobQueries.ADD_TO_GUARDS(npc.getObjectUUID(), mobBase, pirateName, npc.getSiegeMinionMap().size() + 1))
|
||||
return true;
|
||||
|
||||
Mob toCreate = npc.createGuardMob(mobBase, npc.getGuild(), zone, b.getLoc(), npc.getLevel(),pirateName);
|
||||
|
||||
if (toCreate == null)
|
||||
return true;
|
||||
|
||||
// toCreate.despawn();
|
||||
if (toCreate != null) {
|
||||
toCreate.setTimeToSpawnSiege(System.currentTimeMillis() + MBServerStatics.FIFTEEN_MINUTES);
|
||||
toCreate.setDeathTime(System.currentTimeMillis());
|
||||
toCreate.setState(MobileFSM.STATE.Respawn);
|
||||
}
|
||||
}
|
||||
|
||||
ManageNPCMsg mnm = new ManageNPCMsg(npc);
|
||||
mnm.setMessageType(1);
|
||||
Dispatch dispatch = Dispatch.borrow(player, mnm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
}catch (Exception e){
|
||||
Logger.error(e);
|
||||
}finally {
|
||||
|
||||
npc.minionLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.MovementManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.MoveToPointMsg;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class MoveToPointHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public MoveToPointHandler() {
|
||||
super(MoveToPointMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
MoveToPointMsg msg = (MoveToPointMsg) baseMsg;
|
||||
|
||||
PlayerCharacter pc = (origin != null) ? (origin.getPlayerCharacter()) : null;
|
||||
if (pc == null)
|
||||
return false;
|
||||
|
||||
MovementManager.movement(msg, pc);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,569 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.Enum.ItemType;
|
||||
import engine.InterestManagement.RealmMap;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.*;
|
||||
import engine.math.Bounds;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.*;
|
||||
import engine.powers.PowersBase;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which actives
|
||||
* items such as charters and deeds in the character's inventory
|
||||
*/
|
||||
public class ObjectActionMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Reentrant lock for dropping banes
|
||||
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
public ObjectActionMsgHandler() {
|
||||
super(ObjectActionMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
ObjectActionMsg msg;
|
||||
PlayerCharacter player;
|
||||
CharacterItemManager itemMan;
|
||||
ArrayList<Long> comps;
|
||||
Dispatch dispatch;
|
||||
boolean waterbucketBypass = false;
|
||||
|
||||
// Member variable assignment
|
||||
msg = (ObjectActionMsg) baseMsg;
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
itemMan = player.getCharItemManager();
|
||||
|
||||
if (itemMan == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
comps = msg.getTargetCompID();
|
||||
|
||||
if (comps.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
long comp = comps.get(0);
|
||||
|
||||
if (((int) comp) != 0) {
|
||||
Item item = Item.getFromCache((int) comp);
|
||||
|
||||
if (item == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//dupe check
|
||||
if (!item.validForInventory(origin, player, itemMan)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemBase ib = item.getItemBase();
|
||||
|
||||
if (ib == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (itemMan.doesCharOwnThisItem(item.getObjectUUID())) {
|
||||
|
||||
if (ib.isConsumable() || ib.getType() == ItemType.FARMABLE) {
|
||||
|
||||
int uuid = ib.getUUID();
|
||||
int type = ib.getType().getValue();
|
||||
|
||||
switch (type) {
|
||||
case 27: //Mithril repair
|
||||
break;
|
||||
case 10: //charters
|
||||
//don't think they're handled here?
|
||||
break;
|
||||
case 19: //buildings
|
||||
//Call add building screen here, ib.getUseID() get's building ID
|
||||
|
||||
//if inside player city, center loc on tol. otherwise center on player.
|
||||
Vector3fImmutable loc = player.getLoc();
|
||||
Zone zone = ZoneManager.findSmallestZone(player.getLoc());
|
||||
|
||||
if (zone != null) {
|
||||
if (zone.isPlayerCity()) {
|
||||
loc = zone.getLoc();
|
||||
}
|
||||
}
|
||||
|
||||
PlaceAssetMsg pam = new PlaceAssetMsg();
|
||||
pam.setActionType(2);
|
||||
pam.setContractID(item.getObjectUUID());
|
||||
pam.setX(loc.getX() + 64); //offset grid from tol
|
||||
pam.setY(loc.getY());
|
||||
pam.setZ(loc.getZ() + 64); //offset grid from tol
|
||||
pam.addPlacementInfo(ib.getUseID());
|
||||
|
||||
dispatch = Dispatch.borrow(player, pam);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
//itemMan.consume(item); //temporary fix for dupe.. TODO Make Item Unusable after This message is sent.
|
||||
break;
|
||||
case 25: //furniture
|
||||
//Call add furniture screen here. ib.getUseID() get's furniture ID
|
||||
break;
|
||||
case 33:
|
||||
long shrineCompID = comps.get(1);
|
||||
Building shrineBuilding = BuildingManager.getBuilding((int)shrineCompID);
|
||||
if (shrineBuilding == null) {
|
||||
return true;
|
||||
}
|
||||
if (shrineBuilding.getBlueprint() != null && shrineBuilding.getBlueprint().getBuildingGroup() != engine.Enum.BuildingGroup.SHRINE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (shrineBuilding.getRank() == -1) {
|
||||
return true;
|
||||
}
|
||||
Shrine shrine = Shrine.shrinesByBuildingUUID.get(shrineBuilding.getObjectUUID());
|
||||
|
||||
if (shrine == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (shrine.addFavor(player, item)) {
|
||||
shrineBuilding.addEffectBit(1000000 << 2);
|
||||
shrineBuilding.updateEffects();
|
||||
shrineBuilding.removeEffectBit(1000000 << 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case 35:
|
||||
int charterType = 0;
|
||||
switch (uuid) {
|
||||
case 910020:
|
||||
charterType = 762228431;
|
||||
break;
|
||||
case 910021:
|
||||
charterType = -15978914;
|
||||
break;
|
||||
case 910022:
|
||||
charterType = -600065291;
|
||||
break;
|
||||
}
|
||||
if (claimRealm(player, charterType) == true) {
|
||||
itemMan.consume(item);
|
||||
}
|
||||
break;
|
||||
case 7: //rod of command
|
||||
long compID = comps.get(1);
|
||||
|
||||
int objectType = AbstractWorldObject.extractTypeID(compID).ordinal();
|
||||
Mob toCommand;
|
||||
if (objectType == engine.Enum.GameObjectType.Mob.ordinal()) {
|
||||
toCommand = Mob.getFromCache((int)compID);
|
||||
} //Only Command Mob Types.
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (toCommand == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!toCommand.isSiege())
|
||||
return true;
|
||||
|
||||
if (player.commandSiegeMinion(toCommand)) {
|
||||
itemMan.consume(item);
|
||||
}
|
||||
break;
|
||||
//ANNIVERSERY GIFT
|
||||
case 31:
|
||||
|
||||
|
||||
if (ib.getUUID() == 971012){
|
||||
int random = ThreadLocalRandom.current().nextInt(ItemBase.AnniverseryGifts.size());
|
||||
int annyID = ItemBase.AnniverseryGifts.get(random);
|
||||
|
||||
ItemBase annyIB = ItemBase.getItemBase(annyID);
|
||||
if (annyIB != null){
|
||||
Item gift = MobLoot.createItemForPlayer(player, annyIB);
|
||||
if (gift != null){
|
||||
itemMan.addItemToInventory(gift);
|
||||
itemMan.consume(item);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LootTable.CreateGamblerItem(item, player);
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case 30: //water bucket
|
||||
case 8: //potions, tears of saedron
|
||||
|
||||
case 5: //runes, petition, warrant, scrolls
|
||||
if (uuid > 3000 && uuid < 3050) { //Discipline Runes
|
||||
if (ApplyRuneMsg.applyRune(uuid, origin, player)) {
|
||||
itemMan.consume(item);
|
||||
}
|
||||
break;
|
||||
} else if (uuid > 249999 && uuid < 250123) { //stat and mastery runes
|
||||
if (ApplyRuneMsg.applyRune(uuid, origin, player)) {
|
||||
itemMan.consume(item);
|
||||
}
|
||||
break;
|
||||
} else if (uuid > 250114 && uuid < 250123) { //mastery runes
|
||||
if (ApplyRuneMsg.applyRune(uuid, origin, player)) {
|
||||
itemMan.consume(item);
|
||||
}
|
||||
break;
|
||||
} else if (uuid > 252122 && uuid < 252128) { //mastery runes
|
||||
if (ApplyRuneMsg.applyRune(uuid, origin, player)) {
|
||||
itemMan.consume(item);
|
||||
}
|
||||
break;
|
||||
} else if (uuid > 680069 && uuid < 680074) //Handle Charter, Deed, Petition, Warrant here
|
||||
{
|
||||
break;
|
||||
} else if (uuid > 910010 && uuid < 910019) {
|
||||
|
||||
int rank = uuid - 910010;
|
||||
|
||||
if (rank < 1 || rank > 8) {
|
||||
ChatManager.chatSystemError(player, "Invalid Rank for bane scroll!");
|
||||
return true;
|
||||
}
|
||||
// Only one banestone at a time
|
||||
lock.writeLock().lock();
|
||||
|
||||
try {
|
||||
if (Bane.summonBanestone(player, origin, rank) == true)
|
||||
itemMan.consume(item);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
break;
|
||||
} else if (uuid == 910010) { //tears of saedron
|
||||
if (comps.size() > 1) {
|
||||
removeRune(player, origin, comps.get(1).intValue());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
else if (item.getChargesRemaining() > 0) {
|
||||
ArrayList<Long> tarList = msg.getTargetCompID();
|
||||
AbstractWorldObject target = player;
|
||||
if (tarList.size() > 1) {
|
||||
long tarID = tarList.get(1);
|
||||
if (tarID != 0) {
|
||||
AbstractGameObject tarAgo = AbstractGameObject.getFromTypeAndID(tarID);
|
||||
if (tarAgo != null && tarAgo instanceof AbstractWorldObject) {
|
||||
target = (AbstractWorldObject) tarAgo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bypass for waterbuckets
|
||||
|
||||
// test character targeted
|
||||
|
||||
if (ib.getUUID() == 910005) {
|
||||
|
||||
// test for valid target type
|
||||
if (target.getObjectType() == Enum.GameObjectType.PlayerCharacter)
|
||||
waterbucketBypass = true;
|
||||
else {
|
||||
// test distance to structure
|
||||
Building targetBuilding = (Building) target;
|
||||
Bounds testBounds = Bounds.borrow();
|
||||
testBounds.setBounds(player.getLoc(), 25);
|
||||
|
||||
if (Bounds.collide(targetBuilding.getBounds(), testBounds, .1f) == false) {
|
||||
ChatManager.chatSystemError(player, "Not in range of structura for to heal!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Send piss bucket animation
|
||||
|
||||
VisualUpdateMessage vum = new VisualUpdateMessage(player, 16323);
|
||||
vum.configure();
|
||||
DispatchMessage.sendToAllInRange(player, vum);
|
||||
}
|
||||
|
||||
if (waterbucketBypass == false)
|
||||
PowersManager.applyPower(player, target, Vector3fImmutable.ZERO, ib.getUseID(), ib.getUseAmount(), true);
|
||||
|
||||
itemMan.consume(item);
|
||||
} else //just remove the item at this point
|
||||
itemMan.consume(item);
|
||||
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
player.cancelOnSpell();
|
||||
break;
|
||||
default: //shouldn't be here, consume item
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
// itemMan.consume(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO log item does not belong to player
|
||||
// System.out.println("Item does not belong to player");
|
||||
// Cleanup duped item here
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean claimRealm(PlayerCharacter player, int charterUUID) {
|
||||
|
||||
Guild guild;
|
||||
Realm realm;
|
||||
City city;
|
||||
Building tol;
|
||||
float hPMod;
|
||||
Warehouse warehouse;
|
||||
boolean hasResources = true;
|
||||
int resourceValue;
|
||||
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 176); // Only guild leaders can claim a territory
|
||||
return false;
|
||||
}
|
||||
|
||||
guild = player.getGuild();
|
||||
city = guild.getOwnedCity();
|
||||
|
||||
if (city == null) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 179); // Only landed guilds may claim a territory
|
||||
return false;
|
||||
}
|
||||
|
||||
if (city.isLocationOnCityGrid(player.getLoc()) == false) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 186); // Your tree is not inside a territory!
|
||||
return false;
|
||||
}
|
||||
|
||||
tol = city.getTOL();
|
||||
|
||||
if (tol.getRank() != 7) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 181); // Your tree must be rank 7 before claiming a territory
|
||||
return false;
|
||||
}
|
||||
|
||||
realm = RealmMap.getRealmForCity(city);
|
||||
|
||||
if (realm.getCanBeClaimed() == false) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 180); // This territory cannot be ruled by anyone
|
||||
return false;
|
||||
}
|
||||
|
||||
if (realm.isRuled() == true) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 178); // This territory is already claimed
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Realm.HasAllBlessings(player)) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 185); // You must seek the blessing of the three sages before you can rule
|
||||
return false;
|
||||
}
|
||||
|
||||
// Must have the required resources in warehouse to claim realm
|
||||
|
||||
warehouse = city.getWarehouse();
|
||||
|
||||
if (warehouse == null) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 188); // You must have a warehouse to become a capital
|
||||
return false;
|
||||
}
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.goldIB);
|
||||
|
||||
if (resourceValue < 5000000)
|
||||
hasResources = false;
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.stoneIB);
|
||||
|
||||
if (resourceValue < 8000)
|
||||
hasResources = false;
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.lumberIB);
|
||||
|
||||
if (resourceValue < 8000)
|
||||
hasResources = false;
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.galvorIB);
|
||||
|
||||
if (resourceValue < 15)
|
||||
hasResources = false;
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB);
|
||||
|
||||
if (resourceValue < 15)
|
||||
hasResources = false;
|
||||
|
||||
if (hasResources == false) {
|
||||
ErrorPopupMsg.sendErrorPopup(player, 184); // Insufficient gold or resources to upgrade to capital
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove resources from warehouse before claiming realm
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.goldIB);
|
||||
|
||||
if (DbManager.WarehouseQueries.updateGold(warehouse, resourceValue - 5000000) == true) {
|
||||
warehouse.getResources().put(Warehouse.goldIB, resourceValue - 5000000);
|
||||
warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.GOLD, 5000000);
|
||||
} else {
|
||||
Logger.error("gold update failed for warehouse of UUID:" + warehouse.getObjectUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.stoneIB);
|
||||
|
||||
if (DbManager.WarehouseQueries.updateStone(warehouse, resourceValue - 8000) == true) {
|
||||
warehouse.getResources().put(Warehouse.stoneIB, resourceValue - 8000);
|
||||
warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.STONE, 8000);
|
||||
} else {
|
||||
Logger.error( "stone update failed for warehouse of UUID:" + warehouse.getObjectUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.lumberIB);
|
||||
|
||||
if (DbManager.WarehouseQueries.updateLumber(warehouse, resourceValue - 8000) == true) {
|
||||
warehouse.getResources().put(Warehouse.lumberIB, resourceValue - 8000);
|
||||
warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.LUMBER, 8000);
|
||||
} else {
|
||||
Logger.error("lumber update failed for warehouse of UUID:" + warehouse.getObjectUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.galvorIB);
|
||||
|
||||
if (DbManager.WarehouseQueries.updateGalvor(warehouse, resourceValue - 15) == true) {
|
||||
warehouse.getResources().put(Warehouse.galvorIB, resourceValue - 15);
|
||||
warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.GALVOR, 15);
|
||||
} else {
|
||||
Logger.error("galvor update failed for warehouse of UUID:" + warehouse.getObjectUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
resourceValue = warehouse.getResources().get(Warehouse.wormwoodIB);
|
||||
|
||||
if (DbManager.WarehouseQueries.updateWormwood(warehouse, resourceValue - 15) == true) {
|
||||
warehouse.getResources().put(Warehouse.wormwoodIB, resourceValue - 15);
|
||||
warehouse.AddTransactionToWarehouse(engine.Enum.GameObjectType.Building, tol.getObjectUUID(), Enum.TransactionType.WITHDRAWL, Resource.WORMWOOD, 15);
|
||||
} else {
|
||||
Logger.error("wormwood update failed for warehouse of UUID:" + warehouse.getObjectUUID());
|
||||
return false;
|
||||
}
|
||||
|
||||
realm.claimRealmForCity(city, charterUUID);
|
||||
|
||||
tol.setRank(8);
|
||||
WorldGrid.updateObject(tol);
|
||||
|
||||
for (Building building : city.getParent().zoneBuildingSet) {
|
||||
|
||||
if (building.getBlueprintUUID() != 0) {
|
||||
|
||||
// TOL Health set through regular linear equation
|
||||
if (building.getBlueprint().getBuildingGroup() == BuildingGroup.TOL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hPMod = (building.getMaxHitPoints() * Realm.getRealmHealthMod(city));
|
||||
building.setMaxHitPoints(building.getMaxHitPoints() + hPMod);
|
||||
}
|
||||
}
|
||||
|
||||
if (!guild.getNation().equals(guild)) {
|
||||
guild.getNation().setRealmsOwned(guild.getNation().getRealmsOwned() + 1);
|
||||
GuildManager.updateAllGuildTags(guild.getNation());
|
||||
}
|
||||
|
||||
guild.setRealmsOwned(guild.getRealmsOwned() + 1);
|
||||
GuildManager.updateAllGuildTags(guild);
|
||||
|
||||
removeAllBlessings(player);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void removeAllBlessings(PlayerCharacter player) {
|
||||
|
||||
PowersBase[] powers = new PowersBase[3];
|
||||
|
||||
powers[0] = PowersManager.getPowerByIDString("BLS-POWER");
|
||||
powers[1] = PowersManager.getPowerByIDString("BLS-FORTUNE");
|
||||
powers[2] = PowersManager.getPowerByIDString("BLS-WISDOM");
|
||||
|
||||
for (PowersBase power : powers) {
|
||||
PowersManager.removeEffect(player, power.getActions().get(0), true, false);
|
||||
}
|
||||
|
||||
}
|
||||
// Handle activation of tears of seadron: Removes rune from player.
|
||||
|
||||
private static void removeRune(PlayerCharacter pc, ClientConnection origin, int runeID) {
|
||||
|
||||
if (pc == null || origin == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove only if rune is discipline
|
||||
if (runeID < 3001 || runeID > 3048) {
|
||||
return;
|
||||
}
|
||||
|
||||
//see if pc has rune
|
||||
ArrayList<CharacterRune> runes = pc.getRunes();
|
||||
|
||||
if (runes == null)
|
||||
return;
|
||||
|
||||
CharacterRune found = pc.getRune(runeID);
|
||||
|
||||
if (found == null)
|
||||
return;
|
||||
|
||||
//TODO see if player needs to refine skills or powers first
|
||||
//attempt remove rune from player
|
||||
|
||||
if (!CharacterRune.removeRune(pc, runeID))
|
||||
return;
|
||||
|
||||
//update client with removed rune.
|
||||
ApplyRuneMsg arm = new ApplyRuneMsg(pc.getObjectType().ordinal(), pc.getObjectUUID(), runeID);
|
||||
Dispatch dispatch = Dispatch.borrow(pc, arm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,397 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.OpenFriendsCondemnListMsg;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* client requests for various lists
|
||||
*/
|
||||
|
||||
public class OpenFriendsCondemnListMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public OpenFriendsCondemnListMsgHandler() {
|
||||
super(OpenFriendsCondemnListMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = SessionManager.getPlayerCharacter(origin);
|
||||
Building sourceBuilding;
|
||||
OpenFriendsCondemnListMsg msg;
|
||||
OpenFriendsCondemnListMsg openFriendsCondemnListMsg;
|
||||
Enum.FriendListType friendListType;
|
||||
Dispatch dispatch;
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
msg = (OpenFriendsCondemnListMsg) baseMsg;
|
||||
openFriendsCondemnListMsg = new OpenFriendsCondemnListMsg(msg);
|
||||
friendListType = Enum.FriendListType.getListTypeByID(msg.getMessageType());
|
||||
|
||||
if (friendListType == null){
|
||||
Logger.error("Invalid FriendListType for messageType " + msg.getMessageType());
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (friendListType) {
|
||||
case VIEWHERALDRY: // Heraldry
|
||||
|
||||
Heraldry.ValidateHeraldry(player.getObjectUUID());
|
||||
OpenFriendsCondemnListMsg outMsg = new OpenFriendsCondemnListMsg(msg);
|
||||
outMsg.setOrigin(origin);
|
||||
outMsg.setMessageType(2);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
case ADDHERALDRY:
|
||||
Heraldry.ValidateHeraldry(player.getObjectUUID());
|
||||
if (msg.getPlayerID() <= 0){
|
||||
//ErrorPopupMsg.sendErrorMsg(player, "Invalid Heraldry Object.");
|
||||
return true;
|
||||
}
|
||||
AbstractCharacter toAdd = null;
|
||||
if (msg.getPlayerType() == GameObjectType.PlayerCharacter.ordinal())
|
||||
toAdd = PlayerCharacter.getFromCache(msg.getPlayerID());
|
||||
else if (msg.getPlayerType() == GameObjectType.NPC.ordinal())
|
||||
toAdd = NPC.getFromCache(msg.getPlayerID());
|
||||
else if (msg.getPlayerType() == GameObjectType.Mob.ordinal())
|
||||
toAdd = Mob.getFromCache(msg.getPlayerID());
|
||||
else{
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Invalid Heraldry Object.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (toAdd == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Invalid Heraldry Object.");
|
||||
return true;
|
||||
}
|
||||
|
||||
Heraldry.AddToHeraldy(player.getObjectUUID(), toAdd);
|
||||
|
||||
|
||||
outMsg = new OpenFriendsCondemnListMsg(msg);
|
||||
outMsg.setOrigin(origin);
|
||||
outMsg.setMessageType(2);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
break;
|
||||
case REMOVEHERALDRY:
|
||||
Heraldry.ValidateHeraldry(player.getObjectUUID());
|
||||
Heraldry.RemoveFromHeraldy(player.getObjectUUID(), msg.getPlayerID());
|
||||
|
||||
|
||||
outMsg = new OpenFriendsCondemnListMsg(msg);
|
||||
outMsg.setOrigin(origin);
|
||||
outMsg.setMessageType(2);
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
break;
|
||||
|
||||
case DEALTHS: // Death List
|
||||
openFriendsCondemnListMsg.updateMsg(8, new ArrayList<>(player.pvpDeaths));
|
||||
dispatch = Dispatch.borrow(player, openFriendsCondemnListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
case KILLS: // Kill List
|
||||
openFriendsCondemnListMsg.updateMsg(10, new ArrayList<>(player.pvpKills));
|
||||
dispatch = Dispatch.borrow(player, openFriendsCondemnListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
case VIEWCONDEMN:
|
||||
|
||||
sourceBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (sourceBuilding == null)
|
||||
return true;
|
||||
|
||||
openFriendsCondemnListMsg = new OpenFriendsCondemnListMsg(12, sourceBuilding.getCondemned(), sourceBuilding.reverseKOS);
|
||||
openFriendsCondemnListMsg.configure();
|
||||
dispatch = Dispatch.borrow(player, openFriendsCondemnListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
//msg.updateMsg(12, DbManager.GuildQueries.)
|
||||
break;
|
||||
//REMOVE CONDEMN
|
||||
case REMOVECONDEMN:
|
||||
|
||||
sourceBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (sourceBuilding == null)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(sourceBuilding, player))
|
||||
return true;
|
||||
|
||||
Condemned removeCondemn = sourceBuilding.getCondemned().get(msg.getRemoveFriendID());
|
||||
|
||||
if (removeCondemn == null)
|
||||
return true;
|
||||
|
||||
if (!DbManager.BuildingQueries.REMOVE_FROM_CONDEMNED_LIST(removeCondemn.getParent(), removeCondemn.getPlayerUID(), removeCondemn.getGuildUID(), removeCondemn.getFriendType()))
|
||||
return true;
|
||||
|
||||
sourceBuilding.getCondemned().remove(msg.getRemoveFriendID());
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
case TOGGLEACTIVE:
|
||||
|
||||
sourceBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (sourceBuilding == null)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(sourceBuilding, player))
|
||||
return true;
|
||||
|
||||
Condemned condemn = sourceBuilding.getCondemned().get(msg.getRemoveFriendID());
|
||||
|
||||
if (condemn == null)
|
||||
return true;
|
||||
|
||||
condemn.setActive(msg.isReverseKOS());
|
||||
openFriendsCondemnListMsg.setReverseKOS(condemn.isActive());
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case REVERSEKOS:
|
||||
|
||||
|
||||
sourceBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (sourceBuilding == null)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(sourceBuilding, player))
|
||||
return true;
|
||||
|
||||
if (!sourceBuilding.setReverseKOS(msg.isReverseKOS()))
|
||||
return true;
|
||||
break;
|
||||
|
||||
//ADD GUILD CONDEMN
|
||||
case ADDCONDEMN:
|
||||
|
||||
sourceBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (sourceBuilding == null)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(sourceBuilding, player))
|
||||
return true;
|
||||
|
||||
switch (msg.getInviteType()) {
|
||||
case 2:
|
||||
|
||||
if (msg.getPlayerID() == 0)
|
||||
return true;
|
||||
|
||||
if (msg.getPlayerType() != GameObjectType.PlayerCharacter.ordinal())
|
||||
return true;
|
||||
|
||||
PlayerCharacter playerCharacter = PlayerCharacter.getFromCache(msg.getPlayerID());
|
||||
|
||||
if (playerCharacter == null)
|
||||
return true;
|
||||
|
||||
if (Guild.sameNationExcludeErrant(sourceBuilding.getGuild(), playerCharacter.getGuild()))
|
||||
return true;
|
||||
|
||||
if (sourceBuilding.getCondemned().containsKey(playerCharacter.getObjectUUID()))
|
||||
return true;
|
||||
|
||||
if (!DbManager.BuildingQueries.ADD_TO_CONDEMNLIST(sourceBuilding.getObjectUUID(), playerCharacter.getObjectUUID(), msg.getGuildID(), msg.getInviteType())) {
|
||||
Logger.debug( "Failed to add Condemned: " + playerCharacter.getFirstName() + " to Building With UID " + sourceBuilding.getObjectUUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
sourceBuilding.getCondemned().put(playerCharacter.getObjectUUID(), new Condemned(playerCharacter.getObjectUUID(), sourceBuilding.getObjectUUID(), msg.getGuildID(), msg.getInviteType()));
|
||||
break;
|
||||
case 4:
|
||||
if (msg.getGuildID() == 0)
|
||||
return true;
|
||||
|
||||
if (sourceBuilding.getCondemned().containsKey(msg.getGuildID()))
|
||||
return true;
|
||||
|
||||
Guild condemnedGuild = Guild.getGuild(msg.getGuildID());
|
||||
|
||||
if (condemnedGuild == null)
|
||||
return true;
|
||||
|
||||
if (!DbManager.BuildingQueries.ADD_TO_CONDEMNLIST(sourceBuilding.getObjectUUID(), msg.getPlayerID(), condemnedGuild.getObjectUUID(), msg.getInviteType())) {
|
||||
Logger.debug("Failed to add Condemned: " + condemnedGuild.getName() + " to Building With UID " + sourceBuilding.getObjectUUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
sourceBuilding.getCondemned().put(condemnedGuild.getObjectUUID(), new Condemned(msg.getPlayerID(), sourceBuilding.getObjectUUID(), condemnedGuild.getObjectUUID(), msg.getInviteType()));
|
||||
break;
|
||||
case 5:
|
||||
if (msg.getNationID() == 0)
|
||||
return true;
|
||||
|
||||
if (sourceBuilding.getCondemned().containsKey(msg.getNationID()))
|
||||
return true;
|
||||
|
||||
Guild condemnedNation = Guild.getGuild(msg.getNationID());
|
||||
|
||||
if (condemnedNation == null)
|
||||
return true;
|
||||
|
||||
if (!DbManager.BuildingQueries.ADD_TO_CONDEMNLIST(sourceBuilding.getObjectUUID(), msg.getPlayerID(), condemnedNation.getObjectUUID(), msg.getInviteType())) {
|
||||
Logger.debug( "Failed to add Condemned: " + condemnedNation.getName() + " to Building With UID " + sourceBuilding.getObjectUUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
sourceBuilding.getCondemned().put(condemnedNation.getObjectUUID(), new Condemned(msg.getPlayerID(), sourceBuilding.getObjectUUID(), condemnedNation.getObjectUUID(), msg.getInviteType()));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
openFriendsCondemnListMsg = new OpenFriendsCondemnListMsg(12, sourceBuilding.getCondemned(), sourceBuilding.reverseKOS);
|
||||
openFriendsCondemnListMsg.configure();
|
||||
dispatch = Dispatch.borrow(player, openFriendsCondemnListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
//ADD FRIEND BUILDING
|
||||
case ADDFRIEND:
|
||||
sourceBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (sourceBuilding == null)
|
||||
return true;
|
||||
|
||||
if (msg.getGuildID() == 0)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(sourceBuilding, player))
|
||||
return true;
|
||||
|
||||
PlayerCharacter playerCharacter = null;
|
||||
|
||||
|
||||
|
||||
Guild guildInvited = Guild.getGuild(msg.getGuildID());
|
||||
|
||||
if (guildInvited == null)
|
||||
return true;
|
||||
|
||||
//Check to see if the invited is already on the friends list.
|
||||
switch (msg.getInviteType()) {
|
||||
case 7:
|
||||
playerCharacter = PlayerCharacter.getFromCache(msg.getPlayerID());
|
||||
if (playerCharacter == null)
|
||||
return true;
|
||||
if (sourceBuilding.getFriends().containsKey(playerCharacter.getObjectUUID()))
|
||||
return true;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
if (sourceBuilding.getFriends().containsKey(guildInvited.getObjectUUID()))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!DbManager.BuildingQueries.ADD_TO_FRIENDS_LIST(sourceBuilding.getObjectUUID(), msg.getPlayerID(), guildInvited.getObjectUUID(), msg.getInviteType())) {
|
||||
Logger.debug( "Failed to add Friend: " + playerCharacter.getFirstName() + " to Building With UID " + sourceBuilding.getObjectUUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (msg.getInviteType()) {
|
||||
case 7:
|
||||
sourceBuilding.getFriends().put(playerCharacter.getObjectUUID(), new BuildingFriends(playerCharacter.getObjectUUID(), sourceBuilding.getObjectUUID(), playerCharacter.getGuild().getObjectUUID(), 7));
|
||||
break;
|
||||
case 8:
|
||||
sourceBuilding.getFriends().put(guildInvited.getObjectUUID(), new BuildingFriends(msg.getPlayerID(), sourceBuilding.getObjectUUID(), guildInvited.getObjectUUID(), 8));
|
||||
break;
|
||||
case 9:
|
||||
sourceBuilding.getFriends().put(guildInvited.getObjectUUID(), new BuildingFriends(msg.getPlayerID(), sourceBuilding.getObjectUUID(), guildInvited.getObjectUUID(), 9));
|
||||
break;
|
||||
}
|
||||
|
||||
openFriendsCondemnListMsg = new OpenFriendsCondemnListMsg(26, sourceBuilding.getFriends());
|
||||
openFriendsCondemnListMsg.configure();
|
||||
|
||||
dispatch = Dispatch.borrow(player, openFriendsCondemnListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
//REMOVE from friends list.
|
||||
case REMOVEFRIEND:
|
||||
sourceBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (sourceBuilding == null)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(sourceBuilding, player))
|
||||
return true;
|
||||
|
||||
BuildingFriends friend = sourceBuilding.getFriends().get(msg.getRemoveFriendID());
|
||||
|
||||
if (friend == null)
|
||||
return true;
|
||||
|
||||
if (!DbManager.BuildingQueries.REMOVE_FROM_FRIENDS_LIST(sourceBuilding.getObjectUUID(), friend.getPlayerUID(), friend.getGuildUID(), friend.getFriendType())) {
|
||||
Logger.debug( "Failed to remove Friend: " + msg.getRemoveFriendID() + " from Building With UID " + sourceBuilding.getObjectUUID());
|
||||
return true;
|
||||
}
|
||||
sourceBuilding.getFriends().remove(msg.getRemoveFriendID());
|
||||
|
||||
openFriendsCondemnListMsg = new OpenFriendsCondemnListMsg(26, sourceBuilding.getFriends());
|
||||
openFriendsCondemnListMsg.configure();
|
||||
dispatch = Dispatch.borrow(player, openFriendsCondemnListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
break;
|
||||
//view Friends
|
||||
case VIEWFRIENDS:
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
if (building == null)
|
||||
return true;
|
||||
|
||||
if (!BuildingManager.PlayerCanControlNotOwner(building, player))
|
||||
return true;
|
||||
|
||||
//this message is sent twice back?????
|
||||
|
||||
openFriendsCondemnListMsg = new OpenFriendsCondemnListMsg(26, building.getFriends());
|
||||
openFriendsCondemnListMsg.configure();
|
||||
|
||||
|
||||
dispatch = Dispatch.borrow(player, openFriendsCondemnListMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,575 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.ProfitType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.math.FastMath;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.*;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which keeps
|
||||
* client's tcp connection open.
|
||||
*/
|
||||
public class OrderNPCMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Constants used for incoming message type
|
||||
|
||||
private static final int CLIENT_UPGRADE_REQUEST = 3;
|
||||
private static final int CLIENT_REDEED_REQUEST = 6;
|
||||
private static final int SVR_CLOSE_WINDOW = 4;
|
||||
|
||||
public OrderNPCMsgHandler() {
|
||||
super(OrderNPCMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declarations
|
||||
|
||||
PlayerCharacter player;
|
||||
NPC npc;
|
||||
Mob mob;
|
||||
Building building;
|
||||
OrderNPCMsg orderNPCMsg;
|
||||
ManageCityAssetsMsg outMsg;
|
||||
|
||||
// Member variable assignment
|
||||
orderNPCMsg = (OrderNPCMsg) baseMsg;
|
||||
|
||||
if (origin.ordernpcspam > System.currentTimeMillis())
|
||||
return true;
|
||||
|
||||
origin.ordernpcspam = System.currentTimeMillis() + 500;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
if (orderNPCMsg.getActionType() == 28) {
|
||||
OrderNPCMsgHandler.handleCityCommand(orderNPCMsg, player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (orderNPCMsg.getObjectType() == GameObjectType.NPC.ordinal()) {
|
||||
|
||||
npc = NPC.getFromCache(orderNPCMsg.getNpcUUID());
|
||||
|
||||
if (npc == null)
|
||||
return true;
|
||||
|
||||
building = BuildingManager.getBuildingFromCache(orderNPCMsg.getBuildingUUID());
|
||||
|
||||
if (building == null)
|
||||
return true;
|
||||
|
||||
if (building.getHirelings().containsKey(npc) == false)
|
||||
return true;
|
||||
|
||||
|
||||
if (player.getCharItemManager().getTradingWith() != null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot barter and trade with same timings.");
|
||||
return true;
|
||||
}
|
||||
|
||||
player.lastBuildingAccessed = building.getObjectUUID();
|
||||
|
||||
switch (orderNPCMsg.getActionType()) {
|
||||
|
||||
case 2:
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (ManageCityAssetMsgHandler.playerCanManageNotFriends(player, building) == false)
|
||||
return true;
|
||||
|
||||
if (building.getHirelings().containsKey(npc) == false)
|
||||
return true;
|
||||
|
||||
if (npc.remove() == false) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
ManageCityAssetsMsg manageCityAssetsMsg = new ManageCityAssetsMsg();
|
||||
manageCityAssetsMsg.actionType = SVR_CLOSE_WINDOW;
|
||||
manageCityAssetsMsg.setTargetType(building.getObjectType().ordinal());
|
||||
manageCityAssetsMsg.setTargetID(building.getObjectUUID());
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, manageCityAssetsMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
|
||||
case CLIENT_UPGRADE_REQUEST:
|
||||
|
||||
if (BuildingManager.playerCanManage(player, building) == false)
|
||||
return true;
|
||||
|
||||
processUpgradeNPC(player, npc);
|
||||
|
||||
outMsg = new ManageCityAssetsMsg(player, building);
|
||||
|
||||
// Action TYPE
|
||||
outMsg.actionType = 3;
|
||||
outMsg.setTargetType(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID(building.getObjectUUID());
|
||||
outMsg.setTargetType3(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID3(building.getObjectUUID());
|
||||
outMsg.setAssetName1(building.getName());
|
||||
outMsg.setUnknown54(1);
|
||||
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
break;
|
||||
case CLIENT_REDEED_REQUEST:
|
||||
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
return true;
|
||||
|
||||
processRedeedNPC(npc, building, origin);
|
||||
return true;
|
||||
//MB TODO HANDLE all profits.
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
return true;
|
||||
|
||||
modifySellProfit(orderNPCMsg, origin);
|
||||
dispatch = Dispatch.borrow(player, orderNPCMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
return true;
|
||||
|
||||
modifyBuyProfit(orderNPCMsg, origin);
|
||||
dispatch = Dispatch.borrow(player, orderNPCMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validation check Owner or IC or friends
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
if (BuildingManager.playerCanManage(player, building) == false)
|
||||
return true;
|
||||
|
||||
ManageNPCMsg manageNPCMsg = new ManageNPCMsg(npc);
|
||||
Dispatch dispatch = Dispatch.borrow(player, manageNPCMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
|
||||
} else if (orderNPCMsg.getObjectType() == GameObjectType.Mob.ordinal()) {
|
||||
|
||||
mob = Mob.getFromCacheDBID(orderNPCMsg.getNpcUUID());
|
||||
|
||||
if (mob == null)
|
||||
return true;
|
||||
|
||||
building = BuildingManager.getBuildingFromCache(orderNPCMsg.getBuildingUUID());
|
||||
|
||||
if (building == null)
|
||||
return true;
|
||||
|
||||
if (!building.getHirelings().containsKey(mob))
|
||||
return true;
|
||||
|
||||
if (player.getCharItemManager().getTradingWith() != null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot barter and trade with same timings.");
|
||||
return true;
|
||||
}
|
||||
|
||||
player.lastBuildingAccessed = building.getObjectUUID();
|
||||
|
||||
switch (orderNPCMsg.getActionType()) {
|
||||
case 2:
|
||||
|
||||
if (BuildingManager.playerCanManage(player, building) == false)
|
||||
return true;
|
||||
|
||||
if (building.getHirelings().containsKey(mob) == false)
|
||||
return true;
|
||||
|
||||
if (mob.remove(building) == false) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
ManageCityAssetsMsg manageCityAssetsMsg = new ManageCityAssetsMsg();
|
||||
manageCityAssetsMsg.actionType = SVR_CLOSE_WINDOW;
|
||||
manageCityAssetsMsg.setTargetType(building.getObjectType().ordinal());
|
||||
manageCityAssetsMsg.setTargetID(building.getObjectUUID());
|
||||
Dispatch dispatch = Dispatch.borrow(player, manageCityAssetsMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case 3:
|
||||
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
return true;
|
||||
|
||||
processUpgradeNPC(player, mob);
|
||||
|
||||
outMsg = new ManageCityAssetsMsg(player, building);
|
||||
|
||||
// Action TYPE
|
||||
outMsg.actionType = 3;
|
||||
outMsg.setTargetType(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID(building.getObjectUUID());
|
||||
outMsg.setTargetType3(building.getObjectType().ordinal());
|
||||
outMsg.setTargetID3(building.getObjectUUID());
|
||||
outMsg.setAssetName1(building.getName());
|
||||
outMsg.setUnknown54(1);
|
||||
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
break;
|
||||
case 6:
|
||||
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
return true;
|
||||
|
||||
processRedeedNPC(mob, building, origin);
|
||||
return true;
|
||||
//MB TODO HANDLE all profits.
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
break;
|
||||
}
|
||||
|
||||
// Validation check Owner or IC
|
||||
if (BuildingManager.PlayerCanControlNotOwner(building, player) == false)
|
||||
if (BuildingManager.playerCanManage(player, building) == false)
|
||||
return true;
|
||||
|
||||
ManageNPCMsg manageNPCMsg = new ManageNPCMsg(mob);
|
||||
Dispatch dispatch = Dispatch.borrow(player, manageNPCMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void modifyBuyProfit(OrderNPCMsg msg, ClientConnection origin) {
|
||||
NPC npc;
|
||||
PlayerCharacter player;
|
||||
Building building;
|
||||
float percent;
|
||||
|
||||
ProfitType profitType = null;
|
||||
player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
npc = NPC.getFromCache(msg.getNpcUUID());
|
||||
|
||||
if (npc == null)
|
||||
return;
|
||||
|
||||
building = npc.getBuilding();
|
||||
|
||||
if (building == null)
|
||||
return;
|
||||
|
||||
NPCProfits profit = NPC.GetNPCProfits(npc);
|
||||
|
||||
if (profit == null)
|
||||
return;
|
||||
|
||||
switch (msg.getActionType()) {
|
||||
case 10:
|
||||
profitType = ProfitType.BuyNormal;
|
||||
break;
|
||||
case 11:
|
||||
profitType = ProfitType.BuyGuild;
|
||||
break;
|
||||
case 12:
|
||||
profitType = ProfitType.BuyNation;
|
||||
}
|
||||
|
||||
percent = msg.getBuySellPercent();
|
||||
percent = FastMath.clamp(percent, 0.0f, 1.0f);
|
||||
|
||||
NPCProfits.UpdateProfits(npc, profit, profitType, percent);
|
||||
}
|
||||
|
||||
private static void modifySellProfit(OrderNPCMsg orderNPCMsg, ClientConnection origin) {
|
||||
NPC npc;
|
||||
PlayerCharacter player;
|
||||
Building building;
|
||||
float percent;
|
||||
|
||||
ProfitType profitType = null;
|
||||
|
||||
player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
npc = NPC.getFromCache(orderNPCMsg.getNpcUUID());
|
||||
|
||||
if (npc == null)
|
||||
return;
|
||||
|
||||
building = npc.getBuilding();
|
||||
|
||||
if (building == null)
|
||||
return;
|
||||
|
||||
NPCProfits profit = NPC.GetNPCProfits(npc);
|
||||
|
||||
if (profit == null)
|
||||
return;
|
||||
|
||||
switch (orderNPCMsg.getActionType()) {
|
||||
case 7:
|
||||
profitType = ProfitType.SellNormal;
|
||||
break;
|
||||
case 8:
|
||||
profitType = ProfitType.SellGuild;
|
||||
break;
|
||||
case 9:
|
||||
profitType = ProfitType.SellNation;
|
||||
}
|
||||
|
||||
percent = orderNPCMsg.getBuySellPercent();
|
||||
|
||||
percent -= 1f;
|
||||
percent = FastMath.clamp(percent, 0.0f, 3.0f);
|
||||
|
||||
NPCProfits.UpdateProfits(npc, profit, profitType, percent);
|
||||
}
|
||||
|
||||
private static void handleCityCommand(OrderNPCMsg orderNpcMsg, PlayerCharacter player) {
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(orderNpcMsg.getBuildingUUID());
|
||||
|
||||
if (building == null)
|
||||
return;
|
||||
|
||||
if (ManageCityAssetMsgHandler.playerCanManageNotFriends(player, building) == false)
|
||||
return;
|
||||
|
||||
if (orderNpcMsg.getPatrolSize() >= 20)
|
||||
Logger.info(player.getName() + " is attempting to add patrol points amount " + orderNpcMsg.getPatrolSize());
|
||||
|
||||
if (orderNpcMsg.getSentrySize() >= 20)
|
||||
Logger.info(player.getName() + " is attempting to add patrol points amount " + orderNpcMsg.getSentryPoints());
|
||||
|
||||
if (orderNpcMsg.getPatrolPoints() != null) {
|
||||
|
||||
if ( !AddPatrolPoints(building.getObjectUUID(), orderNpcMsg.getPatrolPoints())){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Patrol Points must be placed on city zone.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (AbstractCharacter guard : building.getHirelings().keySet()) {
|
||||
if (guard.getObjectType() == GameObjectType.Mob)
|
||||
((Mob) guard).setPatrolPointIndex(0);
|
||||
}
|
||||
} else if (building.getPatrolPoints() != null)
|
||||
ClearPatrolPoints(building.getObjectUUID());
|
||||
|
||||
if (orderNpcMsg.getSentryPoints() != null) {
|
||||
AddSentryPoints(building.getObjectUUID(), orderNpcMsg.getSentryPoints());
|
||||
} else if (building.getSentryPoints() != null)
|
||||
ClearSentryPoints(building.getObjectUUID());
|
||||
|
||||
// Dispatch dispatch = Dispatch.borrow(pc, msg);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
}
|
||||
|
||||
private static void processUpgradeNPC(PlayerCharacter player, AbstractCharacter abstractCharacter) {
|
||||
|
||||
Building building;
|
||||
|
||||
switch (abstractCharacter.getObjectType()) {
|
||||
|
||||
case NPC:
|
||||
NPC npc = (NPC) abstractCharacter;
|
||||
building = npc.getBuilding();
|
||||
|
||||
// Cannot upgrade an npc not within a building
|
||||
|
||||
if (building == null)
|
||||
return;
|
||||
|
||||
City buildingCity = building.getCity();
|
||||
|
||||
if (buildingCity == null) {
|
||||
npc.processUpgradeNPC(player);
|
||||
return;
|
||||
}
|
||||
|
||||
buildingCity.transactionLock.writeLock().lock();
|
||||
|
||||
try {
|
||||
npc.processUpgradeNPC(player);
|
||||
} catch (Exception e) {
|
||||
Logger.error(e);
|
||||
} finally {
|
||||
buildingCity.transactionLock.writeLock().unlock();
|
||||
}
|
||||
break;
|
||||
case Mob:
|
||||
|
||||
Mob mob = (Mob) abstractCharacter;
|
||||
building = mob.getBuilding();
|
||||
|
||||
if (mob.getBuilding() == null)
|
||||
return;
|
||||
|
||||
City mobCity = building.getCity();
|
||||
|
||||
if (mobCity == null) {
|
||||
mob.processUpgradeMob(player);
|
||||
return;
|
||||
}
|
||||
|
||||
mobCity.transactionLock.writeLock().lock();
|
||||
|
||||
try {
|
||||
mob.processUpgradeMob(player);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
Logger.error(e);
|
||||
} finally {
|
||||
mobCity.transactionLock.writeLock().unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void processRedeedNPC(AbstractCharacter abstractCharacter, Building building, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
switch (abstractCharacter.getObjectType()) {
|
||||
case NPC:
|
||||
NPC npc = (NPC) abstractCharacter;
|
||||
|
||||
Building cityBuilding = npc.getBuilding();
|
||||
|
||||
if (cityBuilding == null)
|
||||
return;
|
||||
|
||||
npc.processRedeedNPC(origin);
|
||||
break;
|
||||
case Mob:
|
||||
Mob mob = (Mob) abstractCharacter;
|
||||
mob.processRedeedMob(origin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean AddPatrolPoints(int buildingID, ArrayList<Vector3fImmutable> patrolPoints) {
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(buildingID);
|
||||
|
||||
if (building == null)
|
||||
return false;
|
||||
|
||||
Zone zone = building.getParentZone();
|
||||
|
||||
if (zone == null)
|
||||
return false;
|
||||
|
||||
if (zone.getPlayerCityUUID() == 0)
|
||||
return false;
|
||||
|
||||
City city = building.getCity();
|
||||
|
||||
if (city == null)
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
//clear first.
|
||||
|
||||
for (Vector3fImmutable point : patrolPoints) {
|
||||
|
||||
if (city.isLocationOnCityZone(point) == false){
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DbManager.BuildingQueries.CLEAR_PATROL(buildingID);
|
||||
|
||||
for (Vector3fImmutable point : patrolPoints) {
|
||||
|
||||
if (!DbManager.BuildingQueries.ADD_TO_PATROL(buildingID, point))
|
||||
return false;
|
||||
}
|
||||
building.patrolPoints = patrolPoints;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean AddSentryPoints(int buildingID, ArrayList<Vector3fImmutable> sentryPoints) {
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(buildingID);
|
||||
|
||||
if (building == null)
|
||||
return false;
|
||||
|
||||
building.sentryPoints = sentryPoints;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean ClearPatrolPoints(int buildingID) {
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(buildingID);
|
||||
|
||||
if (building == null)
|
||||
return false;
|
||||
|
||||
if (building.patrolPoints == null)
|
||||
return true;
|
||||
|
||||
if (DbManager.BuildingQueries.CLEAR_PATROL(buildingID) == false)
|
||||
return false;
|
||||
|
||||
building.patrolPoints.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean ClearSentryPoints(int buildingID) {
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(buildingID);
|
||||
|
||||
if (building == null)
|
||||
return false;
|
||||
|
||||
if (building.sentryPoints == null)
|
||||
return true;
|
||||
|
||||
building.sentryPoints.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,90 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.AllianceType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.AllianceChangeMsg;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.RecommendNationMsg;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* protecting and unprotecting city assets
|
||||
*/
|
||||
public class RecommendNationMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public RecommendNationMsgHandler() {
|
||||
super(RecommendNationMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
RecommendNationMsg msg;
|
||||
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (RecommendNationMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
RecommendNationMsgHandler.RecommendNation(player.getGuild(), Guild.getGuild(msg.getGuildID()), msg, origin);
|
||||
|
||||
|
||||
|
||||
|
||||
// dispatch = Dispatch.borrow(player, baseMsg);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void RecommendNation(Guild fromGuild, Guild toGuild, RecommendNationMsg msg, ClientConnection origin) {
|
||||
|
||||
// Member variable declaration
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
if (fromGuild == null)
|
||||
return;
|
||||
|
||||
if (toGuild == null)
|
||||
return;
|
||||
|
||||
AllianceType allianceType;
|
||||
if (msg.getAlly() == 1)
|
||||
allianceType = AllianceType.RecommendedAlly;
|
||||
else
|
||||
allianceType = AllianceType.RecommendedEnemy;
|
||||
|
||||
if (!fromGuild.addGuildToAlliance(new AllianceChangeMsg(origin.getPlayerCharacter(),fromGuild.getObjectUUID(), toGuild.getObjectUUID(), (byte)0, 0), allianceType, toGuild, origin.getPlayerCharacter()))
|
||||
return;
|
||||
String alliance = msg.getAlly() == 1? "ally" : "enemy";
|
||||
|
||||
ChatManager.chatGuildInfo(fromGuild, origin.getPlayerCharacter().getFirstName() + " has recommended " + toGuild.getName() + " as an " + alliance );
|
||||
|
||||
// dispatch = Dispatch.borrow(origin.getPlayerCharacter(), msg);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.RemoveFriendMessage;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.PlayerFriends;
|
||||
|
||||
|
||||
|
||||
public class RemoveFriendHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public RemoveFriendHandler() {
|
||||
super(RemoveFriendMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
RemoveFriendMessage msg = (RemoveFriendMessage)baseMsg;
|
||||
|
||||
HandleRemoveFriend(player,msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void HandleRemoveFriend(PlayerCharacter player, RemoveFriendMessage msg){
|
||||
|
||||
//No friends in list. Early exit.
|
||||
PlayerFriends.RemoveFromFriends(player.getObjectUUID(), msg.friendID);
|
||||
PlayerFriends.RemoveFromFriends(msg.friendID, player.getObjectUUID());
|
||||
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
|
||||
msg = new RemoveFriendMessage(msg.friendID);
|
||||
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
import engine.net.client.msg.group.RemoveFromGroupMsg;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class RemoveFromGroupHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public RemoveFromGroupHandler() {
|
||||
super(RemoveFromGroupMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Declar member variables
|
||||
|
||||
PlayerCharacter source;
|
||||
PlayerCharacter target;
|
||||
RemoveFromGroupMsg msg;
|
||||
Group group;
|
||||
GroupUpdateMsg gim;
|
||||
ClientConnection gcc;
|
||||
Set<PlayerCharacter> groupMembers;
|
||||
|
||||
// Assign member variables
|
||||
|
||||
msg = (RemoveFromGroupMsg) baseMsg;
|
||||
|
||||
source = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (source == null)
|
||||
return false;
|
||||
|
||||
group = GroupManager.getGroup(source);
|
||||
|
||||
if (group == null)
|
||||
return false;
|
||||
|
||||
if (group.getGroupLead() != source) // Only group lead can remove
|
||||
return false;
|
||||
|
||||
target = SessionManager.getPlayerCharacterByID(msg.getTargetID());
|
||||
|
||||
if (target == null)
|
||||
return false;
|
||||
|
||||
if (target == source) { // can't remove self, must quit
|
||||
RemoveFromGroupMsg reply = new RemoveFromGroupMsg();
|
||||
reply.setResponse(1);
|
||||
Dispatch dispatch = Dispatch.borrow(source, reply);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, engine.Enum.DispatchChannel.SECONDARY);
|
||||
return false;
|
||||
}
|
||||
|
||||
gcc = SessionManager.getClientConnection(target);
|
||||
|
||||
if (gcc != null) {
|
||||
|
||||
// Cleanup group window for player quiting
|
||||
|
||||
groupMembers = group.getMembers();
|
||||
|
||||
for (PlayerCharacter groupMember : groupMembers) {
|
||||
|
||||
if (groupMember == null)
|
||||
continue;
|
||||
|
||||
gim = new GroupUpdateMsg();
|
||||
gim.setGroup(group);
|
||||
gim.setPlayer(target);
|
||||
gim.setMessageType(3);
|
||||
gim.setPlayer(groupMember);
|
||||
Dispatch dispatch = Dispatch.borrow(target, gim);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from group and clean up everyone elses window
|
||||
group.removeGroupMember(target);
|
||||
GroupManager.removeFromGroups(target);
|
||||
|
||||
gim = new GroupUpdateMsg();
|
||||
gim.setGroup(group);
|
||||
gim.setMessageType(3);
|
||||
gim.setPlayer(target);
|
||||
group.sendUpdate(gim);
|
||||
|
||||
String text = target.getFirstName() + " has left your group.";
|
||||
ChatManager.chatGroupInfo(source, text);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.BuildingGroup;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.gameManager.ZoneManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.RepairBuildingMsg;
|
||||
import engine.net.client.msg.UpdateObjectMsg;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.City;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.Zone;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* protecting and unprotecting city assets
|
||||
*/
|
||||
public class RepairBuildingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public RepairBuildingMsgHandler() {
|
||||
super(RepairBuildingMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
Building targetBuilding;
|
||||
RepairBuildingMsg msg;
|
||||
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
msg = (RepairBuildingMsg) baseMsg;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
switch (msg.getType()) {
|
||||
case 0:
|
||||
targetBuilding = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
RepairBuilding(targetBuilding, origin, msg);
|
||||
break;
|
||||
|
||||
// targetBuilding.createFurniture(item.getItemBase().getUseID(), 0, msg.getFurnitureLoc(), Vector3f.ZERO, 0, player);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// dispatch = Dispatch.borrow(player, baseMsg);
|
||||
// DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void RepairBuilding(Building targetBuilding, ClientConnection origin, RepairBuildingMsg msg) {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
Zone serverZone;
|
||||
Dispatch dispatch;
|
||||
|
||||
// Member variable assignment
|
||||
|
||||
if (targetBuilding == null)
|
||||
return;
|
||||
|
||||
if (!targetBuilding.hasFunds(BuildingManager.GetRepairCost(targetBuilding)))
|
||||
return;
|
||||
|
||||
PlayerCharacter pc = origin.getPlayerCharacter();
|
||||
|
||||
serverZone = ZoneManager.findSmallestZone(pc.getLoc());
|
||||
|
||||
if (serverZone.getPlayerCityUUID() == 0 && targetBuilding.getBlueprint() != null && targetBuilding.getBlueprint().getBuildingGroup() != BuildingGroup.MINE)
|
||||
return;
|
||||
|
||||
|
||||
City city = City.GetCityFromCache(serverZone.getPlayerCityUUID());
|
||||
|
||||
if (city != null){
|
||||
if(city.getBane() != null && city.protectionEnforced == false)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
//cannot repair mines during 24/7 activity.
|
||||
|
||||
if (targetBuilding.getBlueprint() != null && targetBuilding.getBlueprint().getBuildingGroup() == BuildingGroup.MINE){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int maxHP = (int) targetBuilding.getMaxHitPoints();
|
||||
int repairCost = BuildingManager.GetRepairCost(targetBuilding);
|
||||
int missingHealth = (int) BuildingManager.GetMissingHealth(targetBuilding);
|
||||
|
||||
if (!targetBuilding.transferGold(-repairCost,false))
|
||||
return;
|
||||
|
||||
targetBuilding.modifyHealth(BuildingManager.GetMissingHealth(targetBuilding), null);
|
||||
|
||||
UpdateObjectMsg uom = new UpdateObjectMsg(targetBuilding,3);
|
||||
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), uom);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
|
||||
|
||||
RepairBuildingMsg rbm = new RepairBuildingMsg( targetBuilding.getObjectUUID(), maxHP, missingHealth, repairCost, targetBuilding.getStrongboxValue());
|
||||
|
||||
|
||||
dispatch = Dispatch.borrow(origin.getPlayerCharacter(), rbm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.RequestBallListMessage;
|
||||
import engine.objects.PlayerCharacter;
|
||||
public class RequestBallListHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public RequestBallListHandler() {
|
||||
super(RequestBallListMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
RequestBallListMessage msg = (RequestBallListMessage)baseMsg;
|
||||
|
||||
HandleRequestBallList(player,msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void HandleRequestBallList(PlayerCharacter player, RequestBallListMessage msg){
|
||||
//currently not handled.
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.InterestManagement.InterestManager;
|
||||
import engine.InterestManagement.WorldGrid;
|
||||
import engine.db.archive.CharacterRecord;
|
||||
import engine.db.archive.DataWarehouse;
|
||||
import engine.db.archive.PvpRecord;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.math.Vector3fImmutable;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.AbstractWorldObject;
|
||||
import engine.objects.Account;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.server.MBServerStatics;
|
||||
import engine.session.Session;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which requests
|
||||
* that a character enters the game world from login screen
|
||||
*/
|
||||
|
||||
public class RequestEnterWorldHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public RequestEnterWorldHandler() {
|
||||
super(RequestEnterWorldMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
RequestEnterWorldMsg msg;
|
||||
|
||||
msg = (RequestEnterWorldMsg) baseMsg;
|
||||
|
||||
Session session = SessionManager.getSession(origin);
|
||||
|
||||
if (session == null)
|
||||
return true;
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
WorldGrid.RemoveWorldObject(player);
|
||||
Dispatch dispatch;
|
||||
|
||||
if (player == null) {
|
||||
Logger.error("Unable to find player for session" + session.getSessionID());
|
||||
origin.kickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Player not found.");
|
||||
return true;
|
||||
}
|
||||
|
||||
player.setEnteredWorld(false);
|
||||
|
||||
Account acc = SessionManager.getAccount(origin);
|
||||
|
||||
if (acc.status.ordinal() < MBServerStatics.worldAccessLevel.ordinal() || MBServerStatics.blockLogin) {
|
||||
origin.disconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Brand new character. Send the city select screen
|
||||
|
||||
if (player.getLevel() == 1 && player.getBindBuildingID() == -1) {
|
||||
SelectCityMsg scm = new SelectCityMsg(player, true);
|
||||
dispatch = Dispatch.borrow(player, scm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
}
|
||||
|
||||
player.resetRegenUpdateTime();
|
||||
|
||||
// Map Data
|
||||
|
||||
try {
|
||||
WorldDataMsg wdm = new WorldDataMsg();
|
||||
dispatch = Dispatch.borrow(player, wdm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
Logger.error("WORLDDATAMESSAGE" + e.getMessage());
|
||||
}
|
||||
|
||||
// Realm Data
|
||||
|
||||
try {
|
||||
WorldRealmMsg wrm = new WorldRealmMsg();
|
||||
dispatch = Dispatch.borrow(player, wrm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
Logger.error("REALMMESSAGE" + e.getMessage());
|
||||
}
|
||||
|
||||
// Object Data
|
||||
WorldObjectMsg wom = new WorldObjectMsg(session, true);
|
||||
dispatch = Dispatch.borrow(player, wom);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
|
||||
player.getTimestamps().put("EnterWorld", System.currentTimeMillis());
|
||||
|
||||
if (player.getLoc().equals(Vector3fImmutable.ZERO) || System.currentTimeMillis() > player.getTimeStamp("logout") + (15 * 60 * 1000)) {
|
||||
player.stopMovement(player.getBindLoc());
|
||||
player.setSafeMode();
|
||||
player.updateLocation();
|
||||
player.setRegion(AbstractWorldObject.GetRegionByWorldObject(player));
|
||||
}
|
||||
|
||||
player.setTimeStamp("logout", 0);
|
||||
player.respawnLock.writeLock().lock();
|
||||
try{
|
||||
if (!player.isAlive()){
|
||||
Logger.info("respawning player on enter world.");
|
||||
player.respawn(true, true,true);
|
||||
}
|
||||
|
||||
}catch (Exception e){
|
||||
Logger.error(e);
|
||||
}finally{
|
||||
player.respawnLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
|
||||
player.resetDataAtLogin();
|
||||
|
||||
InterestManager.INTERESTMANAGER.HandleLoadForEnterWorld(player);
|
||||
|
||||
// If this is a brand new character...
|
||||
// when they enter world is a great time to write their
|
||||
// character record to the data warehouse.
|
||||
|
||||
if (player.getHash() == null) {
|
||||
|
||||
if (DataWarehouse.recordExists(Enum.DataRecordType.CHARACTER, player.getObjectUUID()) == false) {
|
||||
CharacterRecord characterRecord = CharacterRecord.borrow(player);
|
||||
DataWarehouse.pushToWarehouse(characterRecord);
|
||||
}
|
||||
player.setHash();
|
||||
}
|
||||
|
||||
//
|
||||
// We will load the kill/death lists here as data is only pertinent
|
||||
// to characters actually logged into the game.
|
||||
//
|
||||
|
||||
player.pvpKills = PvpRecord.getCharacterPvPHistory(player.getObjectUUID(), Enum.PvpHistoryType.KILLS);
|
||||
player.pvpDeaths = PvpRecord.getCharacterPvPHistory(player.getObjectUUID(), Enum.PvpHistoryType.DEATHS);
|
||||
|
||||
SendOwnPlayerMsg sopm = new SendOwnPlayerMsg(SessionManager.getSession(origin));
|
||||
dispatch = Dispatch.borrow(player, sopm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.PRIMARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.ReqGuildListMsg;
|
||||
import engine.net.client.msg.guild.SendGuildEntryMsg;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
|
||||
public class RequestGuildListHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public RequestGuildListHandler() {
|
||||
super(ReqGuildListMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
Dispatch dispatch;
|
||||
|
||||
// get PlayerCharacter of person accepting invite
|
||||
PlayerCharacter pc = SessionManager.getPlayerCharacter(
|
||||
origin);
|
||||
if (pc == null)
|
||||
return true;
|
||||
|
||||
if (GuildStatusController.isGuildLeader(pc.getGuildStatus()) == false){
|
||||
ErrorPopupMsg.sendErrorMsg(pc, "You do not have such authority!");
|
||||
}
|
||||
SendGuildEntryMsg msg = new SendGuildEntryMsg(pc);
|
||||
|
||||
|
||||
dispatch = Dispatch.borrow(pc, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.SendBallEntryMessage;
|
||||
import engine.objects.PlayerCharacter;
|
||||
public class SendBallEntryHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public SendBallEntryHandler() {
|
||||
super(SendBallEntryMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
SendBallEntryMessage msg = (SendBallEntryMessage)baseMsg;
|
||||
|
||||
HandleAddBall(player,msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void HandleAddBall(PlayerCharacter player, SendBallEntryMessage msg){
|
||||
//currently not handled.
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.Enum.GuildState;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.GuildManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.SendGuildEntryMsg;
|
||||
import engine.net.client.msg.guild.SwearInGuildMsg;
|
||||
import engine.objects.City;
|
||||
import engine.objects.Guild;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SwearInGuildHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public SwearInGuildHandler() {
|
||||
super(SwearInGuildMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
PlayerCharacter player;
|
||||
SwearInGuildMsg swearInMsg;
|
||||
Guild targetGuild;
|
||||
Guild nation;
|
||||
Dispatch dispatch;
|
||||
|
||||
swearInMsg = (SwearInGuildMsg) baseMsg;
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
targetGuild = (Guild) DbManager.getObject(GameObjectType.Guild, swearInMsg.getGuildUUID());
|
||||
|
||||
if (targetGuild == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
nation = player.getGuild();
|
||||
|
||||
if (nation == null) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You do not belong to a guild!");
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!nation.isNation()) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Your guild is not a nation!");
|
||||
return true;
|
||||
}
|
||||
if (!nation.getSubGuildList().contains(targetGuild)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Your do not have such authority!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Guild.canSwearIn(targetGuild)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, targetGuild.getGuildState().name() + "cannot be sworn in");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GuildStatusController.isGuildLeader(player.getGuildStatus()) == false){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Your do not have such authority!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!DbManager.GuildQueries.UPDATE_PARENT(targetGuild.getObjectUUID(), nation.getObjectUUID())) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "A Serious error has occured. Please post details for to ensure transaction integrity");
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (targetGuild.getGuildState()) {
|
||||
case Petitioner:
|
||||
GuildManager.updateAllGuildBinds(targetGuild, nation.getOwnedCity());
|
||||
break;
|
||||
case Protectorate:
|
||||
break;
|
||||
default:
|
||||
//shouldn't get here.
|
||||
break;
|
||||
}
|
||||
|
||||
//update Guild state.
|
||||
targetGuild.setNation(nation);
|
||||
GuildManager.updateAllGuildTags(targetGuild);
|
||||
targetGuild.upgradeGuildState(false);
|
||||
|
||||
if (nation.getGuildState() == GuildState.Sovereign)
|
||||
nation.upgradeGuildState(true);
|
||||
|
||||
SendGuildEntryMsg msg = new SendGuildEntryMsg(player);
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
City.lastCityUpdate = System.currentTimeMillis();
|
||||
|
||||
ArrayList<PlayerCharacter> guildMembers = SessionManager.getActivePCsInGuildID(nation.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : guildMembers) {
|
||||
ChatManager.chatGuildInfo(member, "Your Guild is now a Nation!");
|
||||
}
|
||||
|
||||
ArrayList<PlayerCharacter> swornMembers = SessionManager.getActivePCsInGuildID(targetGuild.getObjectUUID());
|
||||
|
||||
for (PlayerCharacter member : swornMembers) {
|
||||
ChatManager.chatGuildInfo(member, "Your Guild has sword fealty to " + nation.getName() + '.');
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Logger.error( e.getMessage());
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.guild.GuildInfoMsg;
|
||||
import engine.net.client.msg.guild.GuildListMsg;
|
||||
import engine.net.client.msg.guild.SwearInMsg;
|
||||
import engine.objects.GuildStatusController;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class SwearInHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public SwearInHandler() {
|
||||
super(SwearInMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
SwearInMsg msg = (SwearInMsg) baseMsg;
|
||||
Dispatch dispatch;
|
||||
|
||||
// get source player
|
||||
PlayerCharacter source = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (source == null)
|
||||
return true;
|
||||
|
||||
// get target player
|
||||
PlayerCharacter target = SessionManager.getPlayerCharacterByID(msg.getTargetID());
|
||||
|
||||
if (target == null) {
|
||||
ChatManager.chatGuildError(source,
|
||||
"No such character found!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if(source.getGuild() != target.getGuild()) {
|
||||
ChatManager.chatGuildError(source,
|
||||
"That player is not a member of " + source.getGuild().getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Verify source has authority to swear in
|
||||
if (GuildStatusController.isInnerCouncil(source.getGuildStatus()) == false) {
|
||||
ErrorPopupMsg.sendErrorMsg(source, "Your do not have such authority!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Swear target in and send message to guild
|
||||
target.setFullMember(true);
|
||||
target.incVer();
|
||||
|
||||
ChatManager.chatGuildInfo(source,target.getFirstName() + " has been sworn in as a full member!");
|
||||
|
||||
dispatch = Dispatch.borrow(source, new GuildListMsg(source.getGuild()));
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
DispatchMessage.sendToAllInRange(target, new GuildInfoMsg(target, target.getGuild(), 2));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.InterestManagement.RealmMap;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.TaxCityMsg;
|
||||
import engine.net.client.msg.ViewResourcesMessage;
|
||||
import engine.objects.*;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* protecting and unprotecting city assets
|
||||
*/
|
||||
public class TaxCityMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public TaxCityMsgHandler() {
|
||||
super(TaxCityMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
TaxCityMsg msg;
|
||||
|
||||
player = origin.getPlayerCharacter();
|
||||
|
||||
|
||||
msg = (TaxCityMsg) baseMsg;
|
||||
|
||||
ViewTaxes(msg,player);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static boolean ViewTaxes(TaxCityMsg msg, PlayerCharacter player) {
|
||||
|
||||
// Member variable declaration
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.getGuildID());
|
||||
Guild playerGuild = player.getGuild();
|
||||
|
||||
if (building == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Not a valid Building!");
|
||||
return true;
|
||||
}
|
||||
|
||||
City city = building.getCity();
|
||||
if (city == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "This building does not belong to a city.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (city.getWarehouse() == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "This city does not have a warehouse!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (playerGuild == null || playerGuild.isErrant()){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You must belong to a guild to do that!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (playerGuild.getOwnedCity() == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Your Guild needs to own a city!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (playerGuild.getOwnedCity().getWarehouse() == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Your Guild needs to own a warehouse!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (playerGuild.getOwnedCity().getTOL() == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot find Tree of Life for your city!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// if (playerGuild.getOwnedCity().getTOL().getRank() != 8){
|
||||
// ErrorPopupMsg.sendErrorMsg(player, "Your City needs to Own a realm!");
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if (playerGuild.getOwnedCity().getRealm() == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot find realm for your city!");
|
||||
return true;
|
||||
}
|
||||
Realm targetRealm = RealmMap.getRealmForCity(city);
|
||||
|
||||
if (targetRealm == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot find realm for city you are attempting to tax!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// if (targetRealm.getRulingCity() == null){
|
||||
// ErrorPopupMsg.sendErrorMsg(player, "Realm Does not have a ruling city!");
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if (targetRealm.getRulingCity().getObjectUUID() != playerGuild.getOwnedCity().getObjectUUID()){
|
||||
// ErrorPopupMsg.sendErrorMsg(player, "Your guild does not rule this realm!");
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if (playerGuild.getOwnedCity().getObjectUUID() == city.getObjectUUID()){
|
||||
// ErrorPopupMsg.sendErrorMsg(player, "You cannot tax your own city!");
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
if (!GuildStatusController.isTaxCollector(player.getGuildStatus())){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You Must be a tax Collector!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// if (!city.isAfterTaxPeriod(DateTime.now(), player))
|
||||
// return true;
|
||||
|
||||
|
||||
|
||||
ViewResourcesMessage vrm = new ViewResourcesMessage(player);
|
||||
vrm.setGuild(building.getGuild());
|
||||
vrm.setWarehouseBuilding(BuildingManager.getBuildingFromCache(building.getCity().getWarehouse().getBuildingUID()));
|
||||
vrm.configure();
|
||||
Dispatch dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
dispatch = Dispatch.borrow(player, vrm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
return true;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.TaxResourcesMsg;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.City;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which handles
|
||||
* protecting and unprotecting city assets
|
||||
*/
|
||||
public class TaxResourcesMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public TaxResourcesMsgHandler() {
|
||||
super(TaxResourcesMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter player;
|
||||
TaxResourcesMsg msg;
|
||||
|
||||
player = origin.getPlayerCharacter();
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
msg = (TaxResourcesMsg) baseMsg;
|
||||
|
||||
TaxWarehouse(msg,player);
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static boolean TaxWarehouse(TaxResourcesMsg msg, PlayerCharacter player) {
|
||||
|
||||
// Member variable declaration
|
||||
Building building = BuildingManager.getBuildingFromCache(msg.getBuildingID());
|
||||
|
||||
|
||||
if (building == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Not a valid Building!");
|
||||
return true;
|
||||
}
|
||||
|
||||
City city = building.getCity();
|
||||
if (city == null){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "This building does not belong to a city.");
|
||||
return true;
|
||||
}
|
||||
|
||||
city.TaxWarehouse(msg, player);
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.gameManager.GroupManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.group.GroupUpdateMsg;
|
||||
import engine.net.client.msg.group.ToggleGroupSplitMsg;
|
||||
import engine.objects.Group;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
public class ToggleGroupSplitHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public ToggleGroupSplitHandler() {
|
||||
super(ToggleGroupSplitMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
PlayerCharacter source;
|
||||
Group group;
|
||||
boolean split;
|
||||
|
||||
source = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (source == null)
|
||||
return false;
|
||||
|
||||
group = GroupManager.getGroup(source);
|
||||
|
||||
if (group == null)
|
||||
return false;
|
||||
|
||||
if (group.getGroupLead() != source) // Only group lead can toggle
|
||||
return false;
|
||||
|
||||
split = group.toggleSplitGold();
|
||||
|
||||
// update split button
|
||||
GroupUpdateMsg gum = new GroupUpdateMsg();
|
||||
gum.setGroup(group);
|
||||
gum.setMessageType(6);
|
||||
|
||||
group.sendUpdate(gum);
|
||||
|
||||
// Send split message
|
||||
|
||||
if (split)
|
||||
ChatManager.chatGroupInfo(source, "Treasure is now being split.");
|
||||
else
|
||||
ChatManager.chatGroupInfo(source, "Treasure is no longer being split.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.ChatManager;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.ErrorPopupMsg;
|
||||
import engine.net.client.msg.TransferAssetMsg;
|
||||
import engine.objects.Blueprint;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.PlayerCharacter;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which transers
|
||||
* assets between characters.
|
||||
*/
|
||||
|
||||
public class TransferAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public TransferAssetMsgHandler() {
|
||||
super(TransferAssetMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
TransferAssetMsg transferAssetMsg = (TransferAssetMsg) baseMsg;
|
||||
|
||||
int Buildingid = transferAssetMsg.getObjectID();
|
||||
int BuildingType = transferAssetMsg.getObjectType(); //ToDue Later
|
||||
int TargetID = transferAssetMsg.getTargetID();
|
||||
int TargetType = transferAssetMsg.getTargetType(); //ToDue later
|
||||
|
||||
Building building = BuildingManager.getBuildingFromCache(Buildingid);
|
||||
PlayerCharacter newOwner = PlayerCharacter.getFromCache(TargetID);
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null || building == null || newOwner == null)
|
||||
return true;
|
||||
|
||||
Blueprint blueprint = building.getBlueprint();
|
||||
|
||||
if (blueprint == null)
|
||||
return true;
|
||||
|
||||
if (building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.MINE) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "You cannot transfer a mine!");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Players cannot transfer shrines
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SHRINE)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to transfer shrine!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Blueprint.isMeshWallPiece(building.getBlueprintUUID())) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to transfer fortress asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.BARRACK)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to transfer fortress asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.BULWARK)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to transfer siege asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SIEGETENT)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to transfer siege asset!");
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((building.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.BANESTONE)) {
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Cannot for to transfer banestone!");
|
||||
return true;
|
||||
}
|
||||
if (building.getOwnerUUID() != player.getObjectUUID()) {
|
||||
ChatManager.chatSystemError(player, "You do not own this asset.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (building.getOwnerUUID() == newOwner.getObjectUUID()) {
|
||||
ChatManager.chatSystemError(player, "You already own this asset.");
|
||||
return true;
|
||||
}
|
||||
|
||||
building.setOwner(newOwner);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.PlaceAssetMsg;
|
||||
import engine.net.client.msg.TransferGoldToFromBuildingMsg;
|
||||
import engine.net.client.msg.UpdateGoldMsg;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.CharacterItemManager;
|
||||
import engine.objects.Item;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
/*
|
||||
* @Author:
|
||||
* @Summary: Processes application protocol message which transfers
|
||||
* gold between a building's strongbox and a player character.
|
||||
*/
|
||||
|
||||
public class TransferGoldToFromBuildingMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public TransferGoldToFromBuildingMsgHandler() {
|
||||
super(TransferGoldToFromBuildingMsg.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player;
|
||||
Building building;
|
||||
CharacterItemManager itemMan;
|
||||
Item goldItem;
|
||||
TransferGoldToFromBuildingMsg msg;
|
||||
Dispatch dispatch;
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
msg = (TransferGoldToFromBuildingMsg) baseMsg;
|
||||
|
||||
building = BuildingManager.getBuildingFromCache(msg.getObjectID());
|
||||
|
||||
if (building == null)
|
||||
return true;
|
||||
|
||||
if (msg.getDirection() == 2){
|
||||
|
||||
if(!ManageCityAssetMsgHandler.playerCanManageNotFriends(player, building))
|
||||
return true;
|
||||
if (building.setReserve(msg.getUnknown01(),player)){
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// if (building.getTimeStamp(MBServerStatics.STRONGBOX_DELAY_STRING) > System.currentTimeMillis()){
|
||||
// ErrorPopupMsg.sendErrorMsg(player, MBServerStatics.STRONGBOX_DELAY_OUTPUT);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
//building.getTimestamps().put(MBServerStatics.STRONGBOX_DELAY_STRING, System.currentTimeMillis() + MBServerStatics.ONE_MINUTE);
|
||||
|
||||
itemMan = player.getCharItemManager();
|
||||
|
||||
goldItem = itemMan.getGoldInventory();
|
||||
|
||||
if (goldItem == null) {
|
||||
Logger.error("Could not access gold item");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Update in-game gold values for player and building
|
||||
|
||||
|
||||
try {
|
||||
|
||||
|
||||
if (!itemMan.transferGoldToFromBuilding(msg.getAmount(), building))
|
||||
return true;
|
||||
|
||||
|
||||
UpdateGoldMsg ugm = new UpdateGoldMsg(player);
|
||||
ugm.configure();
|
||||
dispatch = Dispatch.borrow(player, ugm);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
// Refresh the player's inventory if it's currently open
|
||||
|
||||
// Refresh the tree's window to update strongbox
|
||||
|
||||
|
||||
msg.setAmount(building.getStrongboxValue());
|
||||
dispatch = Dispatch.borrow(player, msg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
} catch (Exception e) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum.DispatchChannel;
|
||||
import engine.Enum.FriendStatus;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.ClientNetMsg;
|
||||
import engine.net.client.msg.UpdateFriendStatusMessage;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import engine.objects.PlayerFriends;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public class UpdateFriendStatusHandler extends AbstractClientMsgHandler {
|
||||
|
||||
public UpdateFriendStatusHandler() {
|
||||
super(UpdateFriendStatusMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg,
|
||||
ClientConnection origin) throws MsgSendException {
|
||||
|
||||
PlayerCharacter player = origin.getPlayerCharacter();
|
||||
|
||||
if (player == null)
|
||||
return true;
|
||||
|
||||
|
||||
UpdateFriendStatusMessage msg = (UpdateFriendStatusMessage)baseMsg;
|
||||
|
||||
|
||||
HandleUpdateFriend(player,msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//change to Request
|
||||
public static void HandleUpdateFriend(PlayerCharacter player, UpdateFriendStatusMessage msg){
|
||||
FriendStatus friendStatus = FriendStatus.Available;
|
||||
|
||||
try {
|
||||
friendStatus = FriendStatus.values()[msg.statusType];
|
||||
}catch (Exception e){
|
||||
Logger.error(e);
|
||||
}
|
||||
player.friendStatus = friendStatus;
|
||||
SendUpdateToFriends(player);
|
||||
}
|
||||
|
||||
public static void SendUpdateToFriends(PlayerCharacter player){
|
||||
|
||||
HashSet<Integer> friends = PlayerFriends.PlayerFriendsMap.get(player.getObjectUUID());
|
||||
|
||||
if (friends == null)
|
||||
return;
|
||||
|
||||
UpdateFriendStatusMessage outMsg = new UpdateFriendStatusMessage(player);
|
||||
|
||||
for (int friendID : friends){
|
||||
PlayerCharacter playerFriend = SessionManager.getPlayerCharacterByID(friendID);
|
||||
if (playerFriend == null)
|
||||
return;
|
||||
Dispatch dispatch = Dispatch.borrow(playerFriend, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, DispatchChannel.SECONDARY);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package engine.net.client.handlers;
|
||||
|
||||
import engine.Enum;
|
||||
import engine.Enum.GameObjectType;
|
||||
import engine.exception.MsgSendException;
|
||||
import engine.gameManager.BuildingManager;
|
||||
import engine.gameManager.DbManager;
|
||||
import engine.gameManager.SessionManager;
|
||||
import engine.net.Dispatch;
|
||||
import engine.net.DispatchMessage;
|
||||
import engine.net.client.ClientConnection;
|
||||
import engine.net.client.msg.*;
|
||||
import engine.objects.Building;
|
||||
import engine.objects.PlayerCharacter;
|
||||
import org.pmw.tinylog.Logger;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static engine.net.client.msg.ErrorPopupMsg.sendErrorPopup;
|
||||
|
||||
/*
|
||||
*
|
||||
* @Summary: Processes application protocol message where a
|
||||
* client requests that a building be upgraded.
|
||||
*/
|
||||
public class UpgradeAssetMsgHandler extends AbstractClientMsgHandler {
|
||||
|
||||
// Constructor
|
||||
public UpgradeAssetMsgHandler() {
|
||||
|
||||
super(UpgradeAssetMessage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException {
|
||||
|
||||
// Member variable declaration
|
||||
|
||||
UpgradeAssetMessage msg;
|
||||
ManageCityAssetsMsg outMsg;
|
||||
PlayerCharacter player;
|
||||
int buildingUUID;
|
||||
Building buildingToRank;
|
||||
LocalDateTime dateToUpgrade;
|
||||
int nextRank;
|
||||
int rankCost;
|
||||
Dispatch dispatch;
|
||||
|
||||
// Assign member variables
|
||||
|
||||
msg = (UpgradeAssetMessage) baseMsg;
|
||||
|
||||
// Grab pointer to the requesting player
|
||||
|
||||
player = SessionManager.getPlayerCharacter(origin);
|
||||
|
||||
// Grab pointer to the building from the cache
|
||||
|
||||
buildingUUID = msg.getBuildingUUID();
|
||||
|
||||
buildingToRank = (Building) DbManager.getObject(GameObjectType.Building, buildingUUID);
|
||||
|
||||
// Early exit if building not in cache.
|
||||
|
||||
if (buildingToRank == null) {
|
||||
Logger.error("Attempt to upgrade null building by " + player.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Early exit for building that is already ranking
|
||||
|
||||
if (buildingToRank.isRanking()) {
|
||||
Logger.error("Attempt to upgrade a building already ranking by " + player.getName());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Calculate and set time/cost to upgrade
|
||||
|
||||
nextRank = (buildingToRank.getRank() + 1);
|
||||
|
||||
if (buildingToRank.getBlueprint() == null)
|
||||
return true;
|
||||
if (buildingToRank.getBlueprint().getMaxRank() < nextRank || nextRank == 8){
|
||||
ErrorPopupMsg.sendErrorMsg(player, "Building is already at it's Max rank.");
|
||||
return true;
|
||||
}
|
||||
|
||||
rankCost = buildingToRank.getBlueprint().getRankCost(nextRank);
|
||||
|
||||
// SEND NOT ENOUGH GOLD ERROR
|
||||
|
||||
if (!buildingToRank.hasFunds(rankCost)){
|
||||
ErrorPopupMsg.sendErrorPopup(player, 127); // Not enough gold in strongbox
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rankCost > buildingToRank.getStrongboxValue()) {
|
||||
sendErrorPopup(player, 127);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Validation appears good. Let's now process the upgrade
|
||||
|
||||
try {
|
||||
if (buildingToRank.getCity() != null){
|
||||
buildingToRank.getCity().transactionLock.writeLock().lock();
|
||||
try{
|
||||
if (!buildingToRank.transferGold(-rankCost,false)) {
|
||||
sendErrorPopup(player, 127);
|
||||
return true;
|
||||
}
|
||||
}catch(Exception e){
|
||||
Logger.error(e);
|
||||
}finally{
|
||||
buildingToRank.getCity().transactionLock.writeLock().unlock();
|
||||
}
|
||||
}else
|
||||
if (!buildingToRank.transferGold(-rankCost,false)) {
|
||||
sendErrorPopup(player, 127);
|
||||
return true;
|
||||
}
|
||||
|
||||
dateToUpgrade = LocalDateTime.now().plusHours(buildingToRank.getBlueprint().getRankTime(nextRank));
|
||||
|
||||
BuildingManager.setUpgradeDateTime(buildingToRank, dateToUpgrade, 0);
|
||||
|
||||
// Schedule upgrade job
|
||||
|
||||
BuildingManager.submitUpgradeJob(buildingToRank);
|
||||
|
||||
// Refresh the client's manage asset window
|
||||
// *** Refactor : We have some of these unknowns
|
||||
|
||||
outMsg = new ManageCityAssetsMsg(player, buildingToRank);
|
||||
|
||||
// Action TYPE
|
||||
outMsg.actionType = 3;
|
||||
outMsg.setTargetType(buildingToRank.getObjectType().ordinal());
|
||||
outMsg.setTargetID(buildingToRank.getObjectUUID());
|
||||
outMsg.setTargetType3(buildingToRank.getObjectType().ordinal());
|
||||
outMsg.setTargetID3(buildingToRank.getObjectUUID());
|
||||
outMsg.setAssetName1(buildingToRank.getName());
|
||||
outMsg.setUnknown54(1);
|
||||
|
||||
dispatch = Dispatch.borrow(player, outMsg);
|
||||
DispatchMessage.dispatchMsgDispatch(dispatch, Enum.DispatchChannel.SECONDARY);
|
||||
|
||||
} catch (Exception e) {
|
||||
PlaceAssetMsg.sendPlaceAssetError(player.getClientConnection(), 1, "A Serious error has occurred. Please post details for to ensure transaction integrity");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
|
||||
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
|
||||
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
|
||||
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
|
||||
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
|
||||
// Magicbane Emulator Project © 2013 - 2022
|
||||
// www.magicbane.com
|
||||
|
||||
|
||||
package engine.net.client.msg;
|
||||
|
||||
import engine.exception.SerializationException;
|
||||
import engine.net.AbstractConnection;
|
||||
import engine.net.ByteBufferReader;
|
||||
import engine.net.ByteBufferWriter;
|
||||
import engine.net.client.Protocol;
|
||||
|
||||
|
||||
public class AbandonAssetMsg extends ClientNetMsg {
|
||||
|
||||
private int pad = 0;
|
||||
private int objectType;
|
||||
private int objectUUID;
|
||||
|
||||
/**
|
||||
* This constructor is used by NetMsgFactory. It attempts to deserialize the
|
||||
* ByteBuffer into a message. If a BufferUnderflow occurs (based on reading
|
||||
* past the limit) then this constructor Throws that Exception to the
|
||||
* caller.
|
||||
*/
|
||||
public AbandonAssetMsg(AbstractConnection origin, ByteBufferReader reader){
|
||||
super(Protocol.ABANDONASSET, origin, reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes the subclass specific items from the supplied NetMsgReader.
|
||||
*/
|
||||
@Override
|
||||
protected void _deserialize(ByteBufferReader reader) {
|
||||
this.pad = reader.getInt();
|
||||
this.objectType = reader.getInt();
|
||||
this.objectUUID = reader.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the subclass specific items to the supplied NetMsgWriter.
|
||||
*/
|
||||
@Override
|
||||
protected void _serialize(ByteBufferWriter writer) throws SerializationException {
|
||||
writer.putInt(this.pad);
|
||||
writer.putInt(this.objectType);
|
||||
writer.putInt(this.objectUUID);
|
||||
}
|
||||
|
||||
public int getObjectType() {
|
||||
return objectType;
|
||||
}
|
||||
|
||||
public void setObjectType(int value) {
|
||||
this.objectType = value;
|
||||
}
|
||||
|
||||
public void setPad(int value) {
|
||||
this.pad = value;
|
||||
}
|
||||
|
||||
public int getUUID() {
|
||||
return objectUUID;
|
||||
|
||||
}
|
||||
|
||||
public int getPad() {
|
||||
return pad;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user