uhhh go brrr?

This commit is contained in:
Ceikry
2021-03-11 20:42:32 -06:00
parent 89d51b788b
commit 76c7b16108
2757 changed files with 0 additions and 0 deletions
@@ -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);
}
+120
View File
@@ -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