uhhh go brrr?
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package core.net;
|
||||
|
||||
/**
|
||||
* Network constants.
|
||||
* @author Vexia
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
/**
|
||||
* Represents the post the server is hosted on.
|
||||
*/
|
||||
public static final int PORT = 43594;
|
||||
|
||||
/**
|
||||
* The revision of the game server.
|
||||
*/
|
||||
public static final int REVISION = 530;
|
||||
|
||||
/**
|
||||
* The client build of the client, used for notifying players of a client
|
||||
* update.
|
||||
*/
|
||||
public static final int CLIENT_BUILD = 1;
|
||||
|
||||
/**
|
||||
* The default Management server IP.
|
||||
*/
|
||||
public static final String DEFAULT_MS_IP = "127.0.0.1";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package core.net;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Used for producing I/O events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public interface EventProducer {
|
||||
|
||||
/**
|
||||
* Produces a new read event.
|
||||
* @param session The session.
|
||||
* @param buffer The buffer to read.
|
||||
* @return The read event handler.
|
||||
*/
|
||||
IoReadEvent produceReader(IoSession session, ByteBuffer buffer);
|
||||
|
||||
/**
|
||||
* Produces a new writing event.
|
||||
* @param session The session.
|
||||
* @param context The context.
|
||||
* @return The write event handler.
|
||||
*/
|
||||
IoWriteEvent produceWriter(IoSession session, Object context);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package core.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
/**
|
||||
* I/O event handling.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class IoEventHandler {
|
||||
|
||||
/**
|
||||
* The executor service.
|
||||
*/
|
||||
protected final ExecutorService service;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoEventHandler}.
|
||||
* @param service The executor service used for handling events.
|
||||
*/
|
||||
public IoEventHandler(ExecutorService service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when making a new connection.
|
||||
* @param key The selection key.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
*/
|
||||
public void connect(SelectionKey key) throws IOException {
|
||||
/*
|
||||
* empty.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for accepting a new connection.
|
||||
* @param key The selection key.
|
||||
* @param selector The selector.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
*/
|
||||
public void accept(SelectionKey key, Selector selector) throws IOException {
|
||||
SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
|
||||
sc.configureBlocking(false);
|
||||
sc.socket().setTcpNoDelay(true);
|
||||
sc.register(selector, SelectionKey.OP_READ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the incoming packet data.
|
||||
* @param key The selection key.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
*/
|
||||
public void read(SelectionKey key) throws IOException {
|
||||
ReadableByteChannel channel = (ReadableByteChannel) key.channel();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(100_000);
|
||||
IoSession session = (IoSession) key.attachment();
|
||||
if (channel.read(buffer) == -1) {
|
||||
//just when a client closes their client, nothing to worry about.
|
||||
throw new IOException("An existing connection was disconnected!");
|
||||
}
|
||||
buffer.flip();
|
||||
if (session == null) {
|
||||
key.attach(session = new IoSession(key, service));
|
||||
}
|
||||
service.execute(session.getProducer().produceReader(session, buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the outgoing packet data.
|
||||
* @param key The selection key.
|
||||
*/
|
||||
public void write(SelectionKey key) {
|
||||
IoSession session = (IoSession) key.attachment();
|
||||
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
|
||||
session.write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects a connection.
|
||||
* @param key The selection key.
|
||||
* @param t The occurred exception (if any).
|
||||
*/
|
||||
public void disconnect(SelectionKey key, Throwable t) {
|
||||
try {
|
||||
IoSession session = (IoSession) key.attachment();
|
||||
String cause = "" + t;
|
||||
if (t != null && !(t instanceof ClosedChannelException || cause.contains("De externe host") || cause.contains("De software op uw") || cause.contains("An established connection was aborted") || cause.contains("An existing connection") || cause.contains("AsynchronousClose"))) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
if (session != null) {
|
||||
session.disconnect();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package core.net;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles a reading event.
|
||||
* @author Emperor
|
||||
*/
|
||||
public abstract class IoReadEvent implements Runnable {
|
||||
|
||||
/**
|
||||
* The I/O session.
|
||||
*/
|
||||
private final IoSession session;
|
||||
|
||||
/**
|
||||
* The buffer.
|
||||
*/
|
||||
private ByteBuffer buffer;
|
||||
|
||||
/**
|
||||
* If the queued reading buffer was used (debugging purposes).
|
||||
*/
|
||||
protected boolean usedQueuedBuffer;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoReadEvent}.
|
||||
* @param session The session.
|
||||
* @param buffer The buffer to read from.
|
||||
*/
|
||||
public IoReadEvent(IoSession session, ByteBuffer buffer) {
|
||||
this.session = session;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (session.getReadingQueue() != null) {
|
||||
buffer = session.getReadingQueue().put(buffer);
|
||||
buffer.flip();
|
||||
session.setReadingQueue(null);
|
||||
usedQueuedBuffer = true;
|
||||
}
|
||||
read(session, buffer);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
session.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues the buffer until more data has been received.
|
||||
* @param data The data that has been read already.
|
||||
*/
|
||||
public void queueBuffer(int... data) {
|
||||
ByteBuffer queue = ByteBuffer.allocate(data.length + buffer.remaining() + 100_000);
|
||||
for (int value : data) {
|
||||
queue.put((byte) value);
|
||||
}
|
||||
queue.put(buffer);
|
||||
session.setReadingQueue(queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the data from the buffer.
|
||||
* @param session The session.
|
||||
* @param buffer The buffer to read from.
|
||||
*/
|
||||
public abstract void read(IoSession session, ByteBuffer buffer);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
package core.net;
|
||||
|
||||
import core.cache.crypto.ISAACPair;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.ClientInfo;
|
||||
import core.game.node.entity.player.info.login.Response;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.producer.HSEventProducer;
|
||||
import core.net.producer.LoginEventProducer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Represents a connected I/O session.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class IoSession {
|
||||
|
||||
/**
|
||||
* The handshake event producer.
|
||||
*/
|
||||
private static final EventProducer HANDSHAKE_PRODUCER = new HSEventProducer();
|
||||
|
||||
/**
|
||||
* The selection key.
|
||||
*/
|
||||
private final SelectionKey key;
|
||||
|
||||
public int isaacInputOpcode = 0;
|
||||
|
||||
/**
|
||||
* The executor service.
|
||||
*/
|
||||
private final ExecutorService service;
|
||||
|
||||
/**
|
||||
* The event producer.
|
||||
*/
|
||||
private EventProducer producer = HANDSHAKE_PRODUCER;
|
||||
|
||||
/**
|
||||
* The currently queued writing data.
|
||||
*/
|
||||
private List<ByteBuffer> writingQueue = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The currently queued reading data.
|
||||
*/
|
||||
private ByteBuffer readingQueue;
|
||||
|
||||
/**
|
||||
* The writing lock.
|
||||
*/
|
||||
private Lock writingLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* The ISAAC cipher pair.
|
||||
*/
|
||||
private ISAACPair isaacPair;
|
||||
|
||||
/**
|
||||
* The name hash.
|
||||
*/
|
||||
private int nameHash;
|
||||
|
||||
/**
|
||||
* The server key.
|
||||
*/
|
||||
private long serverKey;
|
||||
|
||||
/**
|
||||
* The JS-5 encryption value.
|
||||
*/
|
||||
private int js5Encryption;
|
||||
|
||||
/**
|
||||
* The object.
|
||||
*/
|
||||
private Object object;
|
||||
|
||||
/**
|
||||
* If the session is active.
|
||||
*/
|
||||
private boolean active = true;
|
||||
|
||||
/**
|
||||
* The last ping time stamp.
|
||||
*/
|
||||
private long lastPing;
|
||||
|
||||
/**
|
||||
* The address.
|
||||
*/
|
||||
private final String address;
|
||||
|
||||
/**
|
||||
* The JS-5 queue.
|
||||
*/
|
||||
private final JS5Queue js5Queue;
|
||||
|
||||
/**
|
||||
* The client info.
|
||||
*/
|
||||
private ClientInfo clientInfo;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoSession}.
|
||||
* @param key The selection key.
|
||||
* @param service The executor service.
|
||||
*/
|
||||
public IoSession(SelectionKey key, ExecutorService service) {
|
||||
this.key = key;
|
||||
this.service = service;
|
||||
this.address = getRemoteAddress().replaceAll("/", "").split(":")[0];
|
||||
this.js5Queue = new JS5Queue(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a write event created using the current event producer.
|
||||
* @param context The event context.
|
||||
*/
|
||||
public void write(Object context) {
|
||||
write(context, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires a write event created using the current event producer.
|
||||
* @param context The event context.
|
||||
* @param instant If the event should be instantly executed on this thread.
|
||||
*/
|
||||
public void write(Object context, boolean instant) {
|
||||
if (context == null) {
|
||||
throw new IllegalStateException("Invalid writing context!");
|
||||
}
|
||||
if (!(context instanceof Response) && producer instanceof LoginEventProducer) {
|
||||
// new Throwable().printStackTrace();
|
||||
return;
|
||||
}
|
||||
if (instant) {
|
||||
producer.produceWriter(this, context).run();
|
||||
return;
|
||||
}
|
||||
service.execute(producer.produceWriter(this, context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the packet data (without write event encoding).
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public void queue(ByteBuffer buffer) {
|
||||
try {
|
||||
writingLock.tryLock(1000L, TimeUnit.MILLISECONDS);
|
||||
} catch (Exception e){
|
||||
System.out.println(e);
|
||||
writingLock.unlock();
|
||||
}
|
||||
writingQueue.add(buffer);
|
||||
writingLock.unlock();
|
||||
write();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the writing of all buffers in the queue.
|
||||
*/
|
||||
public void write() {
|
||||
if (!key.isValid()) {
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
writingLock.tryLock(1000L, TimeUnit.MILLISECONDS);
|
||||
} catch (Exception e){
|
||||
System.out.println(e);
|
||||
writingLock.unlock();
|
||||
return;
|
||||
}
|
||||
SocketChannel channel = (SocketChannel) key.channel();
|
||||
try {
|
||||
while (!writingQueue.isEmpty()) {
|
||||
ByteBuffer buffer = writingQueue.get(0);
|
||||
channel.write(buffer);
|
||||
if (buffer.hasRemaining()) {
|
||||
key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
|
||||
break;
|
||||
}
|
||||
writingQueue.remove(0);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
disconnect();
|
||||
}
|
||||
writingLock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects the session.
|
||||
*/
|
||||
public void disconnect() {
|
||||
try {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
active = false;
|
||||
key.cancel();
|
||||
SocketChannel channel = (SocketChannel) key.channel();
|
||||
channel.socket().close();
|
||||
if (object instanceof Player) {
|
||||
final Player p = getPlayer();
|
||||
GameWorld.getPulser().submit(new Pulse(0) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (p.isActive() && !p.getSession().active) {
|
||||
p.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
object = null;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP-address (without the port).
|
||||
* @return The address.
|
||||
*/
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the remote address of this session.
|
||||
* @return The remote address, as a String.
|
||||
*/
|
||||
public String getRemoteAddress() {
|
||||
try {
|
||||
return ((SocketChannel) key.channel()).getRemoteAddress().toString();
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current event producer.
|
||||
* @return The producer.
|
||||
*/
|
||||
public EventProducer getProducer() {
|
||||
return producer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the event producer.
|
||||
* @param producer The producer to set.
|
||||
*/
|
||||
public void setProducer(EventProducer producer) {
|
||||
this.producer = producer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the queued reading data.
|
||||
* @return The readingQueue.
|
||||
*/
|
||||
public ByteBuffer getReadingQueue() {
|
||||
synchronized (this) {
|
||||
return readingQueue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues reading data.
|
||||
* @param readingQueue The readingQueue to set.
|
||||
*/
|
||||
public void setReadingQueue(ByteBuffer readingQueue) {
|
||||
synchronized (this) {
|
||||
this.readingQueue = readingQueue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the writing lock.
|
||||
* @return The writing lock.
|
||||
*/
|
||||
public Lock getWritingLock() {
|
||||
return writingLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selection key.
|
||||
* @return The selection key.
|
||||
*/
|
||||
public SelectionKey getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The active.
|
||||
*/
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The js5Encryption.
|
||||
*/
|
||||
public int getJs5Encryption() {
|
||||
return js5Encryption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param js5Encryption The js5Encryption to set.
|
||||
*/
|
||||
public void setJs5Encryption(int js5Encryption) {
|
||||
this.js5Encryption = js5Encryption;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The player.
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return (Player) object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object.
|
||||
* @return the object.
|
||||
*/
|
||||
public Object getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object The object to set.
|
||||
*/
|
||||
public void setObject(Object object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the lastPing.
|
||||
* @return The lastPing.
|
||||
*/
|
||||
public long getLastPing() {
|
||||
return lastPing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lastPing.
|
||||
* @param lastPing The lastPing to set.
|
||||
*/
|
||||
public void setLastPing(long lastPing) {
|
||||
this.lastPing = lastPing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nameHash.
|
||||
* @return The nameHash.
|
||||
*/
|
||||
public int getNameHash() {
|
||||
return nameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nameHash.
|
||||
* @param nameHash The nameHash to set.
|
||||
*/
|
||||
public void setNameHash(int nameHash) {
|
||||
this.nameHash = nameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the serverKey.
|
||||
* @return The serverKey.
|
||||
*/
|
||||
public long getServerKey() {
|
||||
return serverKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the serverKey.
|
||||
* @param serverKey The serverKey to set.
|
||||
*/
|
||||
public void setServerKey(long serverKey) {
|
||||
this.serverKey = serverKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the isaacPair.
|
||||
* @return The isaacPair.
|
||||
*/
|
||||
public ISAACPair getIsaacPair() {
|
||||
return isaacPair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the isaacPair.
|
||||
* @param isaacPair The isaacPair to set.
|
||||
*/
|
||||
public void setIsaacPair(ISAACPair isaacPair) {
|
||||
this.isaacPair = isaacPair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the js5Queue.
|
||||
* @return the js5Queue
|
||||
*/
|
||||
public JS5Queue getJs5Queue() {
|
||||
return js5Queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clientInfo value.
|
||||
* @return The clientInfo.
|
||||
*/
|
||||
public ClientInfo getClientInfo() {
|
||||
return clientInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clientInfo value.
|
||||
* @param clientInfo The clientInfo to set.
|
||||
*/
|
||||
public void setClientInfo(ClientInfo clientInfo) {
|
||||
this.clientInfo = clientInfo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package core.net;
|
||||
|
||||
import java.nio.channels.CancelledKeyException;
|
||||
|
||||
/**
|
||||
* Handles a writing event.
|
||||
* @author Emperor
|
||||
*/
|
||||
public abstract class IoWriteEvent implements Runnable {
|
||||
|
||||
/**
|
||||
* The I/O session.
|
||||
*/
|
||||
private final IoSession session;
|
||||
|
||||
/**
|
||||
* The buffer.
|
||||
*/
|
||||
private final Object context;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoWriteEvent}.
|
||||
* @param session The session.
|
||||
* @param context The write event context.
|
||||
*/
|
||||
public IoWriteEvent(IoSession session, Object context) {
|
||||
this.session = session;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
write(session, context);
|
||||
} catch (Throwable t) {
|
||||
if (!(t instanceof CancelledKeyException)) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
session.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the data.
|
||||
* @param session The session.
|
||||
* @param context The write event context.
|
||||
*/
|
||||
public abstract void write(IoSession session, Object context);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package core.net;
|
||||
|
||||
import core.game.system.task.TaskExecutor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Handles the JS5 queue for a session.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class JS5Queue {
|
||||
|
||||
/**
|
||||
* The queued JS5 requests.
|
||||
*/
|
||||
private final Map<Integer, Boolean> queue = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The I/O session.
|
||||
*/
|
||||
private final IoSession session;
|
||||
|
||||
/**
|
||||
* If the queue has been scheduled for release.
|
||||
*/
|
||||
private boolean scheduledRelease;
|
||||
|
||||
/**
|
||||
* The lock object.
|
||||
*/
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* Constructs a new {@code JS5Queue} {@code Object}.
|
||||
* @param session The I/O session.
|
||||
*/
|
||||
public JS5Queue(IoSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues a JS-5 request.
|
||||
* @param container The container.
|
||||
* @param archive The archive.
|
||||
* @param highPriority If the request is high priority.
|
||||
*/
|
||||
public void queue(int container, int archive, boolean highPriority) {
|
||||
try {
|
||||
lock.tryLock(1000L, TimeUnit.MILLISECONDS);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
lock.unlock();
|
||||
return;
|
||||
}
|
||||
int key = container << 16 | archive;
|
||||
if (queue.containsKey(key)) {
|
||||
// SystemLogger.logErr("Queue already contained request " + container
|
||||
// + "," + archive + " > " + (container << 16 | archive) + ".");
|
||||
}
|
||||
queue.put(key, highPriority);
|
||||
lock.unlock();
|
||||
release();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the queue.
|
||||
*/
|
||||
public void release() {
|
||||
lock.lock();
|
||||
if (!scheduledRelease) {
|
||||
scheduledRelease = true;
|
||||
TaskExecutor.getExecutor().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
lock.lock();
|
||||
for (Integer hash : queue.keySet()) {
|
||||
try {
|
||||
session.write(new int[] { hash >> 16 & 0xFF, hash & 0xFFFF, queue.get(hash) ? 1 : 0 });
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
queue.clear();
|
||||
scheduledRelease = false;
|
||||
lock.unlock();
|
||||
}
|
||||
}, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session.
|
||||
* @return the session
|
||||
*/
|
||||
public IoSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scheduledRelease.
|
||||
* @return the scheduledRelease
|
||||
*/
|
||||
public boolean isScheduledRelease() {
|
||||
return scheduledRelease;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scheduledRelease.
|
||||
* @param scheduledRelease the scheduledRelease to set.
|
||||
*/
|
||||
public void setScheduledRelease(boolean scheduledRelease) {
|
||||
this.scheduledRelease = scheduledRelease;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package core.net;
|
||||
|
||||
import core.net.amsc.MSEventHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Handles (NIO-based) networking events using the reactor pattern.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class NioReactor implements Runnable {
|
||||
|
||||
/**
|
||||
* The executor service.
|
||||
*/
|
||||
private final ExecutorService service;
|
||||
|
||||
/**
|
||||
* The socket channel.
|
||||
*/
|
||||
private ServerSocketConnection channel;
|
||||
|
||||
/**
|
||||
* The I/O event handling instance.
|
||||
*/
|
||||
private IoEventHandler eventHandler;
|
||||
|
||||
/**
|
||||
* If the reactor is running.
|
||||
*/
|
||||
private boolean running;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code NioReactor}.
|
||||
*/
|
||||
private NioReactor(IoEventHandler eventHandler) {
|
||||
this.service = Executors.newSingleThreadScheduledExecutor();
|
||||
this.eventHandler = eventHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and configures a new {@code NioReactor} with a pool size of 1.
|
||||
* @param port The port.
|
||||
* @return The {@code NioReactor} {@code Object}.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
*/
|
||||
public static NioReactor configure(int port) throws IOException {
|
||||
return configure(port, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and configures a new {@code NioReactor}.
|
||||
* @param port The port.
|
||||
* @param poolSize The amount of threads in the thread pool.
|
||||
* @return The {@code NioReactor} {@code Object}.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
*/
|
||||
public static NioReactor configure(int port, int poolSize) throws IOException {
|
||||
NioReactor reactor = new NioReactor(new IoEventHandler(Executors.newFixedThreadPool(poolSize)));
|
||||
ServerSocketChannel channel = ServerSocketChannel.open();
|
||||
Selector selector = Selector.open();
|
||||
channel.bind(new InetSocketAddress(port));
|
||||
channel.configureBlocking(false);
|
||||
channel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
reactor.channel = new ServerSocketConnection(selector, channel);
|
||||
return reactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a NIO reactor used for client connections.
|
||||
* @param address The IP-address to connect to.
|
||||
* @param port The port used.
|
||||
* @return The NIO reactor object.
|
||||
* @throws IOException When an exception occurs.
|
||||
*/
|
||||
public static NioReactor connect(String address, int port) throws IOException {
|
||||
NioReactor reactor = new NioReactor(new MSEventHandler());
|
||||
Selector selector = Selector.open();
|
||||
SocketChannel channel = SocketChannel.open();
|
||||
channel.configureBlocking(false);
|
||||
channel.socket().setKeepAlive(true);
|
||||
channel.socket().setTcpNoDelay(true);
|
||||
channel.connect(new InetSocketAddress(address, port));
|
||||
channel.register(selector, SelectionKey.OP_CONNECT);
|
||||
reactor.channel = new ServerSocketConnection(selector, channel);
|
||||
return reactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the reactor.
|
||||
*/
|
||||
public void start() {
|
||||
running = true;
|
||||
service.execute(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Thread.currentThread().setName("NioReactor");
|
||||
while (running) {
|
||||
try {
|
||||
channel.getSelector().select();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Iterator<SelectionKey> iterator = channel.getSelector().selectedKeys().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
try {
|
||||
if (!key.isValid() || !key.channel().isOpen()) {
|
||||
key.cancel();
|
||||
continue;
|
||||
}
|
||||
if (key.isConnectable()) {
|
||||
eventHandler.connect(key);
|
||||
}
|
||||
if (key.isAcceptable()) {
|
||||
eventHandler.accept(key, channel.getSelector());
|
||||
}
|
||||
if (key.isReadable()) {
|
||||
eventHandler.read(key);
|
||||
} else if (key.isWritable()) {
|
||||
eventHandler.write(key);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
eventHandler.disconnect(key, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the reactor (once it's done processing current I/O events).
|
||||
*/
|
||||
public void terminate() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package core.net;
|
||||
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
/**
|
||||
* Represents a server socket and its selector.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ServerSocketConnection {
|
||||
|
||||
/**
|
||||
* The selector.
|
||||
*/
|
||||
private final Selector selector;
|
||||
|
||||
/**
|
||||
* The channel.
|
||||
*/
|
||||
private final ServerSocketChannel channel;
|
||||
|
||||
/**
|
||||
* The socket channel.
|
||||
*/
|
||||
private final SocketChannel socket;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ServerSocketConnection} {@code Object}.
|
||||
* @param selector The selector.
|
||||
* @param channel The channel.
|
||||
*/
|
||||
public ServerSocketConnection(Selector selector, ServerSocketChannel channel) {
|
||||
this.selector = selector;
|
||||
this.channel = channel;
|
||||
this.socket = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code ServerSocketConnection} {@Code
|
||||
* Object}
|
||||
* @param selector The selector.
|
||||
* @param channel The channel.
|
||||
*/
|
||||
public ServerSocketConnection(Selector selector, SocketChannel channel) {
|
||||
this.selector = selector;
|
||||
this.socket = channel;
|
||||
this.channel = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the channel is used as client.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isClient() {
|
||||
return socket != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selector.
|
||||
* @return the selector.
|
||||
*/
|
||||
public Selector getSelector() {
|
||||
return selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel.
|
||||
* @return the channel.
|
||||
*/
|
||||
public ServerSocketChannel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the socket.
|
||||
* @return the socket
|
||||
*/
|
||||
public SocketChannel getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package core.net.amsc;
|
||||
|
||||
import core.game.system.SystemLogger;
|
||||
import core.net.IoEventHandler;
|
||||
import core.net.IoSession;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Handles the management server events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MSEventHandler extends IoEventHandler {
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code MSEventHandler} {@Code Object}
|
||||
*/
|
||||
public MSEventHandler() {
|
||||
super(Executors.newSingleThreadExecutor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(SelectionKey key) throws IOException {
|
||||
SocketChannel ch = (SocketChannel) key.channel();
|
||||
try {
|
||||
if (ch.finishConnect()) {
|
||||
key.interestOps(key.interestOps() ^ SelectionKey.OP_CONNECT);
|
||||
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
|
||||
IoSession session = (IoSession) key.attachment();
|
||||
key.attach(session = new IoSession(key, service));
|
||||
WorldCommunicator.register(session);
|
||||
return;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
SystemLogger.logErr("Failed connecting to Management Server!");
|
||||
WorldCommunicator.terminate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SelectionKey key, Selector selector) throws IOException {
|
||||
super.write(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(SelectionKey key) throws IOException {
|
||||
super.read(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(SelectionKey key) {
|
||||
super.write(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(SelectionKey key, Throwable t) {
|
||||
super.disconnect(key, t);
|
||||
WorldCommunicator.terminate();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,663 @@
|
||||
package core.net.amsc;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.PlayerDetails;
|
||||
import core.game.node.entity.player.info.Rights;
|
||||
import core.game.node.entity.player.info.login.LoginParser;
|
||||
import core.game.node.entity.player.info.login.Response;
|
||||
import core.game.system.SystemLogger;
|
||||
import core.game.system.SystemManager;
|
||||
import core.game.system.SystemState;
|
||||
import core.game.system.communication.*;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.repository.Repository;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.PacketHeader;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.ClanContext;
|
||||
import core.net.packet.context.ContactContext;
|
||||
import core.net.packet.context.MessageContext;
|
||||
import core.net.packet.out.CommunicationMessage;
|
||||
import core.net.packet.out.ContactPackets;
|
||||
import core.net.packet.out.UpdateClanChat;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* The Management server packet repository.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MSPacketRepository {
|
||||
|
||||
/**
|
||||
* Handles a player info update.
|
||||
*
|
||||
*/
|
||||
public static void sendInfoUpdate(Player player) {
|
||||
IoBuffer buffer = new IoBuffer(14, PacketHeader.BYTE);
|
||||
buffer.putString(player.getName());
|
||||
buffer.put(Rights.getChatIcon(player));
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
player.getAppearance().sync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a player on the management server.
|
||||
*
|
||||
* @param parser The login.
|
||||
*/
|
||||
public static void sendPlayerRegistry(LoginParser parser) {
|
||||
IoBuffer buffer = new IoBuffer(0, PacketHeader.BYTE);
|
||||
PlayerDetails d = parser.getDetails();
|
||||
buffer.putString(d.getUsername());
|
||||
buffer.putString(d.getPassword());
|
||||
buffer.putString(d.getIpAddress());
|
||||
buffer.putString(d.getMacAddress());
|
||||
buffer.putString(d.getCompName());
|
||||
buffer.putString(d.getSerial());
|
||||
buffer.putInt(d.getRights().toInteger());
|
||||
buffer.put((byte) getIcon(d));
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the player removal packet.
|
||||
*
|
||||
* @param username The name of the player to remove.
|
||||
*/
|
||||
public static void sendPlayerRemoval(String username) {
|
||||
if (!WorldCommunicator.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
IoBuffer buffer = new IoBuffer(1, PacketHeader.BYTE);
|
||||
buffer.putString(username);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the punishment packet to the MS.
|
||||
*
|
||||
* @param player The player punishing the other player.
|
||||
* @param name The name of the player to punish.
|
||||
* @param type The punishment type (0: mute, 1: ban, 2: ip-ban, 3: mac-ban,
|
||||
* 4: msk-ban)
|
||||
* @param duration The duration of the punishment (in milliseconds, -1 =
|
||||
* permanent).
|
||||
*/
|
||||
public static void sendPunishment(Player player, String name, int type, long duration) {
|
||||
IoBuffer buffer = new IoBuffer(2, PacketHeader.BYTE);
|
||||
buffer.put(type);
|
||||
buffer.putString(name);
|
||||
buffer.putLong(duration);
|
||||
buffer.putString(player.getName());
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the communication info for the given player.
|
||||
*
|
||||
* @param username The username.
|
||||
*/
|
||||
public static void requestCommunicationInfo(String username) {
|
||||
IoBuffer buffer = new IoBuffer(3, PacketHeader.BYTE);
|
||||
buffer.putString(username);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a contact update.
|
||||
*
|
||||
* @param username The username.
|
||||
* @param contact The contact's username.
|
||||
* @param remove If we're removing the contact from the list.
|
||||
* @param block If the contact list is for the blocked players.
|
||||
* @param rank The new clan rank (or null when not updating clan rank!).
|
||||
*/
|
||||
public static void sendContactUpdate(String username, String contact, boolean remove, boolean block, ClanRank rank) {
|
||||
IoBuffer buffer = new IoBuffer(block ? 5 : 4, PacketHeader.BYTE);
|
||||
buffer.putString(username);
|
||||
buffer.putString(contact);
|
||||
if (rank != null) {
|
||||
buffer.put((byte) 2);
|
||||
buffer.put((byte) rank.ordinal());
|
||||
} else {
|
||||
buffer.put((byte) (remove ? 1 : 0));
|
||||
}
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins a clan.
|
||||
*
|
||||
* @param player The player joining a clan.
|
||||
* @param name The clan's owner name.
|
||||
*/
|
||||
public static void sendJoinClan(Player player, String name) {
|
||||
if (name.length() > 0 && !ClanRepository.getClans().containsKey(name)) {
|
||||
requestClanInfo(name);
|
||||
}
|
||||
IoBuffer buffer = new IoBuffer(6, PacketHeader.BYTE);
|
||||
buffer.putString(player.getName());
|
||||
buffer.putString(name);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the clan rename packet.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param clanName The clan name.
|
||||
*/
|
||||
public static void sendClanRename(Player player, String clanName) {
|
||||
IoBuffer buffer = new IoBuffer(7, PacketHeader.BYTE);
|
||||
buffer.putString(player.getName());
|
||||
buffer.putString(clanName);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a clan setting.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param type The setting type.
|
||||
* @param rank The rank to set.
|
||||
*/
|
||||
public static void setClanSetting(Player player, int type, ClanRank rank) {
|
||||
if (!WorldCommunicator.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
IoBuffer buffer = new IoBuffer(8, PacketHeader.BYTE);
|
||||
buffer.putString(player.getName());
|
||||
buffer.put((byte) type);
|
||||
if (rank != null) {
|
||||
buffer.put((byte) rank.ordinal());
|
||||
}
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the kicking a clan member packet.
|
||||
*
|
||||
* @param username The player's username.
|
||||
* @param name The name.
|
||||
*/
|
||||
public static void sendClanKick(String username, String name) {
|
||||
IoBuffer buffer = new IoBuffer(9, PacketHeader.BYTE);
|
||||
buffer.putString(username);
|
||||
buffer.putString(name);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a clan message.
|
||||
*
|
||||
* @param player The player sending the message.
|
||||
* @param message The message to send.
|
||||
*/
|
||||
public static void sendClanMessage(Player player, String message) {
|
||||
IoBuffer buffer = new IoBuffer(10, PacketHeader.BYTE);
|
||||
buffer.putString(player.getName());
|
||||
buffer.putString(message);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a private message.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param name The target name.
|
||||
* @param message The message.
|
||||
*/
|
||||
public static void sendPrivateMessage(Player player, String name, String message) {
|
||||
IoBuffer buffer = new IoBuffer(11, PacketHeader.BYTE);
|
||||
buffer.putString(player.getName());
|
||||
buffer.putString(name);
|
||||
buffer.putString(message);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests clan information.
|
||||
*
|
||||
* @param name The clan's owner name.
|
||||
*/
|
||||
public static void requestClanInfo(String name) {
|
||||
IoBuffer buffer = new IoBuffer(12, PacketHeader.BYTE);
|
||||
buffer.putString(name);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the chat settings.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param publicSetting The public chat setting.
|
||||
* @param privateSetting The private chat setting.
|
||||
* @param tradeSetting The trade setting.
|
||||
*/
|
||||
public static void sendChatSetting(Player player, int publicSetting, int privateSetting, int tradeSetting) {
|
||||
IoBuffer buffer = new IoBuffer(13, PacketHeader.BYTE);
|
||||
buffer.putString(player.getName());
|
||||
buffer.put(publicSetting);
|
||||
buffer.put(privateSetting);
|
||||
buffer.put(tradeSetting);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an incoming packet from the management server.
|
||||
*
|
||||
* @param opcode The opcode.
|
||||
* @param b The buffer.
|
||||
*/
|
||||
public static void handleIncoming(int opcode, ByteBuffer b) {
|
||||
IoBuffer buffer = new IoBuffer(opcode, PacketHeader.NORMAL, b);
|
||||
switch (opcode) {
|
||||
case 0:
|
||||
handleRegistryResponse(buffer);
|
||||
break;
|
||||
case 2:
|
||||
handlePlayerMessage(buffer);
|
||||
break;
|
||||
case 3:
|
||||
handleContactInformation(buffer);
|
||||
break;
|
||||
case 4:
|
||||
handleContactUpdate(buffer);
|
||||
break;
|
||||
case 5:
|
||||
handleMessage(buffer);
|
||||
break;
|
||||
case 6:
|
||||
handleClanInformation(buffer);
|
||||
break;
|
||||
case 7:
|
||||
handleLeaveClan(buffer);
|
||||
break;
|
||||
case 8:
|
||||
handleContactNotification(buffer);
|
||||
break;
|
||||
case 9:
|
||||
handlePlayerLogout(buffer);
|
||||
break;
|
||||
case 10:
|
||||
handleUpdate(buffer);
|
||||
break;
|
||||
case 11:
|
||||
handlePunishmentUpdate(buffer);
|
||||
break;
|
||||
case 15:
|
||||
SystemManager.getSystemConfig().parse();
|
||||
SystemLogger.logInfo("System configurations reloaded.");
|
||||
break;
|
||||
default:
|
||||
System.out.println("Handling incoming packet [opcode=" + opcode + ", size=" + b.limit() + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the player registry response packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handleRegistryResponse(IoBuffer buffer) {
|
||||
String username = buffer.getString();
|
||||
int opcode = buffer.get() & 0xFF;
|
||||
LoginParser parser = WorldCommunicator.finishLoginAttempt(username);
|
||||
if (parser != null) {
|
||||
PlayerDetails details = parser.getDetails();
|
||||
Response response = Response.get(opcode);
|
||||
Player player = null;
|
||||
switch (response) {
|
||||
case ALREADY_ONLINE:
|
||||
player = Repository.getPlayerByName(username);
|
||||
if (player == null || player.getSession().isActive() || !player.getSession().getAddress().equals(details.getSession().getAddress())) {
|
||||
details.getSession().write(response, true);
|
||||
break;
|
||||
}
|
||||
player.getPacketDispatch().sendLogout();
|
||||
case SUCCESSFUL:
|
||||
if (!details.getSession().isActive()) {
|
||||
sendPlayerRemoval(username);
|
||||
break;
|
||||
}
|
||||
if (player == null) {
|
||||
player = new Player(details);
|
||||
} else {
|
||||
player.updateDetails(details);
|
||||
}
|
||||
parser.initialize(player, response == Response.ALREADY_ONLINE);
|
||||
break;
|
||||
|
||||
case MOVING_WORLD:
|
||||
details.getSession().setServerKey(buffer.get());
|
||||
default:
|
||||
details.getSession().write(response, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends global message to all player nodes.
|
||||
*
|
||||
* @param message The message.
|
||||
*/
|
||||
public static void sendWorldMessage(String message) {
|
||||
IoBuffer buffer = new IoBuffer(12, PacketHeader.BYTE);
|
||||
buffer.putString(message);
|
||||
WorldCommunicator.getSession().write(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles sending a message to a player.
|
||||
*
|
||||
* @param buffer The buffer to read from.
|
||||
*/
|
||||
private static void handlePlayerMessage(IoBuffer buffer) {
|
||||
String name = buffer.getString();
|
||||
String message = buffer.getString();
|
||||
Player player = Repository.getPlayerByName(name);
|
||||
if (player != null && player.isActive()) {
|
||||
player.getPacketDispatch().sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the contact information packet.
|
||||
*
|
||||
* @param buffer The buffer to read from.
|
||||
*/
|
||||
private static void handleContactInformation(IoBuffer buffer) {
|
||||
String username = buffer.getString();
|
||||
Player player = Repository.getPlayerByName(username);
|
||||
if (player == null || !player.isActive()) {
|
||||
return;
|
||||
}
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, ContactContext.UPDATE_STATE_TYPE));
|
||||
player.getCommunication().getContacts().clear();
|
||||
int length = buffer.get() & 0xFF;
|
||||
for (int i = 0; i < length; i++) {
|
||||
String name = buffer.getString();
|
||||
Contact contact = new Contact(name);
|
||||
contact.setRank(ClanRank.values()[buffer.get() & 0xFF]);
|
||||
contact.setWorldId(buffer.get() & 0xFF);
|
||||
player.getCommunication().getContacts().put(name, contact);
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, name, contact.getWorldId()));
|
||||
}
|
||||
player.getCommunication().getBlocked().clear();
|
||||
length = buffer.get() & 0xFF;
|
||||
for (int i = 0; i < length; i++) {
|
||||
player.getCommunication().getBlocked().add(buffer.getString());
|
||||
}
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, ContactContext.IGNORE_LIST_TYPE));
|
||||
if (buffer.get() == 1) {
|
||||
String name = buffer.getString();
|
||||
sendJoinClan(player, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the contact update packet.
|
||||
*/
|
||||
private static void handleContactUpdate(IoBuffer buffer) {
|
||||
String username = buffer.getString();
|
||||
String contactName = buffer.getString();
|
||||
boolean block = buffer.get() == 1;
|
||||
int type = buffer.get();
|
||||
Player player = Repository.getPlayerByName(username);
|
||||
if (player == null || !player.isActive()) {
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case 0:
|
||||
if (block) {
|
||||
player.getCommunication().getBlocked().add(contactName);
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, ContactContext.IGNORE_LIST_TYPE));
|
||||
break;
|
||||
}
|
||||
int worldId = buffer.get() & 0xFF;
|
||||
Contact contact = player.getCommunication().getContacts().get(contactName);
|
||||
if (contact == null) {
|
||||
player.getCommunication().getContacts().put(contactName, contact = new Contact(contactName));
|
||||
}
|
||||
contact.setWorldId(worldId);
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, contactName, worldId));
|
||||
break;
|
||||
case 1:
|
||||
if (block) {
|
||||
player.getCommunication().getBlocked().remove(contactName);
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, ContactContext.IGNORE_LIST_TYPE));
|
||||
break;
|
||||
}
|
||||
player.getCommunication().getContacts().remove(contactName);
|
||||
break;
|
||||
default:
|
||||
ClanRank rank = ClanRank.values()[type - 2];
|
||||
contact = player.getCommunication().getContacts().get(contactName);
|
||||
if (contact == null) {
|
||||
// SystemLogger.logErr("Invalid contact specified [name=" +
|
||||
// contact + "]!");
|
||||
break;
|
||||
}
|
||||
contact.setRank(rank);
|
||||
ClanRepository clan = ClanRepository.get(username);
|
||||
if (clan != null) {
|
||||
clan.rank(contactName, rank);
|
||||
}
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, contactName, contact.getWorldId()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the message packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handleMessage(IoBuffer buffer) {
|
||||
String username = buffer.getString();
|
||||
String sender = buffer.getString();
|
||||
int type = buffer.get() & 0xFF;
|
||||
int icon = buffer.get() & 0xFF;
|
||||
String message = buffer.getString();
|
||||
Player player = Repository.getPlayerByName(username);
|
||||
if (player == null || !player.isActive()) {
|
||||
return;
|
||||
}
|
||||
int opcode = MessageContext.SEND_MESSAGE;
|
||||
switch (type) {
|
||||
case 1:
|
||||
opcode = MessageContext.RECIEVE_MESSAGE;
|
||||
break;
|
||||
case 2:
|
||||
opcode = MessageContext.CLAN_MESSAGE;
|
||||
break;
|
||||
}
|
||||
PacketRepository.send(CommunicationMessage.class, new MessageContext(player, sender, icon, opcode, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the clan information packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handleClanInformation(IoBuffer buffer) {
|
||||
String owner = buffer.getString();
|
||||
ClanRepository clan = ClanRepository.getClans().get(owner);
|
||||
if (clan == null) {
|
||||
ClanRepository.getClans().put(owner, clan = new ClanRepository(owner));
|
||||
} else {
|
||||
clan.getRanks().clear();
|
||||
clan.getPlayers().clear();
|
||||
}
|
||||
clan.setName(buffer.getString());
|
||||
int length = buffer.get() & 0xFF;
|
||||
for (int i = 0; i < length; i++) {
|
||||
String name = buffer.getString();
|
||||
int worldId = buffer.get() & 0xFF;
|
||||
clan.getRanks().put(name, ClanRank.values()[buffer.get() & 0xFF]);
|
||||
ClanEntry entry = new ClanEntry(name, worldId);
|
||||
if (worldId == GameWorld.getSettings().getWorldId()) {
|
||||
Player player = Repository.getPlayerByName(name);
|
||||
entry.setPlayer(player);
|
||||
if (player != null) {
|
||||
player.getCommunication().setClan(clan);
|
||||
}
|
||||
}
|
||||
clan.getPlayers().add(entry);
|
||||
}
|
||||
clan.setJoinRequirement(ClanRank.values()[buffer.get() & 0xFF]);
|
||||
clan.setKickRequirement(ClanRank.values()[buffer.get() & 0xFF]);
|
||||
clan.setMessageRequirement(ClanRank.values()[buffer.get() & 0xFF]);
|
||||
clan.setLootRequirement(ClanRank.values()[buffer.get() & 0xFF]);
|
||||
clan.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the clan information packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handleLeaveClan(IoBuffer buffer) {
|
||||
String name = buffer.getString();
|
||||
Player player = Repository.getPlayerByName(name);
|
||||
if (player == null || !player.isActive()) {
|
||||
return;
|
||||
}
|
||||
if (player.getCommunication().getClan() == null) {
|
||||
return;
|
||||
}
|
||||
PacketRepository.send(UpdateClanChat.class, new ClanContext(player, null, true));
|
||||
player.getCommunication().setClan(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a contact notification packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handleContactNotification(IoBuffer buffer) {
|
||||
String name = buffer.getString();
|
||||
int worldId = buffer.get() & 0xFF;
|
||||
int size = buffer.get() & 0xFF;
|
||||
for (int i = 0; i < size; i++) {
|
||||
String username = buffer.getString();
|
||||
Player player = Repository.getPlayerByName(username);
|
||||
if (player == null) {
|
||||
continue;
|
||||
}
|
||||
Contact c = player.getCommunication().getContacts().get(name);
|
||||
if (c == null) {
|
||||
continue;
|
||||
}
|
||||
c.setWorldId(worldId);
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, name, worldId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a player logout notification packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handlePlayerLogout(IoBuffer buffer) {
|
||||
String name = buffer.getString();
|
||||
for (Player p : Repository.getPlayers()) {
|
||||
if (CommunicationInfo.hasContact(p, name)) {
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(p, name, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the update packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handleUpdate(IoBuffer buffer) {
|
||||
int ticks = buffer.getInt();
|
||||
if (ticks < 0) {
|
||||
SystemManager.getUpdater().cancel();
|
||||
} else {
|
||||
SystemManager.getUpdater().setCountdown(ticks);
|
||||
SystemManager.flag(SystemState.UPDATING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the punishment update packet.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
private static void handlePunishmentUpdate(IoBuffer buffer) {
|
||||
String key = buffer.getString();
|
||||
int type = buffer.get();
|
||||
long duration = buffer.getLong();
|
||||
switch (type) {
|
||||
case 0:
|
||||
Player player = Repository.getPlayerByName(key);
|
||||
if (player != null && player.isActive()) {
|
||||
player.getPacketDispatch().sendMessages((duration > 0L ? new String[]{"You have been muted.", "To prevent further mutes please read the rules."} : new String[]{"You have been unmuted."}));
|
||||
}
|
||||
player.getDetails().setMuteTime(duration);
|
||||
break;
|
||||
case 1:
|
||||
player = Repository.getPlayerByName(key);
|
||||
if (player != null && player.isActive() && duration > System.currentTimeMillis()) {
|
||||
player.getSession().disconnect();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (Player p : Repository.getPlayers()) {
|
||||
if (p.getDetails().getIpAddress().equals(key)) {
|
||||
p.getSession().disconnect();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (Player p : Repository.getPlayers()) {
|
||||
if (p == null || key == null || p.getDetails() == null) {
|
||||
return;
|
||||
}
|
||||
if (p.getDetails().getMacAddress().equals(key)) {
|
||||
p.getSession().disconnect();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for (Player p : Repository.getPlayers()) {
|
||||
if (p == null || key == null || p.getDetails() == null) {
|
||||
return;
|
||||
}
|
||||
if (p.getDetails().getSerial().equals(key)) {
|
||||
p.getSession().disconnect();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
player = Repository.getPlayerByName(key);
|
||||
if (player != null) {
|
||||
player.getPacketDispatch().sendLogout();
|
||||
player.clear(true);
|
||||
player.getSession().disconnect();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the icon to send.
|
||||
*
|
||||
* @param d the details.
|
||||
* @return the icon.
|
||||
*/
|
||||
private static int getIcon(PlayerDetails d) {
|
||||
int icon = 0;
|
||||
if (d.getRights() != Rights.REGULAR_PLAYER) {
|
||||
icon = d.getRights().toInteger();
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package core.net.amsc;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.repository.Repository;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.ContactContext;
|
||||
import core.net.packet.out.ContactPackets;
|
||||
|
||||
/**
|
||||
* The management server state.
|
||||
* @author Emperor
|
||||
*/
|
||||
public enum ManagementServerState {
|
||||
|
||||
/**
|
||||
* If the management server is not available.
|
||||
*/
|
||||
NOT_AVAILABLE(2),
|
||||
|
||||
/**
|
||||
* If we're still connecting to the Management server.
|
||||
*/
|
||||
CONNECTING(1),
|
||||
|
||||
/**
|
||||
* If we're connected to the management server.
|
||||
*/
|
||||
AVAILABLE(2);
|
||||
|
||||
/**
|
||||
* The value of this state.
|
||||
*/
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ManagementServerState} {@code Object}
|
||||
* @param value The value.
|
||||
*/
|
||||
private ManagementServerState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the state gets set.
|
||||
*/
|
||||
public void set() {
|
||||
for (Player player : Repository.getPlayers()) {
|
||||
PacketRepository.send(ContactPackets.class, new ContactContext(player, ContactContext.UPDATE_STATE_TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state value.
|
||||
* @return The value.
|
||||
*/
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package core.net.amsc;
|
||||
|
||||
import core.game.node.entity.player.info.Rights;
|
||||
import core.game.node.entity.player.info.login.LoginParser;
|
||||
import core.game.node.entity.player.info.login.Response;
|
||||
import core.game.system.SystemLogger;
|
||||
import core.game.system.task.TaskExecutor;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.EventProducer;
|
||||
import core.net.IoSession;
|
||||
import core.net.NioReactor;
|
||||
import core.net.producer.MSHSEventProducer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Handles world communication.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class WorldCommunicator {
|
||||
|
||||
/**
|
||||
* The handshake events producer.
|
||||
*/
|
||||
private static final EventProducer HANDSHAKE_PRODUCER = new MSHSEventProducer();
|
||||
|
||||
/**
|
||||
* The current state.
|
||||
*/
|
||||
private static ManagementServerState state = ManagementServerState.CONNECTING;
|
||||
|
||||
/**
|
||||
* The I/O session.
|
||||
*/
|
||||
private static IoSession session;
|
||||
|
||||
/**
|
||||
* The world information.
|
||||
*/
|
||||
private static final WorldStatistics[] WORLDS = new WorldStatistics[10];
|
||||
|
||||
/**
|
||||
* The current login attempts.
|
||||
*/
|
||||
private static final Map<String, LoginParser> loginAttempts = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* The NIO reactor.
|
||||
*/
|
||||
private static NioReactor reactor;
|
||||
|
||||
/**
|
||||
* Registers a new world.
|
||||
* @param session The session.
|
||||
*/
|
||||
public static void register(IoSession session) {
|
||||
WorldCommunicator.session = session;
|
||||
session.setProducer(HANDSHAKE_PRODUCER);
|
||||
session.write(true);
|
||||
WORLDS[GameWorld.getSettings().getWorldId() - 1] = new WorldStatistics(GameWorld.getSettings().getWorldId());
|
||||
session.setObject(WORLDS[GameWorld.getSettings().getWorldId() - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a login attempt.
|
||||
* @param parser The login attempt.
|
||||
*/
|
||||
public static void register(final LoginParser parser) {
|
||||
LoginParser p = loginAttempts.get(parser.getDetails().getUsername());
|
||||
if (p != null && GameWorld.getTicks() - p.getTimeStamp() < 50 && p.getDetails().getRights() == Rights.REGULAR_PLAYER) {
|
||||
parser.getDetails().getSession().write(Response.ALREADY_ONLINE, true);
|
||||
return;
|
||||
}
|
||||
loginAttempts.put(parser.getDetails().getUsername(), parser);
|
||||
TaskExecutor.executeSQL(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!parser.getDetails().parse()) {
|
||||
parser.getDetails().getSession().write(Response.INVALID_LOGIN_SERVER, true);
|
||||
return;
|
||||
}
|
||||
MSPacketRepository.sendPlayerRegistry(parser);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to connect to the management server.
|
||||
*/
|
||||
public static void connect() {
|
||||
try {
|
||||
SystemLogger.logInfo("Attempting to connect to management server...");
|
||||
setState(ManagementServerState.CONNECTING);
|
||||
/*if (isLocallyHosted()) {
|
||||
SystemLogger.log("Management server is hosted on local machine!");
|
||||
reactor = NioReactor.connect(GameWorld.getSettings().getMsAddress(), 5555);
|
||||
} else {*/
|
||||
reactor = NioReactor.connect(GameWorld.getSettings().getMsAddress(), 5555);
|
||||
//}
|
||||
reactor.start();
|
||||
} catch (Throwable e) {
|
||||
SystemLogger.logErr("Unable to connect to management server");
|
||||
e.printStackTrace();
|
||||
terminate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the Management server is locally hosted.
|
||||
* @return {@code True} if so.
|
||||
* @throws IOException When an I/O exception occurs.
|
||||
*/
|
||||
private static boolean isLocallyHosted() throws IOException {
|
||||
InetAddress address = InetAddress.getByName(GameWorld.getSettings().getMsAddress());
|
||||
if (address.isAnyLocalAddress() || address.isLoopbackAddress()) {
|
||||
return true;
|
||||
}
|
||||
return NetworkInterface.getByInetAddress(address) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the world communicator.
|
||||
*/
|
||||
public static void terminate() {
|
||||
setState(ManagementServerState.NOT_AVAILABLE);
|
||||
if (reactor != null) {
|
||||
reactor.terminate();
|
||||
reactor = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and removes the login attempt for the given username.
|
||||
* @param username The username.
|
||||
* @return The login attempt.
|
||||
*/
|
||||
public static LoginParser finishLoginAttempt(String username) {
|
||||
return loginAttempts.remove(username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local world.
|
||||
* @return The world statistics of this world server.
|
||||
*/
|
||||
public static WorldStatistics getLocalWorld() {
|
||||
return WORLDS[GameWorld.getSettings().getWorldId() - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the world the player is connected to.
|
||||
* @param playerName The player's name.
|
||||
* @return The world id, or -1 if the player wasn't connected.
|
||||
*/
|
||||
public static int getWorld(String playerName) {
|
||||
for (int i = 0; i < WORLDS.length; i++) {
|
||||
if (WORLDS[i].getPlayers().contains(playerName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world statistics for the given index.
|
||||
* @param id The world id.
|
||||
* @return The world statistics.
|
||||
*/
|
||||
public static WorldStatistics getWorld(int id) {
|
||||
return WORLDS[id - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the session.
|
||||
* @return the session
|
||||
*/
|
||||
public static IoSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this world is connected to the Management server.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public static boolean isEnabled() {
|
||||
return state == ManagementServerState.AVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the login attempts mapping.
|
||||
* @return The login attempts mapping.
|
||||
*/
|
||||
public static Map<String, LoginParser> getLoginAttempts() {
|
||||
return loginAttempts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state.
|
||||
* @return the state
|
||||
*/
|
||||
public static ManagementServerState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state.
|
||||
* @param state the state to set.
|
||||
*/
|
||||
public static void setState(ManagementServerState state) {
|
||||
if (WorldCommunicator.state != state) {
|
||||
WorldCommunicator.state = state;
|
||||
state.set();
|
||||
SystemLogger.logInfo("Management server status: " + state + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reactor.
|
||||
* @return the reactor
|
||||
*/
|
||||
public static NioReactor getReactor() {
|
||||
return reactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the reactor.
|
||||
* @param reactor the reactor to set.
|
||||
*/
|
||||
public static void setReactor(NioReactor reactor) {
|
||||
WorldCommunicator.reactor = reactor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package core.net.amsc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Holds information of a certain game world.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class WorldStatistics {
|
||||
|
||||
/**
|
||||
* The world id.
|
||||
*/
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* The list of players connected to this world.
|
||||
*/
|
||||
private final List<String> players = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WorldStatistics} {@Code Object}
|
||||
* @param id The world id.
|
||||
*/
|
||||
public WorldStatistics(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the players.
|
||||
* @return the players
|
||||
*/
|
||||
public List<String> getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
* @return the id
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.game.system.SystemLogger;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.IoReadEvent;
|
||||
import core.net.IoSession;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.PacketRepository;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles game packet reading.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class GameReadEvent extends IoReadEvent {
|
||||
|
||||
/**
|
||||
* The incoming packet sizes, sorted by opcode.
|
||||
*/
|
||||
public static final int[] PACKET_SIZES = {
|
||||
-3, -3, -3, 2, 2, -3, 8, -3, -3, 6, // 0-9
|
||||
4, -3, -3, -3, -3, -3, -3, 0, -3, -3, // 10-19
|
||||
4, 4, 1, 4, -3, -3, -3, 16, -3, -3, // 20-29
|
||||
2, -3, -3, 6, 8, -3, -3, -3, -3, -1, // 30-39
|
||||
-3, -3, -3, -3, -1, -3, -3, -3, 6, -3, // 40-49
|
||||
-3, -3, -3, 6, -3, 8, -3, 8, -3, -3, // 50-59
|
||||
-3, -3, -3, -3, 6, -1, 6, -3, 2, -3, // 60-69
|
||||
-3, 2, 2, 12, -3, 6, -3, -1, 2, 12, // 70-79
|
||||
-3, 8, 12, -3, 6, 8, -3, -3, -3, -3, // 80-89
|
||||
-3, -3, 2, 0, 2, -3, -3, -3, 4, 10, // 90-99
|
||||
-3, 14, -3, -3, 8, -3, 2, -3, -3, 6, // 100-109
|
||||
0, 2, -3, -3, 2, 10, -3, -1, -3, -3, // 110-119
|
||||
8, -3, -3, -1, 6, -3, -3, -3, -3, -3, // 120-129
|
||||
-3, 10, 6, 2, 14, 8, -3, 4, -3, -3, // 130-139
|
||||
-3, -3, -3, -3, -3, -3, -3, -3, 2, -3, // 140-149
|
||||
-3, -3, -3, 8, 8, 6, 8, 3, -3, -3, // 150-159
|
||||
-3, 8, 8, -3, -3, -3, 6, -1, 6, -3, // 160-169
|
||||
6, -3, -3, -3, -3, 2, -3, 2, -1, 4, // 170-179
|
||||
2, -3, -3, -3, 0, -3, -3, -3, 9, -3, // 180-189
|
||||
-3, -3, -3, -3, 6, 8, 6, -3, -3, 6, // 190-199
|
||||
-3, -1, -3, -3, -3, -3, 8, -3, -3, -3, // 200-209
|
||||
-3, -3, -3, 8, -3, -1, -3, -3, 2, -3, // 210-219
|
||||
-3, -3, -3, -3, -3, -3, -3, -3, 6, -3, // 220-229
|
||||
-3, 9, -3, 12, 6, -3, -3, -1, -3, 8, // 230-239
|
||||
-3, -3, -3, 6, 8, 0, -3, 6, 10, -3, // 240-249
|
||||
-3, -3, -3, 14, 6, -3 // 250-255
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GameReadEvent}.
|
||||
* @param session The session.
|
||||
* @param buffer The buffer to read from.
|
||||
*/
|
||||
public GameReadEvent(IoSession session, ByteBuffer buffer) {
|
||||
super(session, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(IoSession session, ByteBuffer buffer) {
|
||||
int last = -1;
|
||||
while (buffer.hasRemaining()) {
|
||||
int opcode = buffer.get() & 0xFF;
|
||||
if (session == null || session.getPlayer() == null) {
|
||||
continue;
|
||||
}
|
||||
if (opcode >= PACKET_SIZES.length) {
|
||||
break;
|
||||
}
|
||||
int header = PACKET_SIZES[opcode];
|
||||
int size = header;
|
||||
if (header < 0) {
|
||||
size = getPacketSize(buffer, opcode, header, last);
|
||||
}
|
||||
if (size == -1) {
|
||||
break;
|
||||
}
|
||||
if (buffer.remaining() < size) {
|
||||
switch (header) {
|
||||
case -2:
|
||||
queueBuffer(opcode, size >> 8, size);
|
||||
break;
|
||||
case -1:
|
||||
queueBuffer(opcode, size);
|
||||
break;
|
||||
default:
|
||||
queueBuffer(opcode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
byte[] data = new byte[size];
|
||||
buffer.get(data);
|
||||
IoBuffer buf = new IoBuffer(opcode, null, ByteBuffer.wrap(data));
|
||||
//SystemLogger.log("Packet opcode " + opcode + "received.");
|
||||
IncomingPacket packet = PacketRepository.getIncoming(opcode);
|
||||
session.setLastPing(System.currentTimeMillis());
|
||||
if (packet == null) {
|
||||
if (GameWorld.getSettings().isDevMode()) {
|
||||
SystemLogger.logErr("Unhandled packet [opcode=" + opcode + ", previous=" + last + ", size=" + size + ", header=" + header + "]");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
last = opcode;
|
||||
try {
|
||||
packet.decode(session.getPlayer(), opcode, buf);
|
||||
//System.out.println("Handled packed " + opcode + "!");
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet size for the given opcode.
|
||||
* @param buffer The buffer.
|
||||
* @param opcode The opcode.
|
||||
* @param header The packet header.
|
||||
* @param last The last opcode.
|
||||
* @return The packet size.
|
||||
*/
|
||||
private int getPacketSize(ByteBuffer buffer, int opcode, int header, int last) {
|
||||
if (header == -1) {
|
||||
if (buffer.remaining() < 1) {
|
||||
queueBuffer(opcode);
|
||||
return -1;
|
||||
}
|
||||
return buffer.get() & 0xFF;
|
||||
}
|
||||
if (header == -2) {
|
||||
if (buffer.remaining() < 2) {
|
||||
queueBuffer(opcode);
|
||||
return -1;
|
||||
}
|
||||
return buffer.getShort() & 0xFFFF;
|
||||
}
|
||||
if(header == -3){
|
||||
System.out.println(buffer.remaining());
|
||||
}
|
||||
SystemLogger.logErr("Invalid packet [opcode=" + opcode + ", last=" + last + ", queued=" + usedQueuedBuffer + "], header=" + header+"!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles game packet writing events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class GameWriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GameWriteEvent}.
|
||||
* @param session The session.
|
||||
* @param context The context.
|
||||
*/
|
||||
public GameWriteEvent(IoSession session, Object context) {
|
||||
super(session, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
if (context instanceof ByteBuffer) {
|
||||
session.queue((ByteBuffer) context);
|
||||
return;
|
||||
}
|
||||
IoBuffer buffer = (IoBuffer) context;
|
||||
ByteBuffer buf = (ByteBuffer) buffer.toByteBuffer().flip();
|
||||
if (buf == null) {
|
||||
throw new RuntimeException("Critical networking error: The byte buffer requested was null.");
|
||||
}
|
||||
if (buffer.opcode() != -1) {
|
||||
int packetLength = buf.remaining() + 4;
|
||||
ByteBuffer response = ByteBuffer.allocate(packetLength);
|
||||
response.put((byte) buffer.opcode());
|
||||
switch (buffer.getHeader()) {
|
||||
case BYTE:
|
||||
response.put((byte) buf.remaining());
|
||||
break;
|
||||
case SHORT:
|
||||
response.putShort((short) buf.remaining());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
buf = (ByteBuffer) response.put(buf).flip();
|
||||
}
|
||||
session.queue(buf);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.net.Constants;
|
||||
import core.net.IoReadEvent;
|
||||
import core.net.IoSession;
|
||||
import core.net.lobby.WorldList;
|
||||
import core.net.registry.AccountRegister;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Handles handshake read events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class HSReadEvent extends IoReadEvent {
|
||||
|
||||
// debug
|
||||
static Map<String, Integer> count = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HSReadEvent}.
|
||||
* @param session The session.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public HSReadEvent(IoSession session, ByteBuffer buffer) {
|
||||
super(session, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(IoSession session, ByteBuffer buffer) {
|
||||
Integer amount = count.get(session.getAddress());
|
||||
if (amount == null) {
|
||||
amount = 0;
|
||||
}
|
||||
count.put(session.getAddress(), amount + 1);
|
||||
int opcode = buffer.get() & 0xFF;
|
||||
switch (opcode) {
|
||||
case 14:
|
||||
session.setNameHash(buffer.get() & 0xFF);
|
||||
session.setServerKey(RandomFunction.RANDOM.nextLong());
|
||||
session.write(true);
|
||||
break;
|
||||
case 15:
|
||||
int revision = buffer.getInt();
|
||||
//int sub_revision = buffer.getInt();
|
||||
buffer.flip();
|
||||
System.out.println(buffer.limit());
|
||||
if (revision != 530 ){//|| sub_revision != Constants.CLIENT_BUILD) {
|
||||
session.disconnect();
|
||||
break;
|
||||
}
|
||||
session.write(false);
|
||||
break;
|
||||
case 147:
|
||||
case 186:
|
||||
case 36:
|
||||
AccountRegister.read(session, opcode, buffer);
|
||||
break;
|
||||
case 255: // World list
|
||||
int updateStamp = buffer.getInt();
|
||||
WorldList.sendUpdate(session, updateStamp);
|
||||
break;
|
||||
default:
|
||||
session.disconnect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
import core.net.producer.JS5EventProducer;
|
||||
import core.net.producer.LoginEventProducer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles Handshake write events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class HSWriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* The JS-5 event producer.
|
||||
*/
|
||||
private static final JS5EventProducer JS5_PRODUCER = new JS5EventProducer();
|
||||
|
||||
/**
|
||||
* The login event producer.
|
||||
*/
|
||||
private static final LoginEventProducer LOGIN_PRODUCER = new LoginEventProducer();
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HSWriteEvent} {@code Object}.
|
||||
* @param session The session.
|
||||
* @param context The context.
|
||||
*/
|
||||
public HSWriteEvent(IoSession session, Object context) {
|
||||
super(session, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(9);
|
||||
buffer.put((byte) 0);
|
||||
if ((Boolean) context) {
|
||||
buffer.putLong(session.getServerKey());
|
||||
session.setProducer(LOGIN_PRODUCER);
|
||||
} else {
|
||||
session.setProducer(JS5_PRODUCER);
|
||||
}
|
||||
buffer.flip();
|
||||
session.queue(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.cache.misc.buffer.ByteBufferUtils;
|
||||
import core.net.IoReadEvent;
|
||||
import core.net.IoSession;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles JS-5 reading events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class JS5ReadEvent extends IoReadEvent {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code JS5ReadEvent}.
|
||||
* @param session The session.
|
||||
* @param buffer The buffer.
|
||||
*/
|
||||
public JS5ReadEvent(IoSession session, ByteBuffer buffer) {
|
||||
super(session, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(IoSession session, ByteBuffer buffer) {
|
||||
while (buffer.hasRemaining()) {
|
||||
int opcode = buffer.get() & 0xFF;
|
||||
//System.out.println("JS5 initiated! Opcode: " + opcode);
|
||||
if (buffer.remaining() < 3) {
|
||||
queueBuffer(opcode);
|
||||
return;
|
||||
}
|
||||
switch (opcode) {
|
||||
case 0:
|
||||
case 1:
|
||||
int request = ByteBufferUtils.getTriByte(buffer);
|
||||
//System.out.println("Requested file " + request);
|
||||
int container = request >> 16 & 0xFF;
|
||||
//System.out.println("In container " + container);
|
||||
int archive = request & 0xFFFF;
|
||||
//System.out.println("In archive " + archive);
|
||||
session.getJs5Queue().queue(container, archive, opcode == 1);
|
||||
break;
|
||||
case 2: // music
|
||||
case 3: // Music
|
||||
buffer.get();
|
||||
buffer.getShort();
|
||||
break;
|
||||
case 4:
|
||||
session.setJs5Encryption(buffer.get());
|
||||
if (buffer.getShort() != 0) {
|
||||
session.disconnect();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case 9:
|
||||
if (buffer.remaining() < 4) {
|
||||
queueBuffer(opcode);
|
||||
return;
|
||||
}
|
||||
buffer.getInt();
|
||||
break;
|
||||
case 6:
|
||||
ByteBufferUtils.getTriByte(buffer); // Value should be 3
|
||||
// buffer.getShort(); // Value should be 0
|
||||
break;
|
||||
case 7:
|
||||
buffer.get();
|
||||
buffer.getShort();
|
||||
session.disconnect();
|
||||
return;
|
||||
default:
|
||||
System.out.println("Unhandled JS5 opcode " + opcode + "!");
|
||||
buffer.get();
|
||||
buffer.getShort();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.cache.Cache;
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles JS-5 writing events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class JS5WriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* The cached reference data.
|
||||
*/
|
||||
private static byte[] cachedReference;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code JS5WriteEvent}.
|
||||
* @param session The session.
|
||||
* @param context The event context.
|
||||
*/
|
||||
public JS5WriteEvent(IoSession session, Object context) {
|
||||
super(session, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
int[] request = (int[]) context;
|
||||
int container = request[0];
|
||||
int archive = request[1];
|
||||
boolean priority = request[2] == 1;
|
||||
if (archive == 255 && container == 255) {
|
||||
session.queue(getReferenceData());
|
||||
return;
|
||||
}
|
||||
ByteBuffer response = Cache.getArchiveData(container, archive, priority, session.getJs5Encryption());
|
||||
if (response != null) {
|
||||
session.queue(response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reference data.
|
||||
* @return The reference data.
|
||||
*/
|
||||
private static ByteBuffer getReferenceData() {
|
||||
if (cachedReference == null) {
|
||||
cachedReference = Cache.generateReferenceData();
|
||||
}
|
||||
ByteBuffer buffer = ByteBuffer.allocate(cachedReference.length << 2);
|
||||
buffer.put((byte) 255);
|
||||
buffer.putShort((short) 255);
|
||||
buffer.put((byte) 0);
|
||||
buffer.putInt(cachedReference.length);
|
||||
int offset = 10;
|
||||
for (int index = 0; index < cachedReference.length; index++) {
|
||||
if (offset == 512) {
|
||||
buffer.put((byte) 255);
|
||||
offset = 1;
|
||||
}
|
||||
buffer.put(cachedReference[index]);
|
||||
offset++;
|
||||
}
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.login.Response;
|
||||
import core.net.EventProducer;
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
import core.net.producer.GameEventProducer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles login writing events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class LoginWriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* The game event producer.
|
||||
*/
|
||||
private static final EventProducer GAME_PRODUCER = new GameEventProducer();
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LoginWriteEvent}.
|
||||
* @param session The session.
|
||||
* @param context The event context.
|
||||
*/
|
||||
public LoginWriteEvent(IoSession session, Object context) {
|
||||
super(session, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
Response response = (Response) context;
|
||||
ByteBuffer buffer = ByteBuffer.allocate(500);
|
||||
buffer.put((byte) response.opcode());
|
||||
switch (response.opcode()) {
|
||||
case 2: //successful login
|
||||
buffer.put(getWorldResponse(session));
|
||||
session.setProducer(GAME_PRODUCER);
|
||||
break;
|
||||
//Could add a case here to auto-restart the server in case the login server goes offline (case 8)
|
||||
//Possibly a risk for malicious attacks though
|
||||
case 21: //Moving world
|
||||
buffer.put((byte) session.getServerKey());
|
||||
break;
|
||||
}
|
||||
buffer.flip();
|
||||
session.queue(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world response buffer.
|
||||
* @param session The session.
|
||||
* @return The buffer.
|
||||
*/
|
||||
private static ByteBuffer getWorldResponse(IoSession session) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(150);
|
||||
Player player = session.getPlayer();
|
||||
buffer.put((byte) player.getDetails().getRights().ordinal());
|
||||
buffer.put((byte) 0);
|
||||
buffer.put((byte) 0);
|
||||
buffer.put((byte) 0);
|
||||
buffer.put((byte) 1);
|
||||
buffer.put((byte) 0);
|
||||
buffer.put((byte) 0);
|
||||
buffer.putShort((short) player.getIndex());
|
||||
buffer.put((byte) (1)); // Enable all G.E boxes
|
||||
buffer.put((byte) 1);
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.net.EventProducer;
|
||||
import core.net.IoReadEvent;
|
||||
import core.net.IoSession;
|
||||
import core.net.producer.RegistryEventProducer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles the management server handshake read events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MSHSReadEvent extends IoReadEvent {
|
||||
|
||||
/**
|
||||
* The event producer.
|
||||
*/
|
||||
private static final EventProducer REGISTRY_PRODUCER = new RegistryEventProducer();
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MSHSReadEvent} {@Code Object}
|
||||
* @param session The session.
|
||||
* @param buffer The buffer to read.
|
||||
*/
|
||||
public MSHSReadEvent(IoSession session, ByteBuffer buffer) {
|
||||
super(session, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(IoSession session, ByteBuffer buffer) {
|
||||
int opcode = buffer.get() & 0xFF;
|
||||
if (opcode == 14) {
|
||||
session.setProducer(REGISTRY_PRODUCER);
|
||||
session.write(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.cache.misc.buffer.ByteBufferUtils;
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles the management server handshake write event.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MSHSWriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* The password used to verify
|
||||
*/
|
||||
private static final String PASSWORD = "0x14ari0SSbh98989910";
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MSHSWriteEvent} {@code Object}
|
||||
* @param session The session.
|
||||
* @param context The context.
|
||||
*/
|
||||
public MSHSWriteEvent(IoSession session, Object context) {
|
||||
super(session, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(2 + PASSWORD.length());
|
||||
buffer.put((byte) 88);
|
||||
ByteBufferUtils.putString(PASSWORD, buffer);
|
||||
session.queue((ByteBuffer) buffer.flip());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.game.system.SystemLogger;
|
||||
import core.net.IoReadEvent;
|
||||
import core.net.IoSession;
|
||||
import core.net.amsc.MSPacketRepository;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles reading Management server packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MSReadEvent extends IoReadEvent {
|
||||
|
||||
/**
|
||||
* The packet sizes.
|
||||
*/
|
||||
private static final int[] PACKET_SIZE = { -1, -1, -1, -2, -1, -1, -2, -1, -2, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MSReadEvent} {@code Object}
|
||||
* @param session The I/O session.
|
||||
* @param buffer The buffer to read from.
|
||||
*/
|
||||
public MSReadEvent(IoSession session, ByteBuffer buffer) {
|
||||
super(session, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(IoSession session, ByteBuffer buffer) {
|
||||
int last = -1;
|
||||
while (buffer.hasRemaining()) {
|
||||
int opcode = buffer.get() & 0xFF;
|
||||
if (opcode >= PACKET_SIZE.length) {
|
||||
break;
|
||||
}
|
||||
int header = PACKET_SIZE[opcode];
|
||||
int size = header;
|
||||
if (header < 0) {
|
||||
size = getPacketSize(buffer, opcode, header, last);
|
||||
}
|
||||
if (size == -1) {
|
||||
break;
|
||||
}
|
||||
if (buffer.remaining() < size) {
|
||||
switch (header) {
|
||||
case -2:
|
||||
queueBuffer(opcode, size >> 8, size);
|
||||
break;
|
||||
case -1:
|
||||
queueBuffer(opcode, size);
|
||||
break;
|
||||
default:
|
||||
queueBuffer(opcode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
byte[] data = new byte[size];
|
||||
buffer.get(data);
|
||||
last = opcode;
|
||||
try {
|
||||
MSPacketRepository.handleIncoming(opcode, ByteBuffer.wrap(data));
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet size for the given opcode.
|
||||
* @param buffer The buffer.
|
||||
* @param opcode The opcode.
|
||||
* @param header The packet header.
|
||||
* @param last The last opcode.
|
||||
* @return The packet size.
|
||||
*/
|
||||
private int getPacketSize(ByteBuffer buffer, int opcode, int header, int last) {
|
||||
if (header == -1) {
|
||||
if (buffer.remaining() < 1) {
|
||||
queueBuffer(opcode);
|
||||
return -1;
|
||||
}
|
||||
return buffer.get() & 0xFF;
|
||||
}
|
||||
if (header == -2) {
|
||||
if (buffer.remaining() < 2) {
|
||||
queueBuffer(opcode);
|
||||
return -1;
|
||||
}
|
||||
return buffer.getShort() & 0xFFFF;
|
||||
}
|
||||
SystemLogger.logErr("Invalid packet [opcode=" + opcode + ", last=" + last + ", queued=" + usedQueuedBuffer + "]!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles management server write events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MSWriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MSWriteEvent} {@code Object}
|
||||
* @param session The I/O session.
|
||||
* @param context The packet context.
|
||||
*/
|
||||
public MSWriteEvent(IoSession session, Object context) {
|
||||
super(session, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
IoBuffer b = (IoBuffer) context;
|
||||
int size = b.toByteBuffer().position();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1 + size + b.getHeader().ordinal());
|
||||
buffer.put((byte) b.opcode());
|
||||
switch (b.getHeader()) {
|
||||
case NORMAL:
|
||||
break;
|
||||
case BYTE:
|
||||
buffer.put((byte) size);
|
||||
break;
|
||||
case SHORT:
|
||||
buffer.putShort((short) size);
|
||||
break;
|
||||
}
|
||||
buffer.put((ByteBuffer) b.toByteBuffer().flip());
|
||||
session.queue((ByteBuffer) buffer.flip());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.game.system.SystemLogger;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.IoReadEvent;
|
||||
import core.net.IoSession;
|
||||
import core.net.amsc.ManagementServerState;
|
||||
import core.net.amsc.WorldCommunicator;
|
||||
import core.net.producer.MSEventProducer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles world registry read events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class RegistryReadEvent extends IoReadEvent {
|
||||
|
||||
/**
|
||||
* The event producer.
|
||||
*/
|
||||
private static final MSEventProducer PRODUCER = new MSEventProducer();
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RegistryReadEvent} {@code Object}.
|
||||
* @param session The session.
|
||||
* @param buffer The buffer to read.
|
||||
*/
|
||||
public RegistryReadEvent(IoSession session, ByteBuffer buffer) {
|
||||
super(session, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(IoSession session, ByteBuffer buffer) {
|
||||
int opcode = buffer.get() & 0xFF;
|
||||
switch (opcode) {
|
||||
case 0:
|
||||
WorldCommunicator.setState(ManagementServerState.NOT_AVAILABLE);
|
||||
SystemLogger.logErr("Failed registering world to AMS - [id=" + GameWorld.getSettings().getWorldId() + ", cause=World id out of bounds]!");
|
||||
break;
|
||||
case 1:
|
||||
session.setProducer(PRODUCER);
|
||||
WorldCommunicator.setState(ManagementServerState.AVAILABLE);
|
||||
SystemLogger.logInfo("Successfully registered world to AMS - [id=" + GameWorld.getSettings().getWorldId() + "]!");
|
||||
break;
|
||||
case 2:
|
||||
WorldCommunicator.setState(ManagementServerState.NOT_AVAILABLE);
|
||||
SystemLogger.logErr("Failed registering world to AMS - [id=" + GameWorld.getSettings().getWorldId() + ", cause=World id already in use]!");
|
||||
break;
|
||||
case 3:
|
||||
WorldCommunicator.setState(ManagementServerState.NOT_AVAILABLE);
|
||||
SystemLogger.logErr("Failed registering world to AMS - [id=" + GameWorld.getSettings().getWorldId() + ", cause=Exception in AMS]!");
|
||||
break;
|
||||
default:
|
||||
System.out.println("??" + opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package core.net.event;
|
||||
|
||||
import core.cache.misc.buffer.ByteBufferUtils;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.Constants;
|
||||
import core.net.IoSession;
|
||||
import core.net.IoWriteEvent;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles game world registry writing events.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class RegistryWriteEvent extends IoWriteEvent {
|
||||
|
||||
/**
|
||||
* The string check.
|
||||
*/
|
||||
private static final String CHECK = "12x4578f5g45hrdjiofed59898";
|
||||
|
||||
/**
|
||||
* Constructs a new {@code RegistryWriteEvent} {@code Object}.
|
||||
* @param session The I/O session.
|
||||
* @param context The writing context.
|
||||
*/
|
||||
public RegistryWriteEvent(IoSession session, Object context) {
|
||||
super(session, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IoSession session, Object context) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(128);
|
||||
buffer.put((byte) GameWorld.getSettings().getWorldId());
|
||||
buffer.putInt(Constants.REVISION);
|
||||
buffer.put((byte) GameWorld.getSettings().getCountryIndex());
|
||||
buffer.put((byte) (GameWorld.getSettings().isMembers() ? 1 : 0));
|
||||
buffer.put((byte) (GameWorld.getSettings().isPvp() ? 1 : 0));
|
||||
buffer.put((byte) (GameWorld.getSettings().isQuickChat() ? 1 : 0));
|
||||
buffer.put((byte) (GameWorld.getSettings().isLootshare() ? 1 : 0));
|
||||
ByteBufferUtils.putString(GameWorld.getSettings().getActivity(), buffer);
|
||||
buffer.put(CHECK.getBytes());
|
||||
session.queue((ByteBuffer) buffer.flip());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package core.net.lobby;
|
||||
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.repository.Repository;
|
||||
|
||||
/**
|
||||
* Represents a world's definition.
|
||||
* @author Dementhium development team.
|
||||
*
|
||||
*/
|
||||
public class WorldDefinition {
|
||||
|
||||
/**
|
||||
* The activity for this world.
|
||||
*/
|
||||
private final String activity;
|
||||
|
||||
/**
|
||||
* The coutry flag.
|
||||
*/
|
||||
private final int country;
|
||||
|
||||
/**
|
||||
* If the world is members.
|
||||
*/
|
||||
private final int flag;
|
||||
|
||||
/**
|
||||
* The ip-address for this world.
|
||||
*/
|
||||
private final String ip;
|
||||
|
||||
/**
|
||||
* The location.
|
||||
*/
|
||||
private final int location;
|
||||
|
||||
/**
|
||||
* The region.
|
||||
*/
|
||||
private final String region;
|
||||
|
||||
/**
|
||||
* The world's id.
|
||||
*/
|
||||
private final int worldId;
|
||||
|
||||
/**
|
||||
* The amount of players in this world.
|
||||
*/
|
||||
private int players;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WorldDefinition} {@code Object}.
|
||||
* @param worldId The world's id.
|
||||
* @param location The location.
|
||||
* @param flag If the world is members.
|
||||
* @param activity The activity for this world.
|
||||
* @param ip The IP-address.
|
||||
* @param region The region.
|
||||
* @param country The country flag.
|
||||
*/
|
||||
public WorldDefinition(int worldId, int location, int flag, String activity, String ip, String region, int country) {
|
||||
this.worldId = worldId;
|
||||
this.location = location;
|
||||
this.flag = flag;
|
||||
this.activity = activity;
|
||||
this.ip = ip;
|
||||
this.region = region;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the activity
|
||||
*/
|
||||
public String getActivity() {
|
||||
return activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the country
|
||||
*/
|
||||
public int getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the flag
|
||||
*/
|
||||
public int getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ip
|
||||
*/
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the location
|
||||
*/
|
||||
public int getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the region
|
||||
*/
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the worldId
|
||||
*/
|
||||
public int getWorldId() {
|
||||
return worldId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player count.
|
||||
* @return The player count.
|
||||
*/
|
||||
public int getPlayerCount() {
|
||||
if (worldId == GameWorld.getSettings().getWorldId()) {
|
||||
return Repository.getPlayers().size();
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the players.
|
||||
* @return the players
|
||||
*/
|
||||
public int getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the baplayers.
|
||||
* @param players the players to set.
|
||||
*/
|
||||
public void setPlayers(int players) {
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
package core.net.lobby;
|
||||
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.IoSession;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Handles the world list.
|
||||
* @author Emperor
|
||||
*
|
||||
*/
|
||||
public final class WorldList {
|
||||
|
||||
/**
|
||||
* The value for Australia.
|
||||
*/
|
||||
public static final int COUNTRY_AUSTRALIA = 16;
|
||||
|
||||
/**
|
||||
* The value for Belgium.
|
||||
*/
|
||||
public static final int COUNTRY_BELGIUM = 22;
|
||||
|
||||
/**
|
||||
* The value for Brazil.
|
||||
*/
|
||||
public static final int COUNTRY_BRAZIL = 31;
|
||||
|
||||
/**
|
||||
* The value for Canada.
|
||||
*/
|
||||
public static final int COUNTRY_CANADA = 38;
|
||||
|
||||
/**
|
||||
* The value for Denmark.
|
||||
*/
|
||||
public static final int COUNTRY_DENMARK = 58;
|
||||
|
||||
/**
|
||||
* The value for Finland.
|
||||
*/
|
||||
public static final int COUNTRY_FINLAND = 69;
|
||||
|
||||
/**
|
||||
* The value for Ireland.
|
||||
*/
|
||||
public static final int COUNTRY_IRELAND = 101;
|
||||
|
||||
/**
|
||||
* The value for Mexico.
|
||||
*/
|
||||
public static final int COUNTRY_MEXICO = 152;
|
||||
|
||||
/**
|
||||
* The value for the Netherlands.
|
||||
*/
|
||||
public static final int COUNTRY_NETHERLANDS = 161;
|
||||
|
||||
/**
|
||||
* The value for Norway.
|
||||
*/
|
||||
public static final int COUNTRY_NORWAY = 162;
|
||||
|
||||
/**
|
||||
* The value for Sweden.
|
||||
*/
|
||||
public static final int COUNTRY_SWEDEN = 191;
|
||||
|
||||
/**
|
||||
* The value for the UK.
|
||||
*/
|
||||
public static final int COUNTRY_UK = 77;
|
||||
|
||||
/**
|
||||
* The value for USA.
|
||||
*/
|
||||
public static final int COUNTRY_USA = 225;
|
||||
|
||||
/**
|
||||
* If the world is free to play.
|
||||
*/
|
||||
public static final int FLAG_NON_MEMBERS = 0;
|
||||
|
||||
/**
|
||||
* If the world is a members world.
|
||||
*/
|
||||
public static final int FLAG_MEMBERS = 1;
|
||||
|
||||
/**
|
||||
* If the world is a quick chat world
|
||||
*/
|
||||
public static final int FLAG_QUICK_CHAT = 2;
|
||||
|
||||
/**
|
||||
* If the world is a PvP-world.
|
||||
*/
|
||||
public static final int FLAG_PVP = 4;
|
||||
|
||||
/**
|
||||
* If the world is a lootshare world.
|
||||
*/
|
||||
public static final int FLAG_LOOTSHARE = 8;
|
||||
|
||||
/**
|
||||
* A list holding all the currently loaded worlds.
|
||||
*/
|
||||
private static final List<WorldDefinition> WORLD_LIST = new ArrayList<WorldDefinition>();
|
||||
|
||||
/**
|
||||
* The last update time stamp (in server ticks).
|
||||
*/
|
||||
private static int updateStamp = 0;
|
||||
|
||||
/**
|
||||
* Populates the world list.
|
||||
*/
|
||||
static {
|
||||
addWorld(new WorldDefinition(1, 0, FLAG_MEMBERS | FLAG_LOOTSHARE, "2009Scape Classic", "127.0.0.1", "Anywhere, USA", COUNTRY_USA));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a world to the world list.
|
||||
* @param def The world definitions.
|
||||
*/
|
||||
public static void addWorld(WorldDefinition def) {
|
||||
WORLD_LIST.add(def);
|
||||
flagUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet to update the world list in the lobby.
|
||||
* @return The {@code OutgoingPacket} to write.
|
||||
*/
|
||||
public static void sendUpdate(IoSession session, int updateStamp) {
|
||||
ByteBuffer buf = ByteBuffer.allocate(1024);
|
||||
buf.put((byte) 0);
|
||||
buf.putShort((short) 0);
|
||||
buf.put((byte) 1);
|
||||
IoBuffer buffer = new IoBuffer();
|
||||
if (updateStamp != WorldList.updateStamp) {
|
||||
buf.put((byte) 1); // Indicates an update occured.
|
||||
putWorldListinfo(buffer);
|
||||
} else {
|
||||
buf.put((byte) 0);
|
||||
}
|
||||
putPlayerInfo(buffer);
|
||||
if (buffer.toByteBuffer().position() > 0) {
|
||||
buf.put((ByteBuffer) buffer.toByteBuffer().flip());
|
||||
}
|
||||
buf.putShort(1, (short) (buf.position() - 3));
|
||||
session.queue((ByteBuffer) buf.flip());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the world configuration on the packet.
|
||||
* @param buffer The current packet.
|
||||
*/
|
||||
private static void putWorldListinfo(IoBuffer buffer) {
|
||||
buffer.putSmart(WORLD_LIST.size());
|
||||
putCountryInfo(buffer);
|
||||
buffer.putSmart(0);
|
||||
buffer.putSmart(WORLD_LIST.size());
|
||||
buffer.putSmart(WORLD_LIST.size());
|
||||
for (WorldDefinition w : WORLD_LIST) {
|
||||
buffer.putSmart(w.getWorldId());
|
||||
buffer.put(w.getLocation());
|
||||
buffer.putInt(w.getFlag());
|
||||
buffer.putJagString(w.getActivity());
|
||||
buffer.putJagString(w.getIp());
|
||||
}
|
||||
buffer.putInt(updateStamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the world status on the packet.
|
||||
* @param buffer The current packet.
|
||||
*/
|
||||
private static void putPlayerInfo(IoBuffer buffer) {
|
||||
for (WorldDefinition w : WORLD_LIST) {
|
||||
buffer.putSmart(w.getWorldId());
|
||||
buffer.putShort(w.getPlayerCount());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the countries for each world.
|
||||
* @param buffer The current packet.
|
||||
*/
|
||||
private static void putCountryInfo(IoBuffer buffer) {
|
||||
for (WorldDefinition w : WORLD_LIST) {
|
||||
buffer.putSmart(w.getCountry());
|
||||
buffer.putJagString(w.getRegion());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the updateStamp.
|
||||
* @return the updateStamp
|
||||
*/
|
||||
public static int getUpdateStamp() {
|
||||
return updateStamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the baupdateStamp.
|
||||
*/
|
||||
public static void flagUpdate() {
|
||||
WorldList.updateStamp = GameWorld.getTicks();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package core.net.packet;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public interface Context {
|
||||
|
||||
/**
|
||||
* Gets the node.
|
||||
* @return The node.
|
||||
*/
|
||||
public Player getPlayer();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package core.net.packet;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents an incoming packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public interface IncomingPacket {
|
||||
|
||||
/**
|
||||
* Decodes the incoming packet.
|
||||
* @param player The player.
|
||||
* @param opcode The opcode.
|
||||
* @param buffer The buffer.
|
||||
* @return The new buffer to send in response.
|
||||
*/
|
||||
public void decode(Player player, int opcode, IoBuffer buffer);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,638 @@
|
||||
package core.net.packet;
|
||||
|
||||
import core.cache.crypto.ISAACCipher;
|
||||
import core.cache.misc.buffer.ByteBufferUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Represents the buffer used for reading/writing packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class IoBuffer {
|
||||
|
||||
/**
|
||||
* The bit masks.
|
||||
*/
|
||||
private static final int[] BIT_MASK = new int[32];
|
||||
|
||||
/**
|
||||
* The packet size.
|
||||
*/
|
||||
private int packetSize;
|
||||
|
||||
/**
|
||||
* The opcode.
|
||||
*/
|
||||
private int opcode;
|
||||
|
||||
/**
|
||||
* The packet header.
|
||||
*/
|
||||
private final PacketHeader header;
|
||||
|
||||
/**
|
||||
* The byte buffer.
|
||||
*/
|
||||
private ByteBuffer buf;
|
||||
|
||||
/**
|
||||
* The bit position.
|
||||
*/
|
||||
private int bitPosition = 0;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoBuffer} {@code Object}.
|
||||
*/
|
||||
public IoBuffer() {
|
||||
this(-1, PacketHeader.NORMAL, ByteBuffer.allocate(2048));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoBuffer} {@code Object}.
|
||||
* @param opcode The opcode.
|
||||
*/
|
||||
public IoBuffer(int opcode) {
|
||||
this(opcode, PacketHeader.NORMAL, ByteBuffer.allocate(2048));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoBuffer} {@code Object}.
|
||||
* @param opcode The opcode.
|
||||
* @param header The packet header.
|
||||
*/
|
||||
public IoBuffer(int opcode, PacketHeader header) {
|
||||
this(opcode, header, ByteBuffer.allocate((1 << 16) + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IoBuffer} {@code Object}.
|
||||
* @param opcode The opcode.
|
||||
* @param header The packet header.
|
||||
* @param buf The byte buffer.
|
||||
*/
|
||||
public IoBuffer(int opcode, PacketHeader header, ByteBuffer buf) {
|
||||
this.opcode = opcode;
|
||||
this.header = header;
|
||||
this.buf = buf;
|
||||
}
|
||||
|
||||
static {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
BIT_MASK[i] = (1 << i) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer clear() {
|
||||
buf.clear();
|
||||
bitPosition = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer put(int val) {
|
||||
buf.put((byte) val);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param datas
|
||||
* @param offset
|
||||
* @param len
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putBytes(byte[] datas, int offset, int len) {
|
||||
for (int i = offset; i < len; i++) {
|
||||
put(datas[i]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final void getBytes(byte data[], int off, int len) {
|
||||
for (int k = off; k < len + off; k++) {
|
||||
data[k] = data[off++];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putA(int val) {
|
||||
buf.put((byte) (val + 128));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putC(int val) {
|
||||
buf.put((byte) -val);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putS(int val) {
|
||||
buf.put((byte) (128 - val));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putTri(int val) {
|
||||
buf.put((byte) (val >> 16));
|
||||
buf.put((byte) (val >> 8));
|
||||
buf.put((byte) val);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putShort(int val) {
|
||||
buf.putShort((short) val);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putLEShort(int val) {
|
||||
buf.put((byte) val);
|
||||
buf.put((byte) (val >> 8));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putShortA(int val) {
|
||||
buf.put((byte) (val >> 8));
|
||||
buf.put((byte) (val + 128));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putLEShortA(int val) {
|
||||
buf.put((byte) (val + 128));
|
||||
buf.put((byte) (val >> 8));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putInt(int val) {
|
||||
buf.putInt(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putLEInt(int val) {
|
||||
buf.put((byte) val);
|
||||
buf.put((byte) (val >> 8));
|
||||
buf.put((byte) (val >> 16));
|
||||
buf.put((byte) (val >> 24));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putIntA(int val) {
|
||||
buf.put((byte) (val >> 8));
|
||||
buf.put((byte) val);
|
||||
buf.put((byte) (val >> 24));
|
||||
buf.put((byte) (val >> 16));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putIntB(int val) {
|
||||
buf.put((byte) (val >> 16));
|
||||
buf.put((byte) (val >> 24));
|
||||
buf.put((byte) val);
|
||||
buf.put((byte) (val >> 8));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putLong(long val) {
|
||||
buf.putLong(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putSmart(int val) {
|
||||
if (val > Byte.MAX_VALUE) {
|
||||
buf.putShort((short) (val + 32768));
|
||||
} else {
|
||||
buf.put((byte) val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putIntSmart(int val) {
|
||||
if (val > Short.MAX_VALUE) {
|
||||
buf.putInt(val + 32768);
|
||||
} else {
|
||||
buf.putShort((short) val);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putString(String val) {
|
||||
buf.put(val.getBytes());
|
||||
buf.put((byte) 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putJagString(String val) {
|
||||
buf.put((byte) 0);
|
||||
buf.put(val.getBytes());
|
||||
buf.put((byte) 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putJagString2(String val) {
|
||||
byte[] packed = new byte[256];
|
||||
int length = ByteBufferUtils.packGJString2(0, packed, val);
|
||||
buf.put((byte) 0).put(packed, 0, length).put((byte) 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer put(byte[] val) {
|
||||
buf.put(val);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a byte array as byte A in reverse.
|
||||
* @param data The data to put.
|
||||
* @param start The start index.
|
||||
* @param offset The offset.
|
||||
*/
|
||||
public void putReverseA(byte[] data, int start, int offset) {
|
||||
for (int i = offset + start; i >= start; i--) {
|
||||
putA(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a byte array as byte A in reverse.
|
||||
* @param data The data to put.
|
||||
* @param start The start index.
|
||||
* @param offset The offset.
|
||||
*/
|
||||
public void putReverse(byte[] data, int start, int offset) {
|
||||
for (int i = offset + start; i >= start; i--) {
|
||||
put(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param numBits
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putBits(int numBits, int value) {
|
||||
int bytePos = getBitPosition() >> 3;
|
||||
int bitOffset = 8 - (getBitPosition() & 7);
|
||||
bitPosition += numBits;
|
||||
for (; numBits > bitOffset; bitOffset = 8) {
|
||||
byte b = buf.get(bytePos);
|
||||
buf.put(bytePos, b &= ~BIT_MASK[bitOffset]);
|
||||
buf.put(bytePos++, b |= value >> numBits - bitOffset & BIT_MASK[bitOffset]);
|
||||
numBits -= bitOffset;
|
||||
}
|
||||
byte b = buf.get(bytePos);
|
||||
if (numBits == bitOffset) {
|
||||
buf.put(bytePos, b &= ~BIT_MASK[bitOffset]);
|
||||
buf.put(bytePos, b |= value & BIT_MASK[bitOffset]);
|
||||
} else {
|
||||
buf.put(bytePos, b &= ~(BIT_MASK[numBits] << bitOffset - numBits));
|
||||
buf.put(bytePos, b |= (value & BIT_MASK[numBits]) << bitOffset - numBits);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param buffer
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer put(IoBuffer buffer) {
|
||||
buffer.toByteBuffer().flip();
|
||||
buf.put(buffer.toByteBuffer());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param buffer
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer putA(IoBuffer buffer) {
|
||||
buffer.toByteBuffer().flip();
|
||||
while (buffer.toByteBuffer().hasRemaining()) {
|
||||
putA(buffer.toByteBuffer().get());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param buffer
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer put(ByteBuffer buffer) {
|
||||
buf.put(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer setBitAccess() {
|
||||
bitPosition = buf.position() * 8;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer setByteAccess() {
|
||||
buf.position((getBitPosition() + 7) / 8);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int get() {
|
||||
return buf.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getA() {
|
||||
return (buf.get() & 0xFF) - 128;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getC() {
|
||||
return -buf.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getS() {
|
||||
return 128 - (buf.get() & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getTri() {
|
||||
return ((buf.get() << 16) & 0xFF) | ((buf.get() << 8) & 0xFF) | (buf.get() & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getShort() {
|
||||
return buf.getShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getLEShort() {
|
||||
return (buf.get() & 0xFF) | ((buf.get() & 0xFF) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getShortA() {
|
||||
return ((buf.get() & 0xFF) << 8) | (buf.get() - 128 & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getLEShortA() {
|
||||
return (buf.get() - 128 & 0xFF) | ((buf.get() & 0xFF) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getInt() {
|
||||
return buf.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getLEInt() {
|
||||
return (buf.get() & 0xFF) + ((buf.get() & 0xFF) << 8) + ((buf.get() & 0xFF) << 16) + ((buf.get() & 0xFF) << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getIntA() {
|
||||
return ((buf.get() & 0xFF) << 8) + (buf.get() & 0xFF) + ((buf.get() & 0xFF) << 24) + ((buf.get() & 0xFF) << 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getIntB() {
|
||||
return ((buf.get() & 0xFF) << 16) + ((buf.get() & 0xFF) << 24) + (buf.get() & 0xFF) + ((buf.get() & 0xFF) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public long getLongL() {
|
||||
long first = getIntB();
|
||||
long second = getIntB();
|
||||
if (second < 0)
|
||||
second = second & 0xffffffffL;
|
||||
return (first << -41780448) + second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public long getLong() {
|
||||
return buf.getLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getSmart() {
|
||||
int peek = buf.get(buf.position());
|
||||
if (peek <= Byte.MAX_VALUE) {
|
||||
return buf.get() & 0xFF;
|
||||
}
|
||||
return (buf.getShort() & 0xFFFF) - 32768;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int getIntSmart() {
|
||||
int peek = buf.getShort(buf.position());
|
||||
if (peek <= Short.MAX_VALUE) {
|
||||
return buf.getShort() & 0xFFFF;
|
||||
}
|
||||
return (buf.getInt() & 0xFFFFFFFF) - 32768;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getString() {
|
||||
return ByteBufferUtils.getString(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getJagString() {
|
||||
buf.get();
|
||||
return ByteBufferUtils.getString(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param is
|
||||
* @param offset
|
||||
* @param length
|
||||
* @return
|
||||
*/
|
||||
public IoBuffer getReverseA(byte[] is, int offset, int length) {
|
||||
for (int i = (offset + length - 1); i >= offset; i--) {
|
||||
is[i] = (byte) (buf.get() - 128);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void cypherOpcode(ISAACCipher cipher){
|
||||
this.opcode += (byte)cipher.getNextValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public ByteBuffer toByteBuffer() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int opcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public int readableBytes() {
|
||||
return buf.capacity() - buf.remaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public PacketHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public byte[] array() {
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the packetSize.
|
||||
*/
|
||||
public int getPacketSize() {
|
||||
return packetSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param packetSize the packetSize to set.
|
||||
*/
|
||||
public void setPacketSize(int packetSize) {
|
||||
this.packetSize = packetSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bitPosition.
|
||||
* @return The bitPosition.
|
||||
*/
|
||||
public int getBitPosition() {
|
||||
return bitPosition;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package core.net.packet;
|
||||
|
||||
/**
|
||||
* Represents an outgoing packet.
|
||||
* @author Emperor
|
||||
* @param <T> The context type.
|
||||
*/
|
||||
public interface OutgoingPacket<T extends Context> {
|
||||
|
||||
/**
|
||||
* Sends the packet.
|
||||
* @param context The context.
|
||||
*/
|
||||
public void send(T context);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package core.net.packet;
|
||||
|
||||
/**
|
||||
* Represents the types of packet headers.
|
||||
* @author Emperor
|
||||
*/
|
||||
public enum PacketHeader {
|
||||
|
||||
/**
|
||||
* The normal packet header.
|
||||
*/
|
||||
NORMAL,
|
||||
|
||||
/**
|
||||
* The byte packet header.
|
||||
*/
|
||||
BYTE,
|
||||
|
||||
/**
|
||||
* The short packet header.
|
||||
*/
|
||||
SHORT;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package core.net.packet;
|
||||
|
||||
import core.game.system.SystemLogger;
|
||||
import core.net.packet.in.*;
|
||||
import core.net.packet.out.*;
|
||||
import core.net.packet.out.GrandExchangePacket;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The packet repository.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class PacketRepository {
|
||||
|
||||
/**
|
||||
* The outgoing packets mapping.
|
||||
*/
|
||||
private final static Map<Class<?>, OutgoingPacket<? extends Context>> OUTGOING_PACKETS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The incoming packets mapping.
|
||||
*/
|
||||
private final static Map<Integer, IncomingPacket> INCOMING_PACKETS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Populate the mappings.
|
||||
*/
|
||||
static {
|
||||
OUTGOING_PACKETS.put(LoginPacket.class, new LoginPacket()); //
|
||||
OUTGOING_PACKETS.put(UpdateSceneGraph.class, new UpdateSceneGraph()); //
|
||||
OUTGOING_PACKETS.put(WindowsPane.class, new WindowsPane()); //
|
||||
OUTGOING_PACKETS.put(Interface.class, new Interface()); //
|
||||
OUTGOING_PACKETS.put(SkillLevel.class, new SkillLevel()); //
|
||||
OUTGOING_PACKETS.put(Config.class, new Config()); //
|
||||
OUTGOING_PACKETS.put(AccessMask.class, new AccessMask()); //
|
||||
OUTGOING_PACKETS.put(GameMessage.class, new GameMessage()); //
|
||||
OUTGOING_PACKETS.put(RunScriptPacket.class, new RunScriptPacket()); //
|
||||
OUTGOING_PACKETS.put(RunEnergy.class, new RunEnergy()); //
|
||||
OUTGOING_PACKETS.put(ContainerPacket.class, new ContainerPacket()); //
|
||||
OUTGOING_PACKETS.put(StringPacket.class, new StringPacket()); //
|
||||
OUTGOING_PACKETS.put(Logout.class, new Logout()); //
|
||||
OUTGOING_PACKETS.put(CloseInterface.class, new CloseInterface()); //
|
||||
OUTGOING_PACKETS.put(AnimateInterface.class, new AnimateInterface()); //
|
||||
OUTGOING_PACKETS.put(DisplayModel.class, new DisplayModel()); //
|
||||
OUTGOING_PACKETS.put(InterfaceConfig.class, new InterfaceConfig()); //
|
||||
OUTGOING_PACKETS.put(PingPacket.class, new PingPacket()); //
|
||||
OUTGOING_PACKETS.put(UpdateAreaPosition.class, new UpdateAreaPosition()); //
|
||||
OUTGOING_PACKETS.put(ConstructObject.class, new ConstructObject()); //
|
||||
OUTGOING_PACKETS.put(ClearObject.class, new ClearObject()); //
|
||||
OUTGOING_PACKETS.put(HintIcon.class, new HintIcon()); //
|
||||
OUTGOING_PACKETS.put(ClearMinimapFlag.class, new ClearMinimapFlag()); //
|
||||
OUTGOING_PACKETS.put(InteractionOption.class, new InteractionOption()); //
|
||||
OUTGOING_PACKETS.put(SetWalkOption.class, new SetWalkOption()); //
|
||||
OUTGOING_PACKETS.put(MinimapState.class, new MinimapState()); //
|
||||
OUTGOING_PACKETS.put(ConstructGroundItem.class, new ConstructGroundItem()); //
|
||||
OUTGOING_PACKETS.put(ClearGroundItem.class, new ClearGroundItem()); //
|
||||
OUTGOING_PACKETS.put(RepositionChild.class, new RepositionChild()); //
|
||||
OUTGOING_PACKETS.put(PositionedGraphic.class, new PositionedGraphic()); //
|
||||
OUTGOING_PACKETS.put(SystemUpdatePacket.class, new SystemUpdatePacket()); //
|
||||
OUTGOING_PACKETS.put(CameraViewPacket.class, new CameraViewPacket()); //
|
||||
OUTGOING_PACKETS.put(MusicPacket.class, new MusicPacket()); //
|
||||
OUTGOING_PACKETS.put(AudioPacket.class, new AudioPacket()); //
|
||||
OUTGOING_PACKETS.put(GrandExchangePacket.class, new GrandExchangePacket()); //
|
||||
OUTGOING_PACKETS.put(BuildDynamicScene.class, new BuildDynamicScene()); //
|
||||
OUTGOING_PACKETS.put(AnimateObjectPacket.class, new AnimateObjectPacket()); //
|
||||
OUTGOING_PACKETS.put(ClearRegionChunk.class, new ClearRegionChunk()); //
|
||||
OUTGOING_PACKETS.put(ContactPackets.class, new ContactPackets()); //
|
||||
OUTGOING_PACKETS.put(CommunicationMessage.class, new CommunicationMessage()); //
|
||||
OUTGOING_PACKETS.put(UpdateClanChat.class, new UpdateClanChat()); //
|
||||
OUTGOING_PACKETS.put(UpdateGroundItemAmount.class, new UpdateGroundItemAmount()); //
|
||||
OUTGOING_PACKETS.put(WeightUpdate.class, new WeightUpdate()); //
|
||||
OUTGOING_PACKETS.put(UpdateRandomFile.class, new UpdateRandomFile()); //
|
||||
OUTGOING_PACKETS.put(InstancedLocationUpdate.class, new InstancedLocationUpdate()); //
|
||||
OUTGOING_PACKETS.put(CSConfigPacket.class, new CSConfigPacket()); //
|
||||
INCOMING_PACKETS.put(22, new ClientFocusPacket());
|
||||
INCOMING_PACKETS.put(93, new PingPacketHandler());
|
||||
INCOMING_PACKETS.put(44, new CommandPacket());
|
||||
INCOMING_PACKETS.put(237, new ChatPacket());
|
||||
INCOMING_PACKETS.put(21, new CameraMovementPacket());
|
||||
INCOMING_PACKETS.put(75, new MouseClickPacket());
|
||||
INCOMING_PACKETS.put(243, new DisplayUpdatePacket());
|
||||
INCOMING_PACKETS.put(177, new UpdateInterfaceCounter());
|
||||
INCOMING_PACKETS.put(4, new DummyPacket());
|
||||
INCOMING_PACKETS.put(245, new IdlePacketHandler());
|
||||
INCOMING_PACKETS.put(111, new core.net.packet.in.GrandExchangePacket());
|
||||
IncomingPacket packet = new WalkPacket();
|
||||
INCOMING_PACKETS.put(39, packet);
|
||||
INCOMING_PACKETS.put(77, packet);
|
||||
INCOMING_PACKETS.put(215, packet);
|
||||
packet = new ItemActionPacket();
|
||||
INCOMING_PACKETS.put(134, packet);//item on object
|
||||
INCOMING_PACKETS.put(115, packet);//on npc
|
||||
INCOMING_PACKETS.put(27, packet);//item on item
|
||||
INCOMING_PACKETS.put(248, packet);//on player
|
||||
INCOMING_PACKETS.put(101,new ItemOnGroundItemPacket()); //Item on Ground Item
|
||||
INCOMING_PACKETS.put(3, packet = new InteractionPacket());
|
||||
INCOMING_PACKETS.put(180, packet);//Player interact options v
|
||||
INCOMING_PACKETS.put(68, packet);
|
||||
INCOMING_PACKETS.put(71, packet);
|
||||
INCOMING_PACKETS.put(114, packet);
|
||||
INCOMING_PACKETS.put(175, packet);//Player interact options ^
|
||||
INCOMING_PACKETS.put(30, packet);
|
||||
INCOMING_PACKETS.put(78, packet);
|
||||
INCOMING_PACKETS.put(148, packet);
|
||||
INCOMING_PACKETS.put(218, packet);
|
||||
INCOMING_PACKETS.put(84, packet);
|
||||
INCOMING_PACKETS.put(170, packet);
|
||||
INCOMING_PACKETS.put(254, packet);
|
||||
INCOMING_PACKETS.put(194, packet);
|
||||
INCOMING_PACKETS.put(66, packet);
|
||||
INCOMING_PACKETS.put(33, packet);
|
||||
INCOMING_PACKETS.put(247, packet);
|
||||
INCOMING_PACKETS.put(156, packet = new ActionButtonPacket()); //Item V
|
||||
INCOMING_PACKETS.put(55, packet);
|
||||
INCOMING_PACKETS.put(153, packet);
|
||||
INCOMING_PACKETS.put(161, packet);
|
||||
INCOMING_PACKETS.put(135, packet); //^
|
||||
INCOMING_PACKETS.put(81, packet);
|
||||
INCOMING_PACKETS.put(184, packet);//close interface
|
||||
INCOMING_PACKETS.put(155, packet); //Interface V
|
||||
INCOMING_PACKETS.put(196, packet);
|
||||
INCOMING_PACKETS.put(124, packet);
|
||||
INCOMING_PACKETS.put(199, packet);
|
||||
INCOMING_PACKETS.put(234, packet);
|
||||
INCOMING_PACKETS.put(168, packet);
|
||||
INCOMING_PACKETS.put(166, packet);
|
||||
INCOMING_PACKETS.put(64, packet);
|
||||
INCOMING_PACKETS.put(53, packet);
|
||||
INCOMING_PACKETS.put(9, packet); //^
|
||||
INCOMING_PACKETS.put(132, packet); //Dialogue
|
||||
INCOMING_PACKETS.put(10, packet); //logout
|
||||
INCOMING_PACKETS.put(206, packet);//operate
|
||||
INCOMING_PACKETS.put(72, packet = new ExaminePacket());
|
||||
INCOMING_PACKETS.put(92, packet);
|
||||
INCOMING_PACKETS.put(94, packet);
|
||||
/*INCOMING_PACKETS.put(57, packet);
|
||||
INCOMING_PACKETS.put(34, packet);
|
||||
INCOMING_PACKETS.put(213, packet);*/
|
||||
//INCOMING_PACKETS.put(69, packet);
|
||||
//packet 98 - 530 settings interface
|
||||
INCOMING_PACKETS.put(104, packet = new ClanPacketHandler());
|
||||
INCOMING_PACKETS.put(188, packet);
|
||||
INCOMING_PACKETS.put(162, packet);
|
||||
INCOMING_PACKETS.put(157, new ChatSettingsPacket());
|
||||
INCOMING_PACKETS.put(244, packet = new RunScriptPacketHandler());
|
||||
INCOMING_PACKETS.put(23, packet);
|
||||
INCOMING_PACKETS.put(65, packet);
|
||||
INCOMING_PACKETS.put(110, new RegionChangePacket());
|
||||
INCOMING_PACKETS.put(195, packet = new InterfaceUseOnPacket());
|
||||
INCOMING_PACKETS.put(239, packet);
|
||||
INCOMING_PACKETS.put(73, packet);
|
||||
INCOMING_PACKETS.put(253, packet);
|
||||
INCOMING_PACKETS.put(233, packet);
|
||||
INCOMING_PACKETS.put(231, packet = new SlotSwitchPacket());
|
||||
INCOMING_PACKETS.put(79, packet);
|
||||
INCOMING_PACKETS.put(167, new QuickChatPacketHandler());
|
||||
INCOMING_PACKETS.put(201, packet = new CommunicationPacket());
|
||||
INCOMING_PACKETS.put(120, packet);
|
||||
INCOMING_PACKETS.put(57, packet);
|
||||
INCOMING_PACKETS.put(34, packet);
|
||||
INCOMING_PACKETS.put(213, packet);
|
||||
INCOMING_PACKETS.put(99, packet = new ReportAbusePacket());
|
||||
INCOMING_PACKETS.put(98, packet = new MapClosedPacket()); // this packet is sent when the world map is closed by the client
|
||||
INCOMING_PACKETS.put(137,packet = new MusicPacketHandler()); //this packet is received when the client stops playing a song
|
||||
// INCOMING_PACKETS.put(77, packet);
|
||||
// INCOMING_PACKETS.put(191, packet);
|
||||
// INCOMING_PACKETS.put(139, packet);
|
||||
// INCOMING_PACKETS.put(251, packet);
|
||||
// INCOMING_PACKETS.put(55, packet);
|
||||
|
||||
//Packet 22 is sent on focus gain/loss
|
||||
//packet 177 is sent when opening/closing interfaces
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a new packet.
|
||||
* @param clazz The class of the outgoing packet to send.
|
||||
* @param context The context.
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static void send(Class<? extends OutgoingPacket> clazz, Context context) {
|
||||
OutgoingPacket p = OUTGOING_PACKETS.get(clazz);
|
||||
if (p == null) {
|
||||
SystemLogger.logErr("Invalid outgoing packet [handler=" + clazz + ", context=" + context + "].");
|
||||
return;
|
||||
}
|
||||
if(!context.getPlayer().isArtificial())
|
||||
p.send(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an incoming packet.
|
||||
* @param opcode The opcode.
|
||||
* @return The incoming packet.
|
||||
*/
|
||||
public static IncomingPacket getIncoming(int opcode) {
|
||||
return INCOMING_PACKETS.get(opcode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The access mask context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class AccessMaskContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The access mask id.
|
||||
*/
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* The child id.
|
||||
*/
|
||||
private int childId;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private int interfaceId;
|
||||
|
||||
/**
|
||||
* The offset.
|
||||
*/
|
||||
private int offset;
|
||||
|
||||
/**
|
||||
* The length.
|
||||
*/
|
||||
private int length;
|
||||
|
||||
/**
|
||||
* Construct a new {@code AccessMaskContext} {@code Object}.
|
||||
* @param player
|
||||
* @param id
|
||||
* @param childId
|
||||
* @param interfaceId
|
||||
* @param offset
|
||||
* @param length
|
||||
*/
|
||||
public AccessMaskContext(Player player, int id, int childId, int interfaceId, int offset, int length) {
|
||||
this.player = player;
|
||||
this.id = id;
|
||||
this.childId = childId;
|
||||
this.interfaceId = interfaceId;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms this access mask context into a new instance with the player
|
||||
* instance and id value changed.
|
||||
* @param player The player to set.
|
||||
* @param id The id to set.
|
||||
* @return The access mask context.
|
||||
*/
|
||||
public AccessMaskContext transform(Player player, int id) {
|
||||
return new AccessMaskContext(player, id, childId, interfaceId, offset, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player.
|
||||
* @param player The player.
|
||||
* @return This context instance.
|
||||
*/
|
||||
public Context setPlayer(Player player) {
|
||||
this.player = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the access mask id.
|
||||
* @return The access mask.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the child id.
|
||||
* @return The child id.
|
||||
*/
|
||||
public int getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface id.
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset.
|
||||
* @return The offset.
|
||||
*/
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length.
|
||||
* @return The length.
|
||||
*/
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The animate interface context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class AnimateInterfaceContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The animation id.
|
||||
*/
|
||||
private int animationId;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private int interfaceId;
|
||||
|
||||
/**
|
||||
* The child id.
|
||||
*/
|
||||
private int childId;
|
||||
|
||||
/**
|
||||
* Construct a new {@code AnimateInterfaceContext} {@code Object}.
|
||||
* @param player The player reference.
|
||||
* @param animationId The animation id.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
*/
|
||||
public AnimateInterfaceContext(Player player, int animationId, int interfaceId, int childId) {
|
||||
this.player = player;
|
||||
this.animationId = animationId;
|
||||
this.interfaceId = interfaceId;
|
||||
this.childId = childId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the animation id.
|
||||
* @return The animation id.
|
||||
*/
|
||||
public int getAnimationId() {
|
||||
return animationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface id.
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the child id.
|
||||
* @return The child id.
|
||||
*/
|
||||
public int getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the context of animating an object.
|
||||
* @author Emperor
|
||||
* @author 'Vexia
|
||||
* @date 10/11/2013
|
||||
*/
|
||||
public class AnimateObjectContext implements Context {
|
||||
|
||||
/**
|
||||
* Represents the player of the context.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Represents the animation to use.
|
||||
*/
|
||||
private final Animation animation;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AnimateObjectContext} {@code Object}.
|
||||
* @param player the player.
|
||||
* @param animation the animation.
|
||||
*/
|
||||
public AnimateObjectContext(Player player, Animation animation) {
|
||||
this.player = player;
|
||||
this.animation = animation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation.
|
||||
* @return The animation.
|
||||
*/
|
||||
public Animation getAnimation() {
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Handles the area position update packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class AreaPositionContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The location.
|
||||
*/
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* The offset x-coordinate.
|
||||
*/
|
||||
private final int offsetX;
|
||||
|
||||
/**
|
||||
* The offset y-coordinate.
|
||||
*/
|
||||
private final int offsetY;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code AreaPositionContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param location The location.
|
||||
* @param offsetX The offset x-coordinate.
|
||||
* @param offsetY The offset y-coordinate.
|
||||
*/
|
||||
public AreaPositionContext(Player player, Location location, int offsetX, int offsetY) {
|
||||
this.player = player;
|
||||
this.location = location;
|
||||
this.offsetX = offsetX;
|
||||
this.offsetY = offsetY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location.
|
||||
* @return The location.
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offsetX.
|
||||
* @return The offsetX.
|
||||
*/
|
||||
public int getOffsetX() {
|
||||
return offsetX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the offsetY.
|
||||
* @return The offsetY.
|
||||
*/
|
||||
public int getOffsetY() {
|
||||
return offsetY;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the build item packet context, <br> which is used for
|
||||
* construct/clear item outgoing packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class BuildItemContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The item to send.
|
||||
*/
|
||||
private final Item item;
|
||||
|
||||
/**
|
||||
* The old item amount.
|
||||
*/
|
||||
private final int oldAmount;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BuildObjectContext} {@code Object}.
|
||||
* @param player The player
|
||||
* @param item The item to send.
|
||||
*/
|
||||
public BuildItemContext(Player player, Item item) {
|
||||
this(player, item, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BuildObjectContext} {@code Object}.
|
||||
* @param player The player
|
||||
* @param item The item to send.
|
||||
* @param oldAmount The old item amount.
|
||||
*/
|
||||
public BuildItemContext(Player player, Item item, int oldAmount) {
|
||||
this.player = player;
|
||||
this.item = item;
|
||||
this.oldAmount = oldAmount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item.
|
||||
* @return The item.
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the oldAmount.
|
||||
* @return The oldAmount.
|
||||
*/
|
||||
public int getOldAmount() {
|
||||
return oldAmount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.object.GameObject;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the build object packet context, <br> which is used for
|
||||
* construct/clear object outgoing packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class BuildObjectContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The list of game objects to send.
|
||||
*/
|
||||
private final GameObject gameObject;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code BuildObjectContext} {@code Object}.
|
||||
* @param player The player
|
||||
* @param gameObject the game object to send.
|
||||
*/
|
||||
public BuildObjectContext(Player player, GameObject gameObject) {
|
||||
this.player = player;
|
||||
this.gameObject = gameObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the gameObject.
|
||||
* @return The gameObject.
|
||||
*/
|
||||
public GameObject getGameObject() {
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The context for ClientScript configurations.
|
||||
*
|
||||
* @author Torchic
|
||||
*/
|
||||
public class CSConfigContext implements Context {
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The value
|
||||
*/
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* The id.
|
||||
*/
|
||||
private int id;
|
||||
private final Object[] parameters;
|
||||
private final String types;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new {@Code CSConfigContext} {@Code Object}
|
||||
* @param player The player.
|
||||
* @param id The id.
|
||||
* @param value The config value.
|
||||
* @param parameters
|
||||
* @param types
|
||||
*/
|
||||
public CSConfigContext(Player player, int id, int value, String types, Object[] parameters) {
|
||||
this.player = player;
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
this.parameters = parameters;
|
||||
this.types = types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player.
|
||||
* @param player The player.
|
||||
* @return This context instance.
|
||||
*/
|
||||
public Context setPlayer(Player player) {
|
||||
this.player = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config value.
|
||||
* @return The config value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config id.
|
||||
* @return The config id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
||||
public Object[] getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.SystemLogger;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents a camera context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class CameraContext implements Context {
|
||||
|
||||
|
||||
/**
|
||||
* Represents the camera types used for determining which packet to send.
|
||||
* @author Emperor
|
||||
*/
|
||||
public static enum CameraType {
|
||||
POSITION(154),
|
||||
ROTATION(125),
|
||||
SET(187), SHAKE(27), RESET(24);
|
||||
|
||||
/**
|
||||
* The opcode.
|
||||
*/
|
||||
private final int opcode;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CameraContext} {@Code Object}.
|
||||
* @param opcode The opcode.
|
||||
*/
|
||||
private CameraType(int opcode) {
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet opcode.
|
||||
* @return The opcode.
|
||||
*/
|
||||
public int opcode() {
|
||||
return opcode;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rotateCamera(Player p, int x, int y, int z, int angle) { MessageBuilder
|
||||
* bldr = new MessageBuilder(26); bldr.writeByte(y); //idk
|
||||
* bldr.writeByte(x); //idk bldr.writeLEShortA(z >>> 2); //idk
|
||||
* bldr.writeByte(0); // speed :S bldr.writeByteS(100);
|
||||
*/
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The camera type.
|
||||
*/
|
||||
private final CameraType type;
|
||||
|
||||
/**
|
||||
* x The (local) x-coordinate of the camera.
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The (local) y-coordinate of the camera.
|
||||
*/
|
||||
private final int y;
|
||||
|
||||
/**
|
||||
* The height.
|
||||
*/
|
||||
private final int height;
|
||||
|
||||
/**
|
||||
* The zoom speed.
|
||||
*/
|
||||
private final int zoomSpeed;
|
||||
|
||||
/**
|
||||
* The speed.
|
||||
*/
|
||||
private final int speed;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code CameraContext} {@Code Object}.
|
||||
* @param player The player.
|
||||
* @param type The camera type.
|
||||
* @param x The x-coordinate of the camera.
|
||||
* @param y The y-coordinate of the camera.
|
||||
* @param height The height.
|
||||
* @param zoomSpeed The zoom speed.
|
||||
* @param speed The speed.
|
||||
*/
|
||||
public CameraContext(Player player, CameraType type, int x, int y, int height, int speed, int zoomSpeed) {
|
||||
this.player = player;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.height = height;
|
||||
this.speed = speed;
|
||||
this.zoomSpeed = zoomSpeed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to transform a camera context.
|
||||
* @param x the x.
|
||||
* @param y the y.
|
||||
* @return the new context.
|
||||
*/
|
||||
public CameraContext transform(final Player player, final int x, final int y) {
|
||||
return new CameraContext(player, type, this.x + x, this.y + y, height, speed, zoomSpeed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method used to transform the context.
|
||||
* @param heightOffset the height offset.
|
||||
* @return the new context.
|
||||
*/
|
||||
public CameraContext transform(final int heightOffset) {
|
||||
return new CameraContext(player, type, x, y, height + heightOffset, speed, zoomSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type.
|
||||
* @return The type.
|
||||
*/
|
||||
public CameraType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x.
|
||||
* @return The x.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y.
|
||||
* @return The y.
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height.
|
||||
* @return The height.
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the speed.
|
||||
* @return The speed.
|
||||
*/
|
||||
public int getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the zoomSpeed.
|
||||
* @return The zoomSpeed.
|
||||
*/
|
||||
public int getZoomSpeed() {
|
||||
return zoomSpeed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* A context implementation used for the interface child repositioning packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ChildPositionContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private final int interfaceId;
|
||||
|
||||
/**
|
||||
* The child id.
|
||||
*/
|
||||
private final int childId;
|
||||
|
||||
/**
|
||||
* The new position of the child.
|
||||
*/
|
||||
private final Point position;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ChildPositionContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The id of the child to reposition.
|
||||
* @param positionX The new x-position.
|
||||
* @param positionY The new y-position.
|
||||
*/
|
||||
public ChildPositionContext(Player player, int interfaceId, int childId, int positionX, int positionY) {
|
||||
this.player = player;
|
||||
this.interfaceId = interfaceId;
|
||||
this.childId = childId;
|
||||
this.position = new Point(positionX, positionY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interfaceId.
|
||||
* @return The interfaceId.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the childId.
|
||||
* @return The childId.
|
||||
*/
|
||||
public int getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position.
|
||||
* @return The position.
|
||||
*/
|
||||
public Point getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.communication.ClanRepository;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The packet context for clan-related outgoing packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ClanContext implements Context {
|
||||
|
||||
/**
|
||||
* The player
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The clan instance.
|
||||
*/
|
||||
private final ClanRepository clan;
|
||||
|
||||
/**
|
||||
* If the player is leaving the clan.
|
||||
*/
|
||||
private final boolean leave;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ClanContext} {@code Object}.
|
||||
* @param player the player.
|
||||
* @param clan the clan.
|
||||
* @param leave If the player is leaving the clan.
|
||||
*/
|
||||
public ClanContext(Player player, ClanRepository clan, boolean leave) {
|
||||
this.player = player;
|
||||
this.clan = clan;
|
||||
this.leave = leave;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clan.
|
||||
* @return The clan.
|
||||
*/
|
||||
public ClanRepository getClan() {
|
||||
return clan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the leave.
|
||||
* @return The leave.
|
||||
*/
|
||||
public boolean isLeave() {
|
||||
return leave;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.RegionChunk;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The packet context for the clear region chunk outgoing packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ClearChunkContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The region chunk to clear.
|
||||
*/
|
||||
private final RegionChunk chunk;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ClearChunkContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param chunk The chunk to clear.
|
||||
*/
|
||||
public ClearChunkContext(Player player, RegionChunk chunk) {
|
||||
this.player = player;
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk.
|
||||
* @return The chunk.
|
||||
*/
|
||||
public RegionChunk getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The config packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class ConfigContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The config id.
|
||||
*/
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* The config value.
|
||||
*/
|
||||
private int value;
|
||||
|
||||
/**
|
||||
* If the config is a cs2-config.
|
||||
*/
|
||||
private boolean cs2;
|
||||
|
||||
/**
|
||||
* Construct a new {@code ConfigContext} {@code Object}.
|
||||
* @param player The player reference.
|
||||
* @param id The config id.
|
||||
* @param value The config value.
|
||||
*/
|
||||
public ConfigContext(Player player, int id, int value) {
|
||||
this(player, id, value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code ConfigContext} {@code Object}.
|
||||
* @param player The player reference.
|
||||
* @param id The config id.
|
||||
* @param value The config value.
|
||||
*/
|
||||
public ConfigContext(Player player, int id, int value, boolean cs2) {
|
||||
this.player = player;
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
this.cs2 = cs2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player.
|
||||
* @param player The player.
|
||||
* @return This context instance.
|
||||
*/
|
||||
public Context setPlayer(Player player) {
|
||||
this.player = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config id.
|
||||
* @return The config id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config value.
|
||||
* @return The config value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cs2.
|
||||
* @return The cs2.
|
||||
*/
|
||||
public boolean isCs2() {
|
||||
return cs2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The packet context for the contact packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ContactContext implements Context {
|
||||
|
||||
/**
|
||||
* The update communication server state type.
|
||||
*/
|
||||
public static final int UPDATE_STATE_TYPE = 0;
|
||||
|
||||
/**
|
||||
* The update friend type.
|
||||
*/
|
||||
public static final int UPDATE_FRIEND_TYPE = 1;
|
||||
|
||||
/**
|
||||
* The ignore list type.
|
||||
*/
|
||||
public static final int IGNORE_LIST_TYPE = 2;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The contact packet type.
|
||||
*/
|
||||
private int type;
|
||||
|
||||
/**
|
||||
* The player name.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The world id
|
||||
*/
|
||||
private int worldId;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ContactContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param type The contact packet type.
|
||||
*/
|
||||
public ContactContext(Player player, int type) {
|
||||
this.player = player;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ContactContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param name The player name.
|
||||
* @param worldId The world id (0 = offline).
|
||||
*/
|
||||
public ContactContext(Player player, String name, int worldId) {
|
||||
this.player = player;
|
||||
this.name = name;
|
||||
this.worldId = worldId;
|
||||
this.type = UPDATE_FRIEND_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type.
|
||||
* @return The type.
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type.
|
||||
* @param type The type to set.
|
||||
*/
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
* @return The name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name.
|
||||
* @param name The name to set.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the online.
|
||||
* @return The online.
|
||||
*/
|
||||
public boolean isOnline() {
|
||||
return worldId > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the worldId.
|
||||
* @return the worldId
|
||||
*/
|
||||
public int getWorldId() {
|
||||
return worldId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the worldId.
|
||||
* @param worldId the worldId to set.
|
||||
*/
|
||||
public void setWorldId(int worldId) {
|
||||
this.worldId = worldId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.container.Container;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the context for the container packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ContainerContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private final int interfaceId;
|
||||
|
||||
/**
|
||||
* The child id.
|
||||
*/
|
||||
private final int childId;
|
||||
|
||||
/**
|
||||
* The container type.
|
||||
*/
|
||||
private final int type;
|
||||
|
||||
/**
|
||||
* The items.
|
||||
*/
|
||||
private final Item[] items;
|
||||
|
||||
/**
|
||||
* The length of the array to send.
|
||||
*/
|
||||
private final int length;
|
||||
|
||||
/**
|
||||
* If the container should be split up.
|
||||
*/
|
||||
private final boolean split;
|
||||
|
||||
/**
|
||||
* The slots we're changing.
|
||||
*/
|
||||
private final int[] slots;
|
||||
|
||||
/**
|
||||
* If the container should be cleared.
|
||||
*/
|
||||
private boolean clear;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ContainerContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
* @param clear If the container should be cleared.
|
||||
*/
|
||||
public ContainerContext(Player player, int interfaceId, int childId, boolean clear) {
|
||||
this(player, interfaceId, childId, 0, null, 1, false);
|
||||
this.clear = clear;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ContainerContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
* @param type The container type.
|
||||
* @param container The container.
|
||||
* @param split If the container should be split.
|
||||
*/
|
||||
public ContainerContext(Player player, int interfaceId, int childId, int type, Container container, boolean split) {
|
||||
this(player, interfaceId, childId, type, container.toArray(), container.toArray().length, split);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ContainerContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
* @param type The container type.
|
||||
* @param items The items.
|
||||
* @param split If the container should be split.
|
||||
*/
|
||||
public ContainerContext(Player player, int interfaceId, int childId, int type, Item[] items, boolean split) {
|
||||
this(player, interfaceId, childId, type, items, items.length, split);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ContainerContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
* @param type The container type.
|
||||
* @param items The items.
|
||||
* @param length The length.
|
||||
* @param split If the container should be split.
|
||||
*/
|
||||
public ContainerContext(Player player, int interfaceId, int childId, int type, Item[] items, int length, boolean split) {
|
||||
this.player = player;
|
||||
this.interfaceId = interfaceId;
|
||||
this.childId = childId;
|
||||
this.type = type;
|
||||
this.items = items;
|
||||
this.length = length;
|
||||
this.split = split;
|
||||
this.slots = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ContainerContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
* @param type The container type.
|
||||
* @param items The items.
|
||||
* @param split If the container should be split.
|
||||
* @param slots The slots to update.
|
||||
*/
|
||||
public ContainerContext(Player player, int interfaceId, int childId, int type, Item[] items, boolean split, int... slots) {
|
||||
this.player = player;
|
||||
this.interfaceId = interfaceId;
|
||||
this.childId = childId;
|
||||
this.type = type;
|
||||
this.items = items;
|
||||
this.length = items.length;
|
||||
this.split = split;
|
||||
this.slots = slots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interfaceId.
|
||||
* @return The interfaceId.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type.
|
||||
* @return The type.
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the items.
|
||||
* @return The items.
|
||||
*/
|
||||
public Item[] getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length.
|
||||
* @return The length.
|
||||
*/
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the split.
|
||||
* @return The split.
|
||||
*/
|
||||
public boolean isSplit() {
|
||||
return split;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slots.
|
||||
* @return The slots.
|
||||
*/
|
||||
public int[] getSlots() {
|
||||
return slots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the childId.
|
||||
* @return The childId.
|
||||
*/
|
||||
public int getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clear.
|
||||
* @return The clear.
|
||||
*/
|
||||
public boolean isClear() {
|
||||
return clear;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clear.
|
||||
* @param clear The clear to set.
|
||||
*/
|
||||
public void setClear(boolean clear) {
|
||||
this.clear = clear;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents a default context of a packet.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public class DefaultContext implements Context {
|
||||
/**
|
||||
* Represents the {@link Player} instance.
|
||||
*/
|
||||
private Player player;
|
||||
/**
|
||||
* Represents the array of objects casted.
|
||||
*/
|
||||
private Object[] objects;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DefaultContext.java} {@code Object}.
|
||||
* @param player the player.
|
||||
* @param objects the objects.
|
||||
*/
|
||||
public DefaultContext(Player player, Object... objects) {
|
||||
this.player = player;
|
||||
this.objects = objects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the objects.
|
||||
*/
|
||||
public Object[] getObjects() {
|
||||
return objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player the player to set.
|
||||
*/
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param objects the objects to set.
|
||||
*/
|
||||
public void setObjects(Object[] objects) {
|
||||
this.objects = objects;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the player on interface context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class DisplayModelContext implements Context {
|
||||
|
||||
/**
|
||||
* Represents the model types.
|
||||
* @author Emperor
|
||||
*/
|
||||
public static enum ModelType {
|
||||
PLAYER, NPC, ITEM, MODEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The model type.
|
||||
*/
|
||||
private final ModelType type;
|
||||
|
||||
/**
|
||||
* The node id.
|
||||
*/
|
||||
private final int nodeId;
|
||||
|
||||
/**
|
||||
* The amount (for item display).
|
||||
*/
|
||||
private int amount;
|
||||
|
||||
/**
|
||||
* The zoom.
|
||||
*/
|
||||
private int zoom;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private final int interfaceId;
|
||||
|
||||
/**
|
||||
* The child id.
|
||||
*/
|
||||
private final int childId;
|
||||
|
||||
/**
|
||||
* Construct a new {@code DisplayModelContext} {@code Object} used for
|
||||
* displaying the player.
|
||||
* @param player The player reference.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
*/
|
||||
public DisplayModelContext(Player player, int interfaceId, int childId) {
|
||||
this(player, ModelType.PLAYER, -1, 0, interfaceId, childId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code DisplayModelContext} {@code Object} used for
|
||||
* displaying an NPC.
|
||||
* @param player The player reference.
|
||||
* @param nodeId The node id to display.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
*/
|
||||
public DisplayModelContext(Player player, int nodeId, int interfaceId, int childId) {
|
||||
this(player, ModelType.NPC, nodeId, 0, interfaceId, childId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code DisplayModelContext} {@code Object} used by the
|
||||
* other constructors or for displaying an item.
|
||||
* @param player The player reference.
|
||||
* @param type The model type.
|
||||
* @param nodeId The node id to display.
|
||||
* @param amount The amount.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
*/
|
||||
public DisplayModelContext(Player player, ModelType type, int nodeId, int amount, int interfaceId, int childId) {
|
||||
this.player = player;
|
||||
this.type = type;
|
||||
this.nodeId = nodeId;
|
||||
this.amount = amount;
|
||||
this.interfaceId = interfaceId;
|
||||
this.childId = childId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new {@code DisplayModelContext} {@code Object} used by the
|
||||
* other constructors or for displaying an item.
|
||||
* @param player The player reference.
|
||||
* @param type The model type.
|
||||
* @param nodeId The node id to display.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
*/
|
||||
public DisplayModelContext(Player player, ModelType type, int nodeId, int zoom, int interfaceId, int childId, Object... object) {
|
||||
this.player = player;
|
||||
this.type = type;
|
||||
this.nodeId = nodeId;
|
||||
this.setZoom(zoom);
|
||||
this.interfaceId = interfaceId;
|
||||
this.childId = childId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type.
|
||||
* @return The type.
|
||||
*/
|
||||
public ModelType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nodeId.
|
||||
* @return The nodeId.
|
||||
*/
|
||||
public int getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount.
|
||||
* @return The amount.
|
||||
*/
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface id.
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the child id.
|
||||
* @return The child id.
|
||||
*/
|
||||
public int getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the zoom.
|
||||
*/
|
||||
public int getZoom() {
|
||||
return zoom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param zoom the zoom to set.
|
||||
*/
|
||||
public void setZoom(int zoom) {
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
|
||||
/**
|
||||
* Represents the packet context for the build dynamic scene graph packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class DynamicSceneContext extends SceneGraphContext {
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DynamicSceneContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param login If the player is logging in.
|
||||
*/
|
||||
public DynamicSceneContext(Player player, boolean login) {
|
||||
super(player, login);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The game message packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class GameMessageContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The game message.
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Construct a new {@code GameMessageContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param message The game message.
|
||||
*/
|
||||
public GameMessageContext(Player player, String message) {
|
||||
this.player = player;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game message.
|
||||
* @return The game message.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The packet context of the grand exchange update packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class GrandExchangeContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
public final byte idx;
|
||||
public final byte state;
|
||||
public final short itemID;
|
||||
public final boolean isSell;
|
||||
public final int value;
|
||||
public final int amt;
|
||||
public final int completedAmt;
|
||||
public final int totalCoinsExchanged;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code GrandExchangeContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param state
|
||||
* @param itemID
|
||||
* @param value
|
||||
* @param amt
|
||||
* @param completedAmt
|
||||
* @param totalCoinsExchanged
|
||||
*/
|
||||
public GrandExchangeContext(Player player, byte idx, byte state, short itemID, boolean isSell, int value, int amt, int completedAmt, int totalCoinsExchanged) {
|
||||
this.player = player;
|
||||
this.idx = idx;
|
||||
this.state = state;
|
||||
this.itemID = itemID;
|
||||
this.isSell = isSell;
|
||||
this.value = value;
|
||||
this.amt = amt;
|
||||
this.completedAmt = completedAmt;
|
||||
this.totalCoinsExchanged = totalCoinsExchanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the hint icon packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class HintIconContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The hint icon slot.
|
||||
*/
|
||||
private final int slot;
|
||||
|
||||
/**
|
||||
* The target type.
|
||||
*/
|
||||
private int targetType;
|
||||
|
||||
/**
|
||||
* The arrow id.
|
||||
*/
|
||||
private int arrowId;
|
||||
|
||||
/**
|
||||
* The entity index.
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
/**
|
||||
* The model id.
|
||||
*/
|
||||
private final int modelId;
|
||||
|
||||
/**
|
||||
* The location.
|
||||
*/
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* The height.
|
||||
*/
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HintIconContext} {@code Object}. <br> This hint
|
||||
* icon is entity based.
|
||||
* @param player The player.
|
||||
* @param slot The hint icon slot.
|
||||
* @param arrowId The arrow id.
|
||||
* @param target The target.
|
||||
* @param modelId The model id.
|
||||
*/
|
||||
public HintIconContext(Player player, int slot, int arrowId, Node target, int modelId) {
|
||||
this(player, slot, arrowId, -1, target, modelId);
|
||||
targetType = 2;
|
||||
if (target instanceof Entity) {
|
||||
targetType = target instanceof Player ? 10 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HintIconContext} {@code Object}. <br> This hint
|
||||
* icon is entity based.
|
||||
* @param player The player.
|
||||
* @param slot The hint icon slot.
|
||||
* @param arrowId The arrow id.
|
||||
* @param targetType The target type.
|
||||
* @param target The index of the entity.
|
||||
* @param modelId The model id.
|
||||
*/
|
||||
public HintIconContext(Player player, int slot, int arrowId, int targetType, Node target, int modelId) {
|
||||
this(player, slot, arrowId, targetType, target, modelId, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code HintIconContext} {@code Object}. <br> This hint
|
||||
* icon is entity based.
|
||||
* @param player The player.
|
||||
* @param slot The hint icon slot.
|
||||
* @param arrowId The arrow id.
|
||||
* @param targetType The target type.
|
||||
* @param target The index of the entity.
|
||||
* @param modelId The model id.
|
||||
* @param height The height.
|
||||
*/
|
||||
public HintIconContext(Player player, int slot, int arrowId, int targetType, Node target, int modelId, int height) {
|
||||
this.player = player;
|
||||
this.slot = slot;
|
||||
this.targetType = targetType;
|
||||
this.arrowId = arrowId;
|
||||
this.modelId = modelId;
|
||||
this.height = height;
|
||||
if (target instanceof Entity) {
|
||||
this.index = ((Entity) target).getIndex();
|
||||
this.location = null;
|
||||
} else {
|
||||
this.location = target.getLocation();
|
||||
this.index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slot.
|
||||
* @return The slot.
|
||||
*/
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the targetType.
|
||||
* @return The targetType.
|
||||
*/
|
||||
public int getTargetType() {
|
||||
return targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arrowId.
|
||||
* @return The arrowId.
|
||||
*/
|
||||
public int getArrowId() {
|
||||
return arrowId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index.
|
||||
* @return The index.
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the modelId.
|
||||
* @return The modelId.
|
||||
*/
|
||||
public int getModelId() {
|
||||
return modelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location.
|
||||
* @return The location.
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the targetType.
|
||||
* @param targetType The targetType to set.
|
||||
*/
|
||||
public void setTargetType(int targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the arrowId.
|
||||
* @param arrowId The arrowId to set.
|
||||
*/
|
||||
public void setArrowId(int arrowId) {
|
||||
this.arrowId = arrowId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height.
|
||||
* @return The height.
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the height.
|
||||
* @param height The height to set.
|
||||
*/
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The <b>Integer</b> context.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public class IntegerContext implements Context {
|
||||
|
||||
/**
|
||||
* The player instance.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The integer value.
|
||||
*/
|
||||
private int integer;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code IntegerContext.java} {@code Object}.
|
||||
* @param player the player.
|
||||
* @param integer the integer.
|
||||
*/
|
||||
public IntegerContext(Player player, int integer) {
|
||||
this.player = player;
|
||||
this.setInteger(integer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the integer.
|
||||
*/
|
||||
public int getInteger() {
|
||||
return integer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer the integer to set.
|
||||
*/
|
||||
public void setInteger(int integer) {
|
||||
this.integer = integer;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The context implementation used for the InteractionOption outgoing packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class InteractionOptionContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The index.
|
||||
*/
|
||||
private final int index;
|
||||
|
||||
private boolean remove = false;
|
||||
|
||||
/**
|
||||
* The name.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code InteractionOptionContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param index The index.
|
||||
* @param name The option name.
|
||||
*/
|
||||
public InteractionOptionContext(Player player, int index, String name) {
|
||||
this.player = player;
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.remove = false;
|
||||
}
|
||||
|
||||
public InteractionOptionContext(Player player, int index, String name, boolean remove){
|
||||
this.player = player;
|
||||
this.index = index;
|
||||
this.name = name;
|
||||
this.remove = remove;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public boolean isRemove() {
|
||||
return remove;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index.
|
||||
* @return The index.
|
||||
*/
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
* @return The name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The interface config packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class InterfaceConfigContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private int interfaceId;
|
||||
|
||||
/**
|
||||
* The child id.
|
||||
*/
|
||||
private int childId;
|
||||
|
||||
/**
|
||||
* If the interface child should be hidden.
|
||||
*/
|
||||
private boolean hide;
|
||||
|
||||
/**
|
||||
* Construct a new {@code InterfaceConfigContext} {@code Object}.
|
||||
* @param player The player reference.
|
||||
* @param interfaceId The interface id.
|
||||
* @param childId The child id.
|
||||
* @param hide If the component should be hidden.
|
||||
*/
|
||||
public InterfaceConfigContext(Player player, int interfaceId, int childId, boolean hide) {
|
||||
this.player = player;
|
||||
this.interfaceId = interfaceId;
|
||||
this.childId = childId;
|
||||
this.hide = hide;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface id.
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the child id.
|
||||
* @return The child id.
|
||||
*/
|
||||
public int getChildId() {
|
||||
return childId;
|
||||
}
|
||||
|
||||
/**
|
||||
* If is set.
|
||||
* @return If is set {@code true}.
|
||||
*/
|
||||
public boolean isHidden() {
|
||||
return hide;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The interface packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class InterfaceContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The window id.
|
||||
*/
|
||||
private final int windowId;
|
||||
|
||||
/**
|
||||
* The component id.
|
||||
*/
|
||||
private int componentId;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private final int interfaceId;
|
||||
|
||||
/**
|
||||
* If the interface can be walked over.
|
||||
*/
|
||||
private final boolean walkable;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code InterfaceContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param windowId The window id.
|
||||
* @param componentId The window component id.
|
||||
* @param interfaceId The interface id.
|
||||
* @param walkable If we can walk over the interface.
|
||||
*/
|
||||
public InterfaceContext(Player player, int windowId, int componentId, int interfaceId, boolean walkable) {
|
||||
this.player = player;
|
||||
this.windowId = windowId;
|
||||
this.componentId = componentId;
|
||||
this.interfaceId = interfaceId;
|
||||
this.walkable = walkable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms this context for the new player & id.
|
||||
* @param player The player.
|
||||
* @param id The new interface id.
|
||||
* @return The interface context created.
|
||||
*/
|
||||
public InterfaceContext transform(Player player, int id) {
|
||||
return new InterfaceContext(player, windowId, componentId, id, walkable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player.
|
||||
* @param player The player.
|
||||
* @return This context instance.
|
||||
*/
|
||||
public Context setPlayer(Player player) {
|
||||
this.player = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the windowId.
|
||||
* @return The windowId.
|
||||
*/
|
||||
public int getWindowId() {
|
||||
return windowId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component id.
|
||||
* @param componentId The component id.
|
||||
*/
|
||||
public void setComponentId(int componentId) {
|
||||
this.componentId = componentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the componentId.
|
||||
* @return The componentId.
|
||||
*/
|
||||
public int getComponentId() {
|
||||
return componentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interfaceId.
|
||||
* @return The interfaceId.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the walkable.
|
||||
* @return The walkable.
|
||||
*/
|
||||
public boolean isWalkable() {
|
||||
return walkable;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Packet context used for location based packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class LocationContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The location.
|
||||
*/
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* If the location update is flagged as a teleport.
|
||||
*/
|
||||
private final boolean teleport;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code LocationContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param location The location.
|
||||
* @param teleport If the location update is flagged as a teleport.
|
||||
*/
|
||||
public LocationContext(Player player, Location location, boolean teleport) {
|
||||
this.player = player;
|
||||
this.location = location;
|
||||
this.teleport = teleport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location.
|
||||
* @return The location.
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the teleport.
|
||||
* @return The teleport.
|
||||
*/
|
||||
public boolean isTeleport() {
|
||||
return teleport;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.Rights;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Packet context for communication message packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MessageContext implements Context {
|
||||
|
||||
/**
|
||||
* Represents the packet id to use when sending a message.
|
||||
*/
|
||||
public static final int SEND_MESSAGE = 71;
|
||||
|
||||
/**
|
||||
* Represents the packet id to use when receiving a message.
|
||||
*/
|
||||
public static final int RECIEVE_MESSAGE = 0;
|
||||
|
||||
/**
|
||||
* Represents the packet id use to send a clan message.
|
||||
*/
|
||||
public static final int CLAN_MESSAGE = 54;
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The other player.
|
||||
*/
|
||||
private final String other;
|
||||
|
||||
/**
|
||||
* The chat icon.
|
||||
*/
|
||||
private final int chatIcon;
|
||||
|
||||
/**
|
||||
* The opcode.
|
||||
*/
|
||||
private final int opcode;
|
||||
|
||||
/**
|
||||
* The message.
|
||||
*/
|
||||
private final String message;
|
||||
|
||||
/**
|
||||
* Constructs a new MessageContext Object.
|
||||
* @param player The player.
|
||||
* @param other The communicated player.
|
||||
* @param opcode The opcode.
|
||||
* @param message The message.
|
||||
*/
|
||||
public MessageContext(Player player, Player other, int opcode, String message) {
|
||||
this.player = player;
|
||||
this.other = other.getName();
|
||||
this.chatIcon = Rights.getChatIcon(other);
|
||||
this.opcode = opcode;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new MessageContext Object.
|
||||
* @param player The player.
|
||||
* @param other The communicated player.
|
||||
* @param opcode The opcode.
|
||||
* @param message The message.
|
||||
*/
|
||||
public MessageContext(Player player, String other, int chatIcon, int opcode, String message) {
|
||||
this.player = player;
|
||||
this.other = other;
|
||||
this.chatIcon = chatIcon;
|
||||
this.opcode = opcode;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the other.
|
||||
* @return The other.
|
||||
*/
|
||||
public String getOther() {
|
||||
return other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the opcode.
|
||||
* @return The opcode.
|
||||
*/
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message.
|
||||
* @return The message.
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chatIcon.
|
||||
* @return the chatIcon
|
||||
*/
|
||||
public int getChatIcon() {
|
||||
return chatIcon;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the context used for the Minimap State packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class MinimapStateContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The minimap state to set.
|
||||
*/
|
||||
private final int state;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MinimapStateContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param state The minimap state to set.
|
||||
*/
|
||||
public MinimapStateContext(Player player, int state) {
|
||||
this.player = player;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state.
|
||||
* @return The state.
|
||||
*/
|
||||
public int getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Packet context for music.
|
||||
* @author Emperor
|
||||
* @author SonicForce41
|
||||
*/
|
||||
public class MusicContext implements Context {
|
||||
|
||||
/**
|
||||
* The Player
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The music Id
|
||||
*/
|
||||
private int musicId;
|
||||
|
||||
/**
|
||||
* The secondary music type.
|
||||
*/
|
||||
private boolean secondary;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MusicContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param musicId The music id.
|
||||
*/
|
||||
public MusicContext(Player player, int musicId) {
|
||||
this(player, musicId, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code MusicContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param musicId The music id.
|
||||
* @param temporary The temporary music type.
|
||||
*/
|
||||
public MusicContext(Player player, int musicId, boolean temporary) {
|
||||
this.player = player;
|
||||
this.musicId = musicId;
|
||||
this.secondary = temporary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Music Id
|
||||
* @return the musicId
|
||||
*/
|
||||
public final int getMusicId() {
|
||||
return musicId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the secondary.
|
||||
* @return The secondary.
|
||||
*/
|
||||
public boolean isSecondary() {
|
||||
return secondary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the secondary.
|
||||
* @param secondary The secondary to set.
|
||||
*/
|
||||
public void setSecondary(boolean secondary) {
|
||||
this.secondary = secondary;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The default packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class PlayerContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PlayerContext} {@code Object}.
|
||||
* @param player The player.
|
||||
*/
|
||||
public PlayerContext(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The packet context for the positioned graphic packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class PositionedGraphicContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The graphics.
|
||||
*/
|
||||
private final Graphics graphic;
|
||||
|
||||
/**
|
||||
* The location.
|
||||
*/
|
||||
private final Location location;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code PositionedGraphicContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param graphic The graphic to display on the given location.
|
||||
* @param location The location to display the graphic on.
|
||||
*/
|
||||
public PositionedGraphicContext(Player player, Graphics graphic, Location location) {
|
||||
this.player = player;
|
||||
this.graphic = graphic;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the graphic
|
||||
*/
|
||||
public Graphics getGraphic() {
|
||||
return graphic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the location
|
||||
*/
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The run script packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class RunScriptContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The run script id.
|
||||
*/
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* The parameters.
|
||||
*/
|
||||
private Object[] objects;
|
||||
|
||||
/**
|
||||
* The string.
|
||||
*/
|
||||
private String string;
|
||||
|
||||
/**
|
||||
* Construct a new {@code RunScriptContext} {@code Object}.
|
||||
* @param player
|
||||
* @param id
|
||||
* @param string
|
||||
* @param objects
|
||||
*/
|
||||
public RunScriptContext(Player player, int id, String string, Object... objects) {
|
||||
this.player = player;
|
||||
this.id = id;
|
||||
this.objects = objects;
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player.
|
||||
* @param player The player.
|
||||
* @return This context instance.
|
||||
*/
|
||||
public Context setPlayer(Player player) {
|
||||
this.player = player;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the run scripts id.
|
||||
* @return The run scripts id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the objects.
|
||||
* @return The objects.
|
||||
*/
|
||||
public Object[] getObjects() {
|
||||
return objects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the string.
|
||||
* @return The string.
|
||||
*/
|
||||
public String getString() {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The update scene graph packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class SceneGraphContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* If we are logging in.
|
||||
*/
|
||||
private final boolean login;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SceneGraphContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param login If we are logging in.
|
||||
*/
|
||||
public SceneGraphContext(Player player, boolean login) {
|
||||
this.player = player;
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the login.
|
||||
* @return The login.
|
||||
*/
|
||||
public boolean isLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The skill context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class SkillContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The skill id.
|
||||
*/
|
||||
private final int skillId;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SkillContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param skillId The skill id.
|
||||
*/
|
||||
public SkillContext(Player player, int skillId) {
|
||||
this.player = player;
|
||||
this.skillId = skillId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skillId.
|
||||
* @return The skillId.
|
||||
*/
|
||||
public int getSkillId() {
|
||||
return skillId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* The StringPacket packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class StringContext implements Context {
|
||||
|
||||
/**
|
||||
* The player reference.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The StringPacket string.
|
||||
*/
|
||||
private String string;
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private int interfaceId;
|
||||
|
||||
/**
|
||||
* The line id.
|
||||
*/
|
||||
private int lineId;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code StringContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param string The string to send.
|
||||
* @param interfaceId The interface id.
|
||||
* @param lineId The child id.
|
||||
*/
|
||||
public StringContext(Player player, String string, int interfaceId, int lineId) {
|
||||
this.player = player;
|
||||
this.string = string;
|
||||
this.interfaceId = interfaceId;
|
||||
this.lineId = lineId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the StringPacket string.
|
||||
* @return The string.
|
||||
*/
|
||||
public String getString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface id.
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the line id.
|
||||
* @return The line id.
|
||||
*/
|
||||
public int getLineId() {
|
||||
return lineId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents a system update.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public class SystemUpdateContext implements Context {
|
||||
|
||||
/**
|
||||
* The <b>Player</b> instance.
|
||||
*/
|
||||
private Player player;
|
||||
|
||||
/**
|
||||
* The time.
|
||||
*/
|
||||
private int time;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SystemUpdateContext.java} {@code Object}.
|
||||
* @param player the <b>Player</b>.
|
||||
* @param time the time.
|
||||
*/
|
||||
public SystemUpdateContext(Player player, int time) {
|
||||
this.player = player;
|
||||
this.setTime(time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the time
|
||||
*/
|
||||
public int getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param time the time to set
|
||||
*/
|
||||
public void setTime(int time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the set walk-to option context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class WalkOptionContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The option.
|
||||
*/
|
||||
private final String option;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WalkOptionContext} {@code Object}.
|
||||
* @param player The player.
|
||||
* @param option The option name.
|
||||
*/
|
||||
public WalkOptionContext(Player player, String option) {
|
||||
this.player = player;
|
||||
this.option = option;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the option.
|
||||
* @return The option.
|
||||
*/
|
||||
public String getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package core.net.packet.context;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.Context;
|
||||
|
||||
/**
|
||||
* Represents the windows pane packet context.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class WindowsPaneContext implements Context {
|
||||
|
||||
/**
|
||||
* The player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* The window id.
|
||||
*/
|
||||
private final int windowId;
|
||||
|
||||
/**
|
||||
* The type.
|
||||
*/
|
||||
private final int type;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code WindowsPaneContext} object.
|
||||
* @param player The player.
|
||||
* @param windowId The window id.
|
||||
* @param type The type.
|
||||
*/
|
||||
public WindowsPaneContext(Player player, int windowId, int type) {
|
||||
this.player = player;
|
||||
this.windowId = windowId;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the windowId.
|
||||
* @return The windowId.
|
||||
*/
|
||||
public int getWindowId() {
|
||||
return windowId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type.
|
||||
* @return The type.
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.component.ComponentPlugin;
|
||||
import core.game.container.Container;
|
||||
import core.game.content.dialogue.DialogueAction;
|
||||
import core.game.interaction.Option;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.login.LoginConfiguration;
|
||||
import core.game.node.entity.player.link.request.assist.AssistSession;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The incoming reward button packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class ActionButtonPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(final Player player, int opcode, IoBuffer buffer) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
int[] args = getArguments(player, buffer);
|
||||
if (args == null || (buffer.opcode() != 76 && args[0] != 106 && args[0] != 108 && args[0] != 110 && args[0] != 646 && player.getLocks().isComponentLocked() && player.getExtension(AssistSession.class) == null)) {
|
||||
player.debug("Check this code in reward button packet, where args arent null && opcode !=");
|
||||
return;
|
||||
}
|
||||
int componentId = args[0];
|
||||
int buttonId = args[1];
|
||||
int slot = args[2];
|
||||
int itemId = args[3];
|
||||
player.debug("Component=" + componentId + ", button=" + buttonId + ", slot=" + slot + ", item=" + itemId + ", opcode=" + buffer.opcode());
|
||||
if (player.getDialogueInterpreter().getDialogue() != null && buffer.opcode() != 132 && componentId != 64) {
|
||||
player.getDialogueInterpreter().close();
|
||||
}
|
||||
if (player.getLocks().isComponentLocked()) {
|
||||
return;
|
||||
}
|
||||
if (itemId > -1 && slot > -1) {
|
||||
Container container = getContainer(player, componentId);
|
||||
if (container != null) {
|
||||
handleItemInteraction(player, buffer.opcode(), itemId, slot, container);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (player.getZoneMonitor().clickButton(componentId, buttonId, slot, itemId, opcode)) {
|
||||
return;
|
||||
}
|
||||
Component c = player.getInterfaceManager().getComponent(componentId);
|
||||
if (c == null || c.isHidden()) {
|
||||
player.debug("Component " + c + " wasn't opened in interface manager.");
|
||||
return;
|
||||
}
|
||||
ComponentPlugin plugin = c.getPlugin();
|
||||
if (plugin != null) {
|
||||
player.debug("Component plugin = " + plugin.getClass().getSimpleName());
|
||||
plugin.handle(player, c, buffer.opcode(), buttonId, slot, itemId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the container for the component id.
|
||||
* @param player The player.
|
||||
* @param componentId The component id.
|
||||
* @return The container.
|
||||
*/
|
||||
private Container getContainer(Player player, int componentId) {
|
||||
switch (componentId) {
|
||||
case 149:
|
||||
return player.getInventory();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arguments for the reward button.
|
||||
* @param player The player.
|
||||
* @param buffer The buffer.
|
||||
* @return The arguments [component, button, slot, item]
|
||||
*/
|
||||
private static int[] getArguments(final Player player, IoBuffer buffer) {
|
||||
int data = -1;
|
||||
int componentId = -1;
|
||||
int buttonId = -1;
|
||||
int itemId = -1;
|
||||
int slot = -1;
|
||||
switch (buffer.opcode()) {
|
||||
case 81:
|
||||
//System.out.println("Using action handler81");
|
||||
slot = buffer.getShortA();
|
||||
itemId = buffer.getShort();
|
||||
buttonId = buffer.getShort();
|
||||
componentId = buffer.getShort();
|
||||
break;
|
||||
case 156:
|
||||
//System.out.println("Using action handler156");
|
||||
slot = buffer.getLEShortA();
|
||||
itemId = buffer.getShortA();
|
||||
data = buffer.getLEInt();
|
||||
componentId = data >> 16;
|
||||
buttonId = data & 0xffff;
|
||||
break;
|
||||
case 55:
|
||||
//System.out.println("Using action handler55");
|
||||
itemId = buffer.getLEShort();
|
||||
slot = buffer.getShortA();
|
||||
data = buffer.getIntA();
|
||||
componentId = data >> 16;
|
||||
buttonId = data & 0xffff;
|
||||
break;
|
||||
case 153:
|
||||
//System.out.println("Using action handler153");
|
||||
data = buffer.getLEInt();
|
||||
slot = buffer.getLEShort();
|
||||
itemId = buffer.getLEShort();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
break;
|
||||
case 161:
|
||||
//System.out.println("Using action handler161");
|
||||
data = buffer.getLEInt();
|
||||
itemId = buffer.getLEShortA();
|
||||
slot = buffer.getLEShortA();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
break;
|
||||
case 135:
|
||||
//System.out.println("Using action handler135");
|
||||
itemId = buffer.getShortA();
|
||||
slot = buffer.getShortA();
|
||||
data = buffer.getIntB();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
break;
|
||||
case 155: //Interface options
|
||||
case 196:
|
||||
case 124:
|
||||
case 199:
|
||||
case 234:
|
||||
case 168:
|
||||
case 166:
|
||||
case 64:
|
||||
case 53:
|
||||
case 9:
|
||||
//System.out.println("Using action handler155-9");
|
||||
data = buffer.getInt();
|
||||
slot = buffer.getShort();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
break;
|
||||
case 132: //Dialogue options
|
||||
//System.out.println("Using action handler132");
|
||||
data = buffer.getIntA();
|
||||
slot = buffer.getLEShort();
|
||||
componentId = data >> 16;
|
||||
buttonId = data & 0xffff;
|
||||
if (player.getDialogueInterpreter().getDialogue() == null && player.getDialogueInterpreter().getDialogueStage() == null) {
|
||||
player.getInterfaceManager().closeChatbox();
|
||||
List<DialogueAction> actions = player.getDialogueInterpreter().getActions();
|
||||
if (actions.size() > 0) {
|
||||
DialogueAction action = actions.get(0);
|
||||
action.handle(player, buttonId);
|
||||
actions.remove(action);
|
||||
}
|
||||
break;
|
||||
}
|
||||
player.getDialogueInterpreter().handle(componentId, buttonId);
|
||||
break;
|
||||
case 133:
|
||||
//System.out.println("Using action handler133");
|
||||
data = buffer.getLEInt();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
slot = buffer.getShort();
|
||||
itemId = buffer.getLEShortA();
|
||||
break;
|
||||
case 206:
|
||||
//System.out.println("Using action handler206");
|
||||
itemId = buffer.getShortA();
|
||||
slot = buffer.getLEShort();
|
||||
data = buffer.getLEInt();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
//player.sendMessage("itemId=" + itemId + ", data=" + data + ", buttonId=" + buttonId + ", compId= " + componentId);
|
||||
break;
|
||||
case 230: // Short
|
||||
case 180:
|
||||
case 10:
|
||||
//System.out.println("Using action handler230-10");
|
||||
data = buffer.getInt();
|
||||
componentId = data >> 16;
|
||||
buttonId = data & 0xffff;
|
||||
if (buffer.opcode() == 230) {
|
||||
slot = buffer.getShort();
|
||||
}
|
||||
if (componentId == 49) {
|
||||
if (player.getDialogueInterpreter().getDialogue() == null && player.getDialogueInterpreter().getDialogueStage() == null) {
|
||||
player.setAttribute("chatbox-buttonid",buttonId);
|
||||
player.getInterfaceManager().closeChatbox();
|
||||
return null;
|
||||
}
|
||||
player.setAttribute("chatbox-buttonid",buttonId);
|
||||
player.getDialogueInterpreter().getDialogue().handle(componentId, buttonId);
|
||||
}
|
||||
break;
|
||||
case 157:
|
||||
//System.out.println("Using action handler157");
|
||||
itemId = buffer.getLEShort();
|
||||
slot = buffer.getLEShort();
|
||||
data = buffer.getLEInt();
|
||||
componentId = data >> 16;
|
||||
buttonId = data & 0xffff;
|
||||
break;
|
||||
case 39:
|
||||
//System.out.println("Using action handler39");
|
||||
data = buffer.getInt();
|
||||
slot = buffer.getShort();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
break;
|
||||
case 128:
|
||||
//System.out.println("Using action handler128");
|
||||
data = buffer.getInt();
|
||||
slot = buffer.getShort();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xffff;
|
||||
break;
|
||||
case 235:
|
||||
//System.out.println("Using action handler235");
|
||||
data = buffer.getInt();
|
||||
slot = buffer.getShort();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xffff;
|
||||
break;
|
||||
case 243:
|
||||
//System.out.println("Using action handler243");
|
||||
data = buffer.getInt();
|
||||
itemId = buffer.getShortA();
|
||||
slot = buffer.getLEShortA();
|
||||
componentId = data >> 16;
|
||||
buttonId = data & 0xffff;
|
||||
break;
|
||||
case 170:
|
||||
//System.out.println("Using action handler170");
|
||||
slot = buffer.getLEShort();
|
||||
itemId = buffer.getShortA();
|
||||
data = buffer.getLEInt();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xFFFF;
|
||||
break;
|
||||
case 145:
|
||||
//System.out.println("Using action handler145");
|
||||
data = buffer.getIntB();
|
||||
itemId = buffer.getShortA();
|
||||
slot = buffer.getLEShort();
|
||||
componentId = (data >> 16) & 0xFFFF;
|
||||
buttonId = data & 0xffff;
|
||||
// TODO dialogue with store X.
|
||||
break;
|
||||
case 127:// 3rd option on send item.
|
||||
case 203:// 5th option on send item.
|
||||
case 205:// 2 option
|
||||
case 211:// 4rth option on send item.
|
||||
case 187: // 6th
|
||||
//System.out.println("Using action handler127-187");
|
||||
data = buffer.getInt();
|
||||
slot = buffer.getShort();
|
||||
componentId = data >> 16;
|
||||
buttonId = data & 0xffff;
|
||||
itemId = -1;
|
||||
break;
|
||||
case 184:
|
||||
case 95:
|
||||
//System.out.println("Using action handler184-95");
|
||||
if (player.getAttribute("logging_in") != null) {
|
||||
player.getInterfaceManager().close();
|
||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.removeAttribute("logging_in");
|
||||
LoginConfiguration.configureGameWorld(player);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
player.getInterfaceManager().close();
|
||||
if (player.getAttribute("worldMap:viewing") != null) {
|
||||
player.removeAttribute("worldMap:viewing");
|
||||
player.getPacketDispatch().sendWindowsPane(player.getInterfaceManager().isResizable() ? 746 : 548, 2);
|
||||
player.unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return new int[] { componentId, buttonId, slot, itemId };
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an item interaction.
|
||||
* @param player The player.
|
||||
* @param opcode The opcode.
|
||||
* @param itemId The item.
|
||||
*/
|
||||
private static void handleItemInteraction(Player player, int opcode, int itemId, int slot, Container container) {
|
||||
if (slot < 0 || slot >= container.capacity()) {
|
||||
return;
|
||||
}
|
||||
Item item = container.get(slot);
|
||||
if (item == null || item.getId() != itemId) {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
switch (opcode) {
|
||||
case 156: // First option
|
||||
index = 0;
|
||||
break;
|
||||
case 55: // Second option (wield/wear)
|
||||
index = 1;
|
||||
break;
|
||||
case 153: // Third option
|
||||
index = 2;
|
||||
break;
|
||||
case 161: // Fourth option (summon)
|
||||
index = 3;
|
||||
break;
|
||||
case 135: // Fifth option (drop/destroy)
|
||||
index = 4;
|
||||
break;
|
||||
}
|
||||
final Option option = item.getInteraction().get(index);
|
||||
if (option == null || player.getLocks().isInteractionLocked()) {
|
||||
return;
|
||||
}
|
||||
item.getInteraction().handleItemOption(player, option, container);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles an incoming camera movement changed packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class CameraMovementPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
buffer.getShortA();
|
||||
buffer.getLEShort();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.monitor.PlayerMonitor;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.update.flag.context.ChatMessage;
|
||||
import core.game.world.update.flag.player.ChatFlag;
|
||||
import core.net.amsc.MSPacketRepository;
|
||||
import core.net.amsc.WorldCommunicator;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents the incoming chat packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class ChatPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(final Player player, int opcode, IoBuffer buffer) {
|
||||
try {
|
||||
final int effects = buffer.getShort();
|
||||
final int numChars = buffer.getSmart();
|
||||
final String message = StringUtils.decryptPlayerChat(buffer, numChars);
|
||||
if (player.getDetails().isMuted()) {
|
||||
player.getPacketDispatch().sendMessage("You have been " + (player.getDetails().isPermMute() ? "permanently" : "temporarily") + " muted due to breaking a rule.");
|
||||
return;
|
||||
}
|
||||
if (message.startsWith("/") && player.getCommunication().getClan() != null) {
|
||||
StringBuilder sb = new StringBuilder(message);
|
||||
sb.append(" => ").append(player.getName()).append(" (owned by ").append(player.getCommunication().getClan().getOwner()).append(")");
|
||||
String m = sb.toString();
|
||||
player.getMonitor().log(m.replace(m.charAt(0), ' ').trim(), PlayerMonitor.CLAN_CHAT_LOG);
|
||||
if (WorldCommunicator.isEnabled()) {
|
||||
MSPacketRepository.sendClanMessage(player, message.substring(1));
|
||||
} else {
|
||||
player.getCommunication().getClan().message(player, message.substring(1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
player.getMonitor().log(message, PlayerMonitor.PUBLIC_CHAT_LOG);
|
||||
ChatMessage ctx = new ChatMessage(player, message, effects, numChars);
|
||||
GameWorld.getPulser().submit(new Pulse(0, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.getUpdateMasks().register(new ChatFlag(ctx));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.amsc.MSPacketRepository;
|
||||
import core.net.amsc.WorldCommunicator;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles an incoming chat settings update packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ChatSettingsPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
int publicSetting = buffer.get();
|
||||
int privateSetting = buffer.get();
|
||||
int tradeSetting = buffer.get();
|
||||
if (WorldCommunicator.isEnabled()) {
|
||||
MSPacketRepository.sendChatSetting(player, publicSetting, privateSetting, tradeSetting);
|
||||
}
|
||||
player.getSettings().updateChatSettings(publicSetting, privateSetting, tradeSetting);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.communication.ClanRank;
|
||||
import core.game.system.communication.ClanRepository;
|
||||
import core.game.system.communication.CommunicationInfo;
|
||||
import core.game.world.repository.Repository;
|
||||
import core.net.amsc.MSPacketRepository;
|
||||
import core.net.amsc.WorldCommunicator;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Handles incoming clan packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class ClanPacketHandler implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
switch (buffer.opcode()) {
|
||||
case 104:
|
||||
long nameLong = buffer.getLong();
|
||||
String name = StringUtils.longToString(nameLong);
|
||||
if (nameLong != 0l) {
|
||||
player.getPacketDispatch().sendMessage("Attempting to join channel...:clan:");
|
||||
}
|
||||
if (WorldCommunicator.isEnabled()) {
|
||||
MSPacketRepository.sendJoinClan(player, name);
|
||||
return;
|
||||
}
|
||||
if (player.getCommunication().getClan() != null) {
|
||||
player.getCommunication().getClan().leave(player, true);
|
||||
player.getCommunication().setClan(null);
|
||||
return;
|
||||
}
|
||||
ClanRepository clan = ClanRepository.get(name);
|
||||
if (clan == null || clan.getName().equals("Chat disabled")) {
|
||||
player.getPacketDispatch().sendMessage("The channel you tried to join does not exist.");
|
||||
break;
|
||||
}
|
||||
if (clan.enter(player)) {
|
||||
player.getCommunication().setClan(clan);
|
||||
}
|
||||
break;
|
||||
case 188:
|
||||
int rank = buffer.getA();
|
||||
name = StringUtils.longToString(buffer.getLong());
|
||||
if (WorldCommunicator.isEnabled()) {
|
||||
MSPacketRepository.sendContactUpdate(player.getName(), name, false, false, ClanRank.values()[rank + 1]);
|
||||
break;
|
||||
}
|
||||
CommunicationInfo.updateClanRank(player, name, ClanRank.values()[rank + 1]);
|
||||
break;
|
||||
case 162:
|
||||
name = StringUtils.longToString(buffer.getLong());
|
||||
if (WorldCommunicator.isEnabled()) {
|
||||
MSPacketRepository.sendClanKick(player.getName(), name);
|
||||
break;
|
||||
}
|
||||
clan = player.getCommunication().getClan();
|
||||
Player target = Repository.getPlayerByName(name);
|
||||
if (clan == null || target == null) {
|
||||
break;
|
||||
}
|
||||
clan.kick(player, target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles an incoming client focus changed packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ClientFocusPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
if (player != null) {
|
||||
player.getMonitor().setClientFocus(buffer.get() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.command.CommandSystem;
|
||||
import core.game.system.monitor.PlayerMonitor;
|
||||
import core.game.world.GameWorld;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles an incoming command packet.
|
||||
* @author Emperor
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public final class CommandPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
final int data = buffer.get();
|
||||
if (buffer.toByteBuffer().hasRemaining()) {
|
||||
final String message = ((char) data + buffer.getString()).toLowerCase();
|
||||
if (!GameWorld.getSettings().isDevMode()) {
|
||||
int last = player.getAttribute("commandLast", 0);
|
||||
if (last > GameWorld.getTicks()) {
|
||||
return;
|
||||
}
|
||||
player.setAttribute("commandLast", GameWorld.getTicks() + 1);
|
||||
}
|
||||
if (CommandSystem.Companion.getCommandSystem().parse(player, message)) {
|
||||
player.getMonitor().log(message, PlayerMonitor.COMMAND_LOG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.communication.CommunicationInfo;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents the packet used to handle all incoming packets related to
|
||||
* communication.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public final class CommunicationPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
switch (buffer.opcode()) {
|
||||
case 120:
|
||||
CommunicationInfo.add(player, StringUtils.longToString(buffer.getLong()));
|
||||
break;
|
||||
case 57:
|
||||
CommunicationInfo.remove(player, StringUtils.longToString(buffer.getLong()), false);
|
||||
break;
|
||||
case 34:
|
||||
CommunicationInfo.block(player, StringUtils.longToString(buffer.getLong()));
|
||||
break;
|
||||
case 213:
|
||||
CommunicationInfo.remove(player, StringUtils.longToString(buffer.getLong()), true);
|
||||
break;
|
||||
case 201:
|
||||
String name = StringUtils.longToString(buffer.getLong());
|
||||
String message = StringUtils.decryptPlayerChat(buffer, buffer.get() & 0xFF);
|
||||
if (player.getDetails().isMuted()) {
|
||||
player.getPacketDispatch().sendMessage("You have been " + (player.getDetails().isPermMute() ? "permanently" : "temporarily") + " muted due to breaking a rule.");
|
||||
return;
|
||||
}
|
||||
CommunicationInfo.sendMessage(player, name, message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles the display update packet.
|
||||
* @author Emperor
|
||||
*
|
||||
*/
|
||||
public class DisplayUpdatePacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
int windowMode = buffer.get(); //Window mode
|
||||
int screenWidth = buffer.getShort();
|
||||
int screenHeight = buffer.getShort();
|
||||
int displayMode = buffer.get(); //Display mode
|
||||
player.getSession().getClientInfo().setScreenWidth(screenWidth);
|
||||
player.getSession().getClientInfo().setScreenHeight(screenHeight);
|
||||
player.getSession().getClientInfo().setDisplayMode(displayMode);
|
||||
player.getInterfaceManager().switchWindowMode(windowMode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.SystemLogger;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
public class DummyPacket implements IncomingPacket {
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
SystemLogger.logInfo("Received opcode " + opcode + " packet.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.cache.Cache;
|
||||
import core.cache.def.impl.ItemDefinition;
|
||||
import core.cache.def.impl.NPCDefinition;
|
||||
import core.cache.def.impl.ObjectDefinition;
|
||||
import core.cache.def.impl.VarbitDefinition;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Handles the incoming examine packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class ExaminePacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
String name;
|
||||
switch (buffer.opcode()) {
|
||||
case 94: // Object examine
|
||||
int id = buffer.getLEShortA();
|
||||
if (id < 0 || id > Cache.getObjectDefinitionsSize()) {
|
||||
break;
|
||||
}
|
||||
ObjectDefinition d = ObjectDefinition.forId(id);
|
||||
name = d.getExamine();
|
||||
//String coords = id + ", " + player.getLocation().getX() + ", " + player.getLocation().getY() + ", " + player.getLocation().getZ();
|
||||
player.debug("Object id: " + id + ", models: " + (d.getModelIds() != null ? Arrays.toString(d.getModelIds()) : null) + ", anim: " + d.animationId + ", config: " + (d.getVarbitID() != -1 ? d.getVarbitID() + " (file)" : d.getConfigId()) + ".");
|
||||
player.debug("Varp config index: " + VarbitDefinition.forObjectID(d.getVarbitID()).getConfigId());
|
||||
player.getPacketDispatch().sendMessage(""+name+"");
|
||||
/*if {
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection("LandscapeParser.removeGameObject(new GameObject("+coords+"));//"+ d.getName() ), null);
|
||||
}*/
|
||||
break;
|
||||
case 235:
|
||||
case 92: // Item examine
|
||||
id = buffer.getLEShortA();
|
||||
if (id < 0 || id > Cache.getItemDefinitionsSize()) {
|
||||
break;
|
||||
}
|
||||
player.getPacketDispatch().sendMessage(getItemExamine(id));
|
||||
break;
|
||||
case 72: // NPC examine
|
||||
id = buffer.getShort();
|
||||
if (id < 0 || id > Cache.getNPCDefinitionsSize()) {
|
||||
break;
|
||||
}
|
||||
player.debug("NPC id: " + id + ".");
|
||||
NPCDefinition def = NPCDefinition.forId(id);
|
||||
if (def == null) {
|
||||
break;
|
||||
}
|
||||
player.getPacketDispatch().sendMessage(def.getExamine());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item examine.
|
||||
* @param id the id.
|
||||
* @return the name.
|
||||
*/
|
||||
public static String getItemExamine(int id) {
|
||||
if (id == 995) {
|
||||
return "Lovely money!";
|
||||
}
|
||||
if (ItemDefinition.forId(id).getExamine().length() == 255) {
|
||||
return "A set of instructions to be followed.";
|
||||
}
|
||||
return ItemDefinition.forId(id).getExamine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Represents the <b>Incoming</b> packet of the grand exchange.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class GrandExchangePacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
int itemId = buffer.getShort();
|
||||
player.getPlayerGrandExchange().constructBuy(itemId);
|
||||
player.getInterfaceManager().closeChatbox();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.info.Rights;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import plugin.ai.general.GeneralBotCreator;
|
||||
|
||||
/**
|
||||
* Handles the idle packet handler.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class IdlePacketHandler implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
if (player.getDetails().getRights() != Rights.ADMINISTRATOR) {
|
||||
GeneralBotCreator.BotScriptPulse pulse = player.getAttribute("botting:script",null);
|
||||
if(pulse != null && pulse.isRunning()){
|
||||
return;
|
||||
}
|
||||
player.getPacketDispatch().sendLogout();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.ServerConstants;
|
||||
import core.cache.def.impl.ObjectDefinition;
|
||||
import core.cache.def.impl.VarbitDefinition;
|
||||
import core.game.interaction.*;
|
||||
import core.game.node.Node;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.SystemLogger;
|
||||
import core.game.system.task.Pulse;
|
||||
import plugin.ai.AIPlayer;
|
||||
import core.game.node.item.GroundItem;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.object.GameObject;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.repository.Repository;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
import core.game.content.quest.PluginInteractionManager;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Handles the incoming interaction packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class InteractionPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
if (buffer.opcode() != 105) {
|
||||
player = getPlayer(player);
|
||||
}
|
||||
if (player.getLocks().isInteractionLocked() || !player.getInterfaceManager().close()) {
|
||||
return;
|
||||
}
|
||||
player.getInterfaceManager().closeChatbox();
|
||||
player.debug("Received " + buffer.opcode());
|
||||
try {
|
||||
switch (buffer.opcode()) {
|
||||
case 78: // NPC reward 1
|
||||
int index = buffer.getLEShort();
|
||||
handleNPCInteraction(player, 0, index);
|
||||
break;
|
||||
case 3: // NPC reward 2
|
||||
index = buffer.getLEShortA();
|
||||
handleNPCInteraction(player, 1, index);
|
||||
break;
|
||||
case 148: // NPC reward 3
|
||||
index = buffer.getShortA();
|
||||
handleNPCInteraction(player, 2, index);
|
||||
break;
|
||||
case 30: // NPC reward 4
|
||||
index = buffer.getShort();
|
||||
handleNPCInteraction(player, 3, index);
|
||||
break;
|
||||
case 218: // NPC reward 5
|
||||
index = buffer.getLEShort();
|
||||
handleNPCInteraction(player, 4, index);
|
||||
break;
|
||||
case 254: // Object reward 1
|
||||
int x = buffer.getLEShort();
|
||||
int objectId = buffer.getShortA() & 0xFFFF;
|
||||
int y = buffer.getShort();
|
||||
handleObjectInteraction(player, 0, x, y, objectId);
|
||||
break;
|
||||
case 194: // Object reward 2
|
||||
y = buffer.getLEShortA();
|
||||
x = buffer.getLEShort();
|
||||
objectId = buffer.getShort() & 0xFFFF;
|
||||
handleObjectInteraction(player, 1, x, y, objectId);
|
||||
break;
|
||||
case 84: // Object reward 3
|
||||
objectId = buffer.getLEShortA() & 0xFFFF;
|
||||
y = buffer.getLEShortA();
|
||||
x = buffer.getLEShort();
|
||||
handleObjectInteraction(player, 2, x, y, objectId);
|
||||
break;
|
||||
case 152: // Object reward 4 TODO
|
||||
objectId = buffer.getLEShortA() & 0xFFFF;
|
||||
x = buffer.getLEShort();
|
||||
y = buffer.getLEShortA();
|
||||
handleObjectInteraction(player, 3, x, y, objectId);
|
||||
break;
|
||||
case 247://Object reward 4
|
||||
y = buffer.getLEShort() & 0xFFFF;
|
||||
x = buffer.getLEShortA();
|
||||
objectId = buffer.getShort() & 0xFFFF;
|
||||
handleObjectInteraction(player, 3, x, y, objectId);
|
||||
break;
|
||||
case 170: // Object reward 5
|
||||
objectId = buffer.getLEShortA() & 0xFFFF;
|
||||
x = buffer.getLEShortA();
|
||||
y = buffer.getLEShortA();
|
||||
handleObjectInteraction(player, 4, x, y, objectId);
|
||||
break;
|
||||
case 68: // Player reward 1 - Challenge
|
||||
index = buffer.getLEShortA();
|
||||
handlePlayerInteraction(player, 0, index);
|
||||
break;
|
||||
/*case : // Player reward 2 TODO
|
||||
index = buffer.getLEShort();
|
||||
handlePlayerInteraction(player, 1, index);
|
||||
break;*/
|
||||
case 71: // Player reward 3 - follow
|
||||
index = buffer.getLEShortA();
|
||||
handlePlayerInteraction(player, 2, index);
|
||||
break;
|
||||
case 180: // Player reward 4 - trade
|
||||
index = buffer.getLEShortA();
|
||||
handlePlayerInteraction(player, 3, index);
|
||||
break;
|
||||
/*case : // Player reward 5 TODO
|
||||
index = buffer.getLEShortA();
|
||||
handlePlayerInteraction(player, 4, index);
|
||||
break;*/
|
||||
/*case : // Player reward 6 TODO
|
||||
index = buffer.getShort();
|
||||
handlePlayerInteraction(player, 5, index);
|
||||
break;*/
|
||||
case 114: // Player reward 7 - req assistance
|
||||
index = buffer.getLEShortA();
|
||||
handlePlayerInteraction(player, 6, index);
|
||||
break;
|
||||
case 175: // Player reward 8 - "whack" (also "control" for AIPs)
|
||||
index = buffer.getShortA();
|
||||
handlePlayerInteraction(player, 7, index);
|
||||
break;
|
||||
case 66: // Ground item reward 1
|
||||
x = buffer.getLEShort();
|
||||
int itemId = buffer.getShort();
|
||||
y = buffer.getLEShortA();
|
||||
handleGroundItemInteraction(player, 2, itemId, Location.create(x, y, player.getLocation().getZ()));
|
||||
break;
|
||||
case 33: // Ground item reward 2
|
||||
itemId = buffer.getShort();
|
||||
x = buffer.getShort();
|
||||
y = buffer.getLEShort();
|
||||
handleGroundItemInteraction(player, 3, itemId, Location.create(x, y, player.getLocation().getZ()));
|
||||
break;
|
||||
}
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the NPC interaction.
|
||||
* @param player the player.
|
||||
* @param index the index.
|
||||
*/
|
||||
public static void handleNPCInteraction(Player player, int optionIndex, final int index) {
|
||||
if (index < 1 || index > ServerConstants.MAX_NPCS) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
return;
|
||||
}
|
||||
final NPC npc = Repository.getNpcs().get(index);
|
||||
if (npc == null) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
return;
|
||||
}
|
||||
if (player.getAttribute("removenpc", false)) {
|
||||
npc.clear();
|
||||
player.getPacketDispatch().sendMessage("Removed npc=" + npc.toString());
|
||||
return;
|
||||
}
|
||||
NPC shown = npc.getShownNPC(player);
|
||||
final Option option = shown.getInteraction().get(optionIndex);
|
||||
if (option == null) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
Interaction.handleInvalidInteraction(player, npc, Option.NULL);
|
||||
return;
|
||||
}
|
||||
player.debug("NPC Interacting with \"" + shown.getUsername() + "\" [index=" + index + ", renderable=" + npc.isRenderable() + "]");
|
||||
player.debug("option=" + option.getName() + ", slot=" + option.getIndex() + ", id=" + shown.getId() + " original=" + npc.getId() + ", location=" + npc.getLocation() + "");
|
||||
player.debug("spawn=" + npc.getProperties().getSpawnLocation() + ".");
|
||||
player.debug("Varp ID= " + npc.getDefinition().getConfigId() + " Offset=" + npc.getDefinition().getVarbitOffset() + " Size=" + npc.getDefinition().getVarbitSize());
|
||||
handleAIPLegion(player, 0, optionIndex, index);
|
||||
if(Listeners.run(shown.getId(),2, option.getName(),player,shown)){
|
||||
return;
|
||||
}
|
||||
if(PluginInteractionManager.handle(player,shown,option)){
|
||||
return;
|
||||
}
|
||||
npc.getInteraction().handle(player, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Node interaction with the first index
|
||||
* @param player The interacting player.
|
||||
* @param n The node to interact with.
|
||||
*/
|
||||
public static void handleObjectInteraction(final Player player, Node n)
|
||||
{
|
||||
handleObjectInteraction(player, 0, n.getLocation(), n.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles object interaction
|
||||
* @param player The interacting player.
|
||||
* @param optionIndex The option index.
|
||||
* @param l The (x,y) location of the object.
|
||||
* @param objectId The object id.
|
||||
*/
|
||||
public static void handleObjectInteraction(final Player player, int optionIndex, Location l, int objectId) {
|
||||
handleObjectInteraction(player, optionIndex, l.getX(), l.getY(), objectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles object interaction
|
||||
* @param player The interacting player.
|
||||
* @param optionIndex The option index.
|
||||
* @param x The x-coordinate of the object.
|
||||
* @param y The y-coordinate of the object.
|
||||
* @param objectId The object id.
|
||||
*/
|
||||
public static void handleObjectInteraction(final Player player, int optionIndex, int x, int y, int objectId) {
|
||||
GameObject object = RegionManager.getObject(player.getLocation().getZ(), x, y, objectId);
|
||||
if (objectId == 29735) {//player safety.
|
||||
player.getPulseManager().run(new MovementPulse(player, Location.create(x, y, player .getLocation().getZ())) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.getDialogueInterpreter().sendDialogue("There appears to be a tunnel behind the poster.");
|
||||
player.getDialogueInterpreter().addAction((player1, buttonId) -> player1.teleport(new Location(3140, 4230, 2)));
|
||||
return true;
|
||||
}
|
||||
}, "movement");
|
||||
return;
|
||||
}
|
||||
if (objectId == 6898) {
|
||||
object = new GameObject(6898, new Location(3219, 9618));
|
||||
} else if (objectId == 6899) {
|
||||
object = new GameObject(6899, new Location(3221, 9618));
|
||||
}
|
||||
if (object == null || object.getId() != objectId) {
|
||||
player.debug("GameObject(" + objectId + ") interaction was " + object + " at location " + x + ", " + y + ".");
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
Interaction.handleInvalidInteraction(player, object, Option.NULL);
|
||||
return;
|
||||
}
|
||||
if (!object.isActive()) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
Interaction.handleInvalidInteraction(player, object, Option.NULL);
|
||||
return;
|
||||
}
|
||||
object = object.getChild(player);
|
||||
Option option = object.getInteraction().get(optionIndex);
|
||||
if (option == null) {
|
||||
player.debug("Invalid option" + object + ", original: " + objectId + ".");
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
Interaction.handleInvalidInteraction(player, object, Option.NULL);
|
||||
return;
|
||||
}
|
||||
player.debug(object + ", original=" + objectId + ", option=" + option.getName() + "");
|
||||
player.debug("dir=" + object.getDirection());
|
||||
VarbitDefinition def = VarbitDefinition.forObjectID(ObjectDefinition.forId(objectId).getVarbitID());
|
||||
player.debug("Varp ID=" + def.getConfigId() + " Offset=" + def.getBitShift() + " Size=" + def.getBitSize());
|
||||
if (option.getHandler() != null) {
|
||||
player.debug("Object handler: " + option.getHandler().getClass().getSimpleName());
|
||||
}
|
||||
handleAIPLegion(player, 1, optionIndex, x, y, objectId);
|
||||
|
||||
if(Listeners.run(object.getId(),1, option.getName(),player,object)){
|
||||
return;
|
||||
}
|
||||
if(PluginInteractionManager.handle(player,object)){
|
||||
return;
|
||||
}
|
||||
object.getInteraction().handle(player, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles player interaction.
|
||||
* @param player The player interacting.
|
||||
* @param optionIndex The option index.
|
||||
* @param index The target index.
|
||||
*/
|
||||
private static void handlePlayerInteraction(Player player, int optionIndex, int index) {
|
||||
if (index < 1 || index > ServerConstants.MAX_PLAYERS) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
return;
|
||||
}
|
||||
final Player target = Repository.getPlayers().get(index);
|
||||
if (target == null || !target.isActive()) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
return;
|
||||
}
|
||||
final Option option = player.getInteraction().get(optionIndex);
|
||||
//Handling for "Pelt" option
|
||||
if(option.getName().toLowerCase().equals("pelt")){
|
||||
|
||||
}
|
||||
if (option == null) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
return;
|
||||
}
|
||||
handleAIPLegion(player, 2, optionIndex, index);
|
||||
target.getInteraction().handle(player, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the ground item interaction.
|
||||
* @param player The player.
|
||||
* @param index The index of the reward.
|
||||
* @param itemId The item id.
|
||||
* @param location The location of the item.
|
||||
*/
|
||||
private static void handleGroundItemInteraction(final Player player, int index, int itemId, Location location) {
|
||||
final GroundItem item = GroundItemManager.get(itemId, location, player);
|
||||
SpecialGroundItems[] groundItems = SpecialGroundItems.values();
|
||||
for(SpecialGroundItems specialItem : groundItems){
|
||||
if(specialItem.getItemid() == itemId && specialItem.getLocation().getX() == location.getX() && specialItem.getLocation().getY() == location.getY()){
|
||||
player.debug("Using special ground item handler");
|
||||
specialItem.getInteraction().handle(player,item.getInteraction().get(index));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (item == null) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
return;
|
||||
}
|
||||
final Option option = item.getInteraction().get(index);
|
||||
if (option == null) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
Interaction.handleInvalidInteraction(player, item, Option.NULL);
|
||||
return;
|
||||
}
|
||||
if(PluginInteractionManager.handle(player,item,option)){
|
||||
player.debug("Handled by quest interaction manager.");
|
||||
return;
|
||||
}
|
||||
item.getInteraction().handle(player, option);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the AIPlayer legion.
|
||||
* @param player The player.
|
||||
* @param type The interaction type.
|
||||
* @param args The arguments.
|
||||
*/
|
||||
private static void handleAIPLegion(Player player, int type, int... args) {
|
||||
if (player.isArtificial()) {
|
||||
List<AIPlayer> legion = player.getAttribute("aip_legion");
|
||||
if (legion != null) {
|
||||
for (AIPlayer aip : legion) {
|
||||
if (aip != player) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
handleNPCInteraction(aip, args[0], args[1]);
|
||||
break;
|
||||
case 1:
|
||||
handleObjectInteraction(aip, args[0], args[1], args[2], args[3]);
|
||||
break;
|
||||
case 2:
|
||||
handlePlayerInteraction(aip, args[0], args[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player instance (used for AIP controlling).
|
||||
* @param player The player.
|
||||
* @return The player instance, or the AIP when the player is controlling an
|
||||
* AIP.
|
||||
*/
|
||||
private static Player getPlayer(Player player) {
|
||||
AIPlayer aip = player.getAttribute("aip_select");
|
||||
if (aip != null && aip.getLocation().withinDistance(player.getLocation())) {
|
||||
return aip;
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.ServerConstants;
|
||||
import core.game.node.entity.skill.magic.MagicSpell;
|
||||
import core.game.node.entity.skill.summoning.familiar.FamiliarSpecial;
|
||||
import core.game.interaction.MovementPulse;
|
||||
import core.game.node.entity.combat.CombatSwingHandler;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.SpellBookManager;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.object.GameObject;
|
||||
import core.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.repository.Repository;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
|
||||
/**
|
||||
* Handles the Interface "Use" on packets.
|
||||
* @author Stacx
|
||||
*/
|
||||
public class InterfaceUseOnPacket implements IncomingPacket {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void decode(final Player player, int opcode, IoBuffer buffer) {
|
||||
int payload;
|
||||
int interfaceId;
|
||||
int componentId;
|
||||
int itemId;
|
||||
int x;
|
||||
int y;
|
||||
switch (buffer.opcode()) {
|
||||
case 73: // Interface On GroundItem
|
||||
componentId = buffer.getShort();
|
||||
interfaceId = buffer.getShort();
|
||||
y = buffer.getShort();
|
||||
itemId = buffer.getLEShortA();
|
||||
x = buffer.getLEShortA();
|
||||
final int spell = buffer.getLEShort();
|
||||
final Item groundItem = GroundItemManager.get(itemId, Location.create(x, y, player.getLocation().getZ()), player);
|
||||
if (groundItem == null || !player.getLocation().withinDistance(groundItem.getLocation())) {
|
||||
break;
|
||||
}
|
||||
if (player.getAttribute("magic:delay", -1) > GameWorld.getTicks()) {
|
||||
break;
|
||||
}
|
||||
if (player.getZoneMonitor().clickButton(interfaceId, componentId, spell, itemId, opcode)) {
|
||||
break;
|
||||
}
|
||||
if (CombatSwingHandler.isProjectileClipped(player, groundItem, false)) {
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.MODERN, spell, groundItem);
|
||||
} else {
|
||||
player.getPulseManager().run(new MovementPulse(player, groundItem) {
|
||||
@Override
|
||||
public boolean update() {
|
||||
if (CombatSwingHandler.isProjectileClipped(player, groundItem, false)) {
|
||||
super.destination = player.getLocation();
|
||||
}
|
||||
boolean finished = super.update();
|
||||
if (finished) {
|
||||
player.getWalkingQueue().reset();
|
||||
}
|
||||
return finished;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.MODERN, spell, groundItem);
|
||||
return true;
|
||||
}
|
||||
}, "movement");
|
||||
}
|
||||
break;
|
||||
case 195: // Interface On Player
|
||||
payload = buffer.getShortA();
|
||||
componentId = buffer.getLEShort();
|
||||
interfaceId = buffer.getLEShort();
|
||||
int targetIndex = buffer.getLEShortA();
|
||||
// Logger.log("Interface:" + interfaceId+ " Component:" +
|
||||
// componentId + " Target Index:"+ targetIndex);
|
||||
//System.out.println("magic on player component = "+componentId+"!");
|
||||
final Player target = Repository.getPlayers().get(targetIndex);
|
||||
if (target == null || !player.getLocation().withinDistance(target.getLocation())) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
break;
|
||||
}
|
||||
switch (interfaceId) {
|
||||
case 192:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.MODERN, componentId, target);
|
||||
break;
|
||||
case 193:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.ANCIENT, componentId, target);
|
||||
break;
|
||||
case 430:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.LUNAR, componentId, target);
|
||||
break;
|
||||
case 662:
|
||||
switch (componentId) {
|
||||
case 67:
|
||||
case 69:
|
||||
case 119:
|
||||
case 121:
|
||||
default:
|
||||
if (!player.getFamiliarManager().hasFamiliar()) {
|
||||
player.getPacketDispatch().sendMessage("You don't have a familiar.");
|
||||
} else {
|
||||
player.getFamiliarManager().getFamiliar().executeSpecialMove(new FamiliarSpecial(target));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
player.debug("Option usage [inter=" + interfaceId + ", child=" + componentId + ", target=" + target + "].");
|
||||
}
|
||||
break;
|
||||
case 233: // Interface On Object
|
||||
y = buffer.getLEShortA();
|
||||
x = buffer.getShortA();
|
||||
itemId = buffer.getLEShortA();
|
||||
if (itemId == 65535) {
|
||||
itemId = -1;
|
||||
}
|
||||
payload = buffer.getIntA();
|
||||
interfaceId = payload >> 16;
|
||||
componentId = payload & 0xFFFF;
|
||||
int objectId = buffer.getShortA();
|
||||
player.debug("Option usage [inter=" + interfaceId + ", child=" + componentId + ", target=(" + objectId + "," + x + "," + y + "), item=" + itemId + "].");
|
||||
GameObject object = RegionManager.getObject(player.getLocation().getZ(), x, y);
|
||||
if (object == null) {
|
||||
object = RegionManager.getObject(Location.create(x, y, 0));
|
||||
}
|
||||
if (object != null) {
|
||||
object = object.getChild(player);
|
||||
}
|
||||
if (object == null || (object.getId() != objectId && object.getWrapper().getId() != objectId) || !player.getLocation().withinDistance(object.getLocation())) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
break;
|
||||
}
|
||||
switch (interfaceId) {
|
||||
case 430:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.LUNAR, componentId, object);
|
||||
break;
|
||||
case 192:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.MODERN, componentId, object);
|
||||
break;
|
||||
case 662:
|
||||
switch (componentId) {
|
||||
case 137:
|
||||
default:
|
||||
player.getFamiliarManager().getFamiliar().executeSpecialMove(new FamiliarSpecial(object));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 239: // Interface On NPC
|
||||
componentId = buffer.getLEShort();
|
||||
interfaceId = buffer.getLEShort();
|
||||
int unknown = buffer.getShortA();
|
||||
int index = buffer.getLEShortA();
|
||||
if (index < 1 || index > ServerConstants.MAX_NPCS) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
break;
|
||||
}
|
||||
|
||||
NPC npc = Repository.getNpcs().get(index);
|
||||
if (npc == null || !player.getLocation().withinDistance(npc.getLocation())) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
break;
|
||||
}
|
||||
if (player.getAttribute("magic:delay", -1) > GameWorld.getTicks()) {
|
||||
break;
|
||||
}
|
||||
switch (interfaceId) {
|
||||
case 430:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.LUNAR, componentId, npc);
|
||||
break;
|
||||
case 192:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.MODERN, componentId, npc);
|
||||
break;
|
||||
case 193:
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.ANCIENT, componentId, npc);
|
||||
break;
|
||||
case 662:
|
||||
switch (componentId) {
|
||||
case 67:
|
||||
case 69:
|
||||
case 177:
|
||||
case 121:
|
||||
case 119:
|
||||
default:
|
||||
if (!player.getFamiliarManager().hasFamiliar()) {
|
||||
player.getPacketDispatch().sendMessage("You don't have a familiar.");
|
||||
} else {
|
||||
player.getFamiliarManager().getFamiliar().executeSpecialMove(new FamiliarSpecial(npc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
player.debug("Option usage [inter=" + interfaceId + ", child=" + componentId + ", target=" + npc + "].");
|
||||
}
|
||||
break;
|
||||
case 253: // Interface On Item
|
||||
componentId = buffer.getLEShort();
|
||||
interfaceId = buffer.getLEShort();
|
||||
int itemSlot = buffer.getLEShortA();
|
||||
itemId = buffer.getShortA();
|
||||
unknown = buffer.getShortA();
|
||||
if (itemSlot < 0 || itemSlot > 27) {
|
||||
break;
|
||||
}
|
||||
Item item = player.getInventory().get(itemSlot);
|
||||
if (item == null) {
|
||||
break;
|
||||
}
|
||||
switch (interfaceId) {
|
||||
case 430:
|
||||
if (player.getAttribute("magic:delay", -1) > GameWorld.getTicks()) {
|
||||
break;
|
||||
}
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.LUNAR, componentId, item);
|
||||
break;
|
||||
case 192:
|
||||
if (player.getAttribute("magic:delay", -1) > GameWorld.getTicks()) {
|
||||
break;
|
||||
}
|
||||
MagicSpell.castSpell(player, SpellBookManager.SpellBook.MODERN, componentId, item);
|
||||
break;
|
||||
case 662:
|
||||
if (player.getFamiliarManager().hasFamiliar()) {
|
||||
player.getFamiliarManager().getFamiliar().executeSpecialMove(new FamiliarSpecial(item, interfaceId, componentId, item));
|
||||
} else {
|
||||
player.getPacketDispatch().sendMessage("You don't have a follower.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
player.debug("Option usage [inter=" + interfaceId + ", child=" + componentId + ", target=" + item + "].");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.interaction.*;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.skill.farming.CompostBins;
|
||||
import core.game.node.entity.skill.farming.FarmingPatch;
|
||||
import core.game.node.entity.skill.farming.UseWithBinHandler;
|
||||
import core.game.node.entity.skill.farming.UseWithPatchHandler;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.object.GameObject;
|
||||
import core.game.system.SystemLogger;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.repository.Repository;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
import core.tools.Items;
|
||||
import core.game.system.command.rottenpotato.RottenPotatoUseWithHandler;
|
||||
import core.game.content.quest.PluginInteractionManager;
|
||||
|
||||
/**
|
||||
* The incoming item reward packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class ItemActionPacket implements IncomingPacket {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
if (player.getLocks().isInteractionLocked()) {
|
||||
return;
|
||||
}
|
||||
int usedWithItemId = -1;
|
||||
int usedWithSlot = -1;
|
||||
int interfaceHash1 = -1;
|
||||
int interfaceId1 = -1;
|
||||
int childId1 = -1;
|
||||
int usedItemId = -1;
|
||||
int usedSlot = -1;
|
||||
int interfaceHash2 = -1;
|
||||
int interfaceId2 = -1;
|
||||
int childId2 = -1;
|
||||
NodeUsageEvent event = null;
|
||||
Item used = null;
|
||||
switch (buffer.opcode()) {
|
||||
case 115: // Item on NPC
|
||||
int interfaceId = buffer.getIntA() >> 16;
|
||||
int slotId = buffer.getLEShort();
|
||||
int npcIndex = buffer.getLEShort();
|
||||
int itemId = buffer.getLEShortA();
|
||||
NPC npc = Repository.getNpcs().get(npcIndex);
|
||||
Item item = player.getInventory().get(slotId);
|
||||
if (item == null || item.getId() != itemId) {
|
||||
return;
|
||||
}
|
||||
if(itemId == Items.ROTTEN_POTATO_5733){
|
||||
RottenPotatoUseWithHandler.handle(npc,player);
|
||||
return;
|
||||
}
|
||||
event = new NodeUsageEvent(player, interfaceId, item, npc);
|
||||
if(PluginInteractionManager.handle(player,event)){
|
||||
return;
|
||||
}
|
||||
event = new NodeUsageEvent(player, interfaceId, item, npc);
|
||||
try {
|
||||
UseWithHandler.run(event);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
case 248: // Item on Player
|
||||
int playerIndex = buffer.getLEShortA();
|
||||
itemId = buffer.getShort();
|
||||
slotId = buffer.getShort();
|
||||
interfaceId = buffer.getInt() >> 16;
|
||||
Player target = Repository.getPlayers().get(playerIndex);
|
||||
item = player.getInventory().get(slotId);
|
||||
if (target == null || item == null || item.getId() != itemId) {
|
||||
return;
|
||||
}
|
||||
if(itemId == Items.ROTTEN_POTATO_5733){
|
||||
RottenPotatoUseWithHandler.handle(target,player);
|
||||
return;
|
||||
}
|
||||
event = new NodeUsageEvent(player, interfaceId, item, target);
|
||||
if(PluginInteractionManager.handle(player,event)){
|
||||
return;
|
||||
}
|
||||
event = new NodeUsageEvent(player, interfaceId, item, target);
|
||||
try {
|
||||
UseWithHandler.run(event);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
case 27://Item on Item
|
||||
usedSlot = buffer.getShort();
|
||||
interfaceHash1 = buffer.getLEInt();
|
||||
usedWithSlot = buffer.getLEShort();
|
||||
interfaceHash2 = buffer.getLEInt();
|
||||
usedItemId = buffer.getLEShortA();
|
||||
usedWithItemId = buffer.getLEShortA();
|
||||
interfaceId1 = interfaceHash1 >> 16;
|
||||
childId1 = interfaceHash1 & 0xFFFF;
|
||||
interfaceId2 = interfaceHash2 >> 16;
|
||||
childId2 = interfaceHash2 & 0xFFFF;
|
||||
used = player.getInventory().get(usedSlot);
|
||||
Item with = player.getInventory().get(usedWithSlot);
|
||||
if (used == null || with == null || used.getId() != usedItemId || with.getId() != usedWithItemId) {
|
||||
return;
|
||||
}
|
||||
if(used.getId() == Items.ROTTEN_POTATO_5733){
|
||||
RottenPotatoUseWithHandler.handle(with,player);
|
||||
return;
|
||||
}
|
||||
if(with.getId() == Items.ROTTEN_POTATO_5733){
|
||||
RottenPotatoUseWithHandler.handle(used,player);
|
||||
return;
|
||||
}
|
||||
if (usedItemId < usedWithItemId) {
|
||||
item = used;
|
||||
used = with;
|
||||
with = item;
|
||||
}
|
||||
player.debug("USED: " + used + " WITH: " + with);
|
||||
event = new NodeUsageEvent(player, interfaceId1, used, with);
|
||||
if(PluginInteractionManager.handle(player,event)){
|
||||
return;
|
||||
}
|
||||
event = new NodeUsageEvent(player, interfaceId1, used, with);
|
||||
try {
|
||||
UseWithHandler.run(event);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case 134://Item on Object
|
||||
int x = buffer.getShortA();
|
||||
int id = buffer.getShort();
|
||||
int y = buffer.getLEShort();
|
||||
int slot = buffer.getShort();
|
||||
buffer.getLEShort();
|
||||
buffer.getShort();
|
||||
int objectId = buffer.getShortA();
|
||||
int z = player.getLocation().getZ();
|
||||
GameObject object = RegionManager.getObject(z, x, y);
|
||||
if(objectId != 6898) {
|
||||
if (object == null || object.getId() != objectId) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
return;
|
||||
}
|
||||
object = object.getChild(player);
|
||||
if (object == null) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
object = new GameObject(6898,x,y,z);
|
||||
}
|
||||
used = player.getInventory().get(slot);
|
||||
if (used == null || used.getId() != id) {
|
||||
return;
|
||||
}
|
||||
if(used.getId() == Items.ROTTEN_POTATO_5733){
|
||||
RottenPotatoUseWithHandler.handle(object,player);
|
||||
return;
|
||||
}
|
||||
event = new NodeUsageEvent(player, 0, used, object);
|
||||
|
||||
/**
|
||||
* Farming-specific handler for item -> patch
|
||||
*/
|
||||
if(FarmingPatch.forObject(object) != null && UseWithPatchHandler.allowedNodes.contains(used.getId())){
|
||||
NodeUsageEvent finalEvent = event;
|
||||
player.getPulseManager().run(new MovementPulse(player,object, DestinationFlag.OBJECT) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.faceLocation(destination.getLocation());
|
||||
UseWithPatchHandler.handle(finalEvent);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Farming-specific handler for item -> compost bin
|
||||
*/
|
||||
if(CompostBins.forObject(object) != null && UseWithBinHandler.allowedNodes.contains(used.getId())){
|
||||
NodeUsageEvent finalEvent = event;
|
||||
player.getPulseManager().run(new MovementPulse(player,object,DestinationFlag.OBJECT){
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.faceLocation(destination.getLocation());
|
||||
UseWithBinHandler.handle(finalEvent);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if(PluginInteractionManager.handle(player,event)){
|
||||
return;
|
||||
}
|
||||
if(object.getName().toLowerCase().contains("bank booth")){
|
||||
new ItemOnBankBooth().handle(event);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
UseWithHandler.run(event);
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
return;
|
||||
default:
|
||||
SystemLogger.logErr("Error in Item Action Packet! Unhandled opcode = " + buffer.opcode());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
public class MapClosedPacket implements IncomingPacket {
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
//This buffer contains an int that is actually a bunch of booleans bitshifted into specific positions. No clue what the use might be.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles incoming mouse click packets.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class MouseClickPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
int data = buffer.getLEShortA();
|
||||
int positioning = buffer.getIntB();
|
||||
boolean rightClick = ((data >> 15) & 0x1) == 1;
|
||||
int delay = data & 0x7FF;
|
||||
int x = positioning >> 16;
|
||||
int y = positioning & 0xFFFF;
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
player.getMonitor().handleMouseClick(x, y, delay, rightClick);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles music-related incoming packets.
|
||||
* @author Ceikry
|
||||
*/
|
||||
public final class MusicPacketHandler implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
int musicId = buffer.getLEShortA();
|
||||
if (player.getMusicPlayer().isLooping()) {
|
||||
player.getMusicPlayer().replay();
|
||||
return;
|
||||
}
|
||||
player.getMusicPlayer().setPlaying(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles an incoming ping packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class PingPacketHandler implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Packet received when a player's region has changed.
|
||||
* @author Emperor
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public class RegionChangePacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
//TODO: no data is sen't so not sure what to do.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.ServerConstants;
|
||||
import core.game.content.global.report.AbuseReport;
|
||||
import core.game.content.global.report.Rule;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Represents the incoming packet to handle a report against a player.
|
||||
* @author Vexia
|
||||
*/
|
||||
public class ReportAbusePacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
String target = StringUtils.longToString(buffer.getLong());
|
||||
Rule rule = Rule.forId(buffer.get());
|
||||
boolean mute = buffer.get() == 1;
|
||||
File file = new File(ServerConstants.PLAYER_SAVE_PATH + target + ".save");
|
||||
if (!file.exists()) {
|
||||
player.getPacketDispatch().sendMessage("Invalid player name.");
|
||||
return;
|
||||
}
|
||||
if (target.equalsIgnoreCase(player.getUsername())) {
|
||||
player.getPacketDispatch().sendMessage("You can't report yourself!");
|
||||
return;
|
||||
}
|
||||
AbuseReport abuse = new AbuseReport(player.getName(), target, rule);
|
||||
abuse.construct(player, mute);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.RunScript;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.tools.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents the incoming packet to handle a run script.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public class RunScriptPacketHandler implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
final RunScript script = player.getAttribute("runscript", null);
|
||||
if (script == null || player.getLocks().isInteractionLocked()) {
|
||||
return;
|
||||
}
|
||||
Object value = "";
|
||||
if (opcode == 244) {
|
||||
value = StringUtils.longToString(buffer.getLong());
|
||||
} else if (opcode == 23) {
|
||||
value = buffer.getInt();
|
||||
} else if (opcode == 65){
|
||||
value = buffer.getString();//"longInput"
|
||||
} else {
|
||||
value = buffer.getInt();
|
||||
}
|
||||
script.setValue(value);
|
||||
script.setPlayer(player);
|
||||
player.removeAttribute("runscript");
|
||||
script.handle();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.container.Container;
|
||||
import core.game.container.impl.BankContainer;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.item.Item;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Represents the packet to handle an item slot switch.
|
||||
* @author 'Vexia
|
||||
*/
|
||||
public class SlotSwitchPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
if (buffer.opcode() == 79) {
|
||||
int interfaceHash = buffer.getIntB();
|
||||
int secondSlot = buffer.getLEShort();
|
||||
int interfaceHash2 = buffer.getInt();
|
||||
int slot = buffer.getLEShort();
|
||||
int interfaceId = interfaceHash >> 16;
|
||||
int childId = interfaceHash & 0xFF;
|
||||
int withInterfaceId = interfaceHash2 >> 16;
|
||||
int withChildId = interfaceHash2 & 0xFF;
|
||||
Container container = player.getInventory();
|
||||
switch (interfaceId) {
|
||||
case 762:
|
||||
if (withInterfaceId == 762) {
|
||||
if (withChildId == 73) {
|
||||
container = player.getBank();
|
||||
switchItem(slot, secondSlot, container, player.getBank().isInsertItems(), player);
|
||||
player.debug("Switching item [" + slot + ", " + interfaceId + ", " + childId + "] with [" + secondSlot + ", " + withInterfaceId + ", " + withChildId + "]!");
|
||||
}
|
||||
else {
|
||||
int tabIndex = BankContainer.getArrayIndex(withChildId);
|
||||
if (tabIndex > -1) {
|
||||
secondSlot = tabIndex == 10 ? player.getBank().freeSlot() : player.getBank().getTabStartSlot()[tabIndex] + player.getBank().getItemsInTab(tabIndex);
|
||||
childId = player.getBank().getTabByItemSlot(slot);
|
||||
if (secondSlot > slot) {
|
||||
player.getBank().insert(slot, secondSlot - 1);
|
||||
} else if (slot > secondSlot) {
|
||||
player.getBank().insert(slot, secondSlot);
|
||||
}
|
||||
player.getBank().increaseTabStartSlots(tabIndex);
|
||||
player.getBank().decreaseTabStartSlots(childId);
|
||||
player.getBank().setTabConfigurations();
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
player.debug("Switching item slot [from=" + slot + ", to=" + secondSlot + ", child=" + childId + ", to child=" + withChildId + "].");
|
||||
switchItem(slot, secondSlot, container, false, player);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
int slot = buffer.getShort();
|
||||
int interfaceHash = buffer.getLEInt();
|
||||
int secondSlot = buffer.getShortA();
|
||||
boolean insert = buffer.get() == 1;
|
||||
int interfaceId = interfaceHash >> 16;
|
||||
Container container = interfaceId == 762 ? player.getBank() : (interfaceId == 15 || interfaceId == 149 || interfaceId == 763) ? player.getInventory() : null;
|
||||
switchItem(slot, secondSlot, container, insert, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches an item.
|
||||
* @param slot The slot.
|
||||
* @param secondSlot The slot to switch slots with.
|
||||
* @param container The container.
|
||||
* @param insert If inserting should happen.
|
||||
*/
|
||||
public void switchItem(int slot, int secondSlot, Container container, boolean insert, Player player) {
|
||||
if (container == null || slot < 0 || slot >= container.toArray().length || secondSlot < 0 || secondSlot >= container.toArray().length) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Item item = container.get(slot);
|
||||
final Item second = container.get(secondSlot);
|
||||
if (player.getInterfaceManager().hasChatbox()) {
|
||||
player.getInterfaceManager().closeChatbox();
|
||||
switchItem(secondSlot,slot,container,insert,player);
|
||||
container.refresh();
|
||||
return;
|
||||
}
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
if (!insert) {
|
||||
container.replace(second, slot, false);
|
||||
container.replace(item, secondSlot, false);
|
||||
if (item != null) {
|
||||
item.setIndex(secondSlot);
|
||||
}
|
||||
if (second != null) {
|
||||
second.setIndex(slot);
|
||||
}
|
||||
} else {
|
||||
container.insert(slot, secondSlot, false);
|
||||
}
|
||||
container.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
|
||||
/**
|
||||
* Handles the update interface packet counter packet.
|
||||
* @author Emperor
|
||||
*
|
||||
*/
|
||||
public final class UpdateInterfaceCounter implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
int count = buffer.getShort() - player.getInterfaceManager().getPacketCount(0);
|
||||
player.getInterfaceManager().getPacketCount(count);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package core.net.packet.in;
|
||||
|
||||
import core.game.interaction.MovementPulse;
|
||||
import core.game.node.entity.Entity;
|
||||
import core.game.node.entity.player.Player;
|
||||
import plugin.ai.AIPlayer;
|
||||
import core.game.world.map.Location;
|
||||
import core.net.packet.IncomingPacket;
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.PacketRepository;
|
||||
import core.net.packet.context.PlayerContext;
|
||||
import core.net.packet.out.ClearMinimapFlag;
|
||||
|
||||
/**
|
||||
* Handles an incoming walk packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public final class WalkPacket implements IncomingPacket {
|
||||
|
||||
@Override
|
||||
public void decode(Player player, int opcode, IoBuffer buffer) {
|
||||
player = getPlayer(player);
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
if (player.getLocks().isMovementLocked() || !player.getInterfaceManager().close() || !player.getInterfaceManager().closeSingleTab() || !player.getDialogueInterpreter().close()) {
|
||||
PacketRepository.send(ClearMinimapFlag.class, new PlayerContext(player));
|
||||
player.debug("[WalkPacket] did not handle - [locked=" + player.getLocks().isMovementLocked() + "]!");
|
||||
return;
|
||||
}
|
||||
player.getProperties().setSpell(null);
|
||||
player.getInterfaceManager().close();
|
||||
player.getInterfaceManager().closeChatbox();
|
||||
player.getDialogueInterpreter().getActions().clear();
|
||||
boolean running = buffer.getA() == 1;
|
||||
int x = buffer.getShort();
|
||||
int y = buffer.getShortA();
|
||||
int steps = (buffer.toByteBuffer().remaining() - (buffer.opcode() == 39 ? 14 : 0)) >> 1;
|
||||
for (int i = 0; i < steps; i++) {
|
||||
int offsetX = buffer.getA();
|
||||
int offsetY = buffer.getS();
|
||||
if (i == steps - 1) {
|
||||
x += offsetX;
|
||||
y += offsetY;
|
||||
}
|
||||
}
|
||||
if (opcode == 77) {
|
||||
player.getWalkingQueue().setRunning(running);
|
||||
return; // Action walking.
|
||||
}
|
||||
player.face((Entity) null);
|
||||
player.faceLocation((Location) null);
|
||||
//player.getWalkingQueue().reset(running);
|
||||
player.getPulseManager().run(new MovementPulse(player, Location.create(x, y, player.getLocation().getZ()), running) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
return true;
|
||||
}
|
||||
}, true, "movement");
|
||||
if (opcode == 39) {
|
||||
buffer.get(); // The x-coordinate of where we clicked on the
|
||||
// minimap.
|
||||
buffer.get(); // The y-coordinate of where we clicked on the
|
||||
// minimap.
|
||||
buffer.getShort(); // The rotation of the minimap.
|
||||
buffer.get(); // Always 57.
|
||||
buffer.get();
|
||||
buffer.get();
|
||||
buffer.get(); // Always 89
|
||||
buffer.getShort();
|
||||
buffer.getShort();
|
||||
buffer.get();
|
||||
buffer.get(); // Always 63
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player instance (used for AIP controlling).
|
||||
* @param player The player.
|
||||
* @return The player instance, or the AIP when the player is controlling an
|
||||
* AIP.
|
||||
*/
|
||||
private static Player getPlayer(Player player) {
|
||||
if (player == null) {
|
||||
return null;
|
||||
}
|
||||
AIPlayer aip = player.getAttribute("aip_select");
|
||||
if (aip != null && aip.getLocation().withinDistance(player.getLocation())) {
|
||||
if (!player.getAttribute("aip_perm_select", true)) {
|
||||
player.removeAttribute("aip_select");
|
||||
}
|
||||
return aip;
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package core.net.packet.out;
|
||||
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.OutgoingPacket;
|
||||
import core.net.packet.context.AccessMaskContext;
|
||||
|
||||
/**
|
||||
* The access mask outgoing packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class AccessMask implements OutgoingPacket<AccessMaskContext> {
|
||||
|
||||
@Override
|
||||
public void send(AccessMaskContext context) {
|
||||
IoBuffer buffer = new IoBuffer(165);
|
||||
buffer.putLEShort(context.getPlayer().getInterfaceManager().getPacketCount(1));
|
||||
buffer.putLEShort(context.getLength());
|
||||
buffer.putInt(context.getInterfaceId() << 16 | context.getChildId());
|
||||
buffer.putShortA(context.getOffset());
|
||||
buffer.putIntA(context.getId());
|
||||
buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());context.getPlayer().getSession().write(buffer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package core.net.packet.out;
|
||||
|
||||
import core.net.packet.IoBuffer;
|
||||
import core.net.packet.OutgoingPacket;
|
||||
import core.net.packet.context.AnimateInterfaceContext;
|
||||
|
||||
/**
|
||||
* The animate interface outgoing packet.
|
||||
* @author Emperor
|
||||
*/
|
||||
public class AnimateInterface implements OutgoingPacket<AnimateInterfaceContext> {
|
||||
|
||||
@Override
|
||||
public void send(AnimateInterfaceContext context) {
|
||||
IoBuffer buffer = new IoBuffer(36);
|
||||
buffer.putIntB((context.getInterfaceId() << 16) + context.getChildId());
|
||||
buffer.putLEShort(context.getAnimationId());
|
||||
buffer.putShortA(context.getPlayer().getInterfaceManager().getPacketCount(1));
|
||||
buffer.cypherOpcode(context.getPlayer().getSession().getIsaacPair().getOutput());context.getPlayer().getDetails().getSession().write(buffer);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user