mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 00:38:21 +00:00
Class member sorting.
This commit is contained in:
@@ -43,7 +43,7 @@ public final class IsaacRandom {
|
||||
/**
|
||||
* A mask for pseudorandom lookup.
|
||||
*/
|
||||
private static int MASK = (SIZE - 1) << 2;
|
||||
private static int MASK = SIZE - 1 << 2;
|
||||
|
||||
/**
|
||||
* The count through the results in the results array.
|
||||
@@ -98,66 +98,6 @@ public final class IsaacRandom {
|
||||
init(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 256 results.
|
||||
*/
|
||||
private void isaac() {
|
||||
int i, j, x, y;
|
||||
|
||||
b += ++c;
|
||||
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
|
||||
x = mem[i];
|
||||
a ^= a << 13;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 6;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a << 2;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 16;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
}
|
||||
|
||||
for (j = 0; j < SIZE / 2;) {
|
||||
x = mem[i];
|
||||
a ^= a << 13;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 6;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a << 2;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 16;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[((y >> SIZEL) & MASK) >> 2] + x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises this random number generator.
|
||||
*
|
||||
@@ -289,6 +229,66 @@ public final class IsaacRandom {
|
||||
count = SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 256 results.
|
||||
*/
|
||||
private void isaac() {
|
||||
int i, j, x, y;
|
||||
|
||||
b += ++c;
|
||||
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
|
||||
x = mem[i];
|
||||
a ^= a << 13;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 6;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a << 2;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 16;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
}
|
||||
|
||||
for (j = 0; j < SIZE / 2;) {
|
||||
x = mem[i];
|
||||
a ^= a << 13;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 6;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a << 2;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
|
||||
x = mem[i];
|
||||
a ^= a >>> 16;
|
||||
a += mem[j++];
|
||||
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
|
||||
rsl[i++] = b = mem[(y >> SIZEL & MASK) >> 2] + x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next random value.
|
||||
*
|
||||
|
||||
+26
-26
@@ -13,8 +13,8 @@ import org.apollo.game.model.World;
|
||||
import org.apollo.net.ApolloHandler;
|
||||
import org.apollo.net.HttpPipelineFactory;
|
||||
import org.apollo.net.JagGrabPipelineFactory;
|
||||
import org.apollo.net.ServicePipelineFactory;
|
||||
import org.apollo.net.NetworkConstants;
|
||||
import org.apollo.net.ServicePipelineFactory;
|
||||
import org.apollo.net.release.Release;
|
||||
import org.apollo.net.release.r317.Release317;
|
||||
import org.apollo.util.plugin.PluginContext;
|
||||
@@ -106,6 +106,31 @@ public final class Server {
|
||||
serviceManager = new ServiceManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the server to the specified address.
|
||||
*
|
||||
* @param serviceAddress The service address to bind to.
|
||||
* @param httpAddress The HTTP address to bind to.
|
||||
* @param jagGrabAddress The JAGGRAB address to bind to.
|
||||
*/
|
||||
public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) {
|
||||
logger.info("Binding service listener to address: " + serviceAddress + "...");
|
||||
serviceBootstrap.bind(serviceAddress);
|
||||
|
||||
logger.info("Binding HTTP listener to address: " + httpAddress + "...");
|
||||
try {
|
||||
httpBootstrap.bind(httpAddress);
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.WARNING,
|
||||
"Binding to HTTP failed: client will use JAGGRAB as a fallback (not recommended)!", t);
|
||||
}
|
||||
|
||||
logger.info("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
|
||||
jagGrabBootstrap.bind(jagGrabAddress);
|
||||
|
||||
logger.info("Ready for connections.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the server.
|
||||
*
|
||||
@@ -139,31 +164,6 @@ public final class Server {
|
||||
jagGrabBootstrap.setPipelineFactory(jagGrabPipelineFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the server to the specified address.
|
||||
*
|
||||
* @param serviceAddress The service address to bind to.
|
||||
* @param httpAddress The HTTP address to bind to.
|
||||
* @param jagGrabAddress The JAGGRAB address to bind to.
|
||||
*/
|
||||
public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) {
|
||||
logger.info("Binding service listener to address: " + serviceAddress + "...");
|
||||
serviceBootstrap.bind(serviceAddress);
|
||||
|
||||
logger.info("Binding HTTP listener to address: " + httpAddress + "...");
|
||||
try {
|
||||
httpBootstrap.bind(httpAddress);
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.WARNING,
|
||||
"Binding to HTTP failed: client will use JAGGRAB as a fallback (not recommended)!", t);
|
||||
}
|
||||
|
||||
logger.info("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
|
||||
jagGrabBootstrap.bind(jagGrabAddress);
|
||||
|
||||
logger.info("Ready for connections.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the server.
|
||||
*
|
||||
|
||||
@@ -60,15 +60,6 @@ public final class ServerContext {
|
||||
return release;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service manager.
|
||||
*
|
||||
* @return The service manager.
|
||||
*/
|
||||
public ServiceManager getServiceManager() {
|
||||
return serviceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a service. This method is shorthand for {@code getServiceManager().getService(...)}.
|
||||
*
|
||||
@@ -80,4 +71,13 @@ public final class ServerContext {
|
||||
return serviceManager.getService(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service manager.
|
||||
*
|
||||
* @return The service manager.
|
||||
*/
|
||||
public ServiceManager getServiceManager() {
|
||||
return serviceManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,18 @@ public final class ServiceManager {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a service.
|
||||
*
|
||||
* @param <S> The type of service.
|
||||
* @param clazz The service class.
|
||||
* @return The service.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S extends Service> S getService(Class<S> clazz) {
|
||||
return (S) services.get(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this service manager.
|
||||
*
|
||||
@@ -85,15 +97,14 @@ public final class ServiceManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a service.
|
||||
* Sets the context of all services.
|
||||
*
|
||||
* @param <S> The type of service.
|
||||
* @param clazz The service class.
|
||||
* @return The service.
|
||||
* @param ctx The server context.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S extends Service> S getService(Class<S> clazz) {
|
||||
return (S) services.get(clazz);
|
||||
public void setContext(ServerContext ctx) {
|
||||
for (Service s : services.values()) {
|
||||
s.setContext(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,15 +118,4 @@ public final class ServiceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the context of all services.
|
||||
*
|
||||
* @param ctx The server context.
|
||||
*/
|
||||
public void setContext(ServerContext ctx) {
|
||||
for (Service s : services.values()) {
|
||||
s.setContext(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,15 +28,6 @@ public final class FileDescriptor {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file type.
|
||||
*
|
||||
* @return The file type.
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file id.
|
||||
*
|
||||
@@ -46,4 +37,13 @@ public final class FileDescriptor {
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file type.
|
||||
*
|
||||
* @return The file type.
|
||||
*/
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ public final class Index {
|
||||
throw new IllegalArgumentException("Incorrect buffer length.");
|
||||
}
|
||||
|
||||
int size = ((buffer[0] & 0xFF) << 16) | ((buffer[1] & 0xFF) << 8) | (buffer[2] & 0xFF);
|
||||
int block = ((buffer[3] & 0xFF) << 16) | ((buffer[4] & 0xFF) << 8) | (buffer[5] & 0xFF);
|
||||
int size = (buffer[0] & 0xFF) << 16 | (buffer[1] & 0xFF) << 8 | buffer[2] & 0xFF;
|
||||
int block = (buffer[3] & 0xFF) << 16 | (buffer[4] & 0xFF) << 8 | buffer[5] & 0xFF;
|
||||
|
||||
return new Index(size, block);
|
||||
}
|
||||
@@ -46,15 +46,6 @@ public final class Index {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the file.
|
||||
*
|
||||
* @return The size of the file.
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first block of the file.
|
||||
*
|
||||
@@ -64,4 +55,13 @@ public final class Index {
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the file.
|
||||
*
|
||||
* @return The size of the file.
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,13 +48,21 @@ public final class IndexedFileSystem implements Closeable {
|
||||
detectLayout(base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this {@link IndexedFileSystem} is read only.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (data != null) {
|
||||
synchronized (data) {
|
||||
data.close();
|
||||
}
|
||||
}
|
||||
|
||||
for (RandomAccessFile index : indices) {
|
||||
if (index != null) {
|
||||
synchronized (index) {
|
||||
index.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,52 +95,6 @@ public final class IndexedFileSystem implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a file.
|
||||
*
|
||||
* @param fd The {@link FileDescriptor} which points to the file.
|
||||
* @return The {@link Index}.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
private Index getIndex(FileDescriptor fd) throws IOException {
|
||||
int index = fd.getType();
|
||||
if (index < 0 || index >= indices.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[FileSystemConstants.INDEX_SIZE];
|
||||
RandomAccessFile indexFile = indices[index];
|
||||
synchronized (indexFile) {
|
||||
long ptr = (long) fd.getFile() * (long) FileSystemConstants.INDEX_SIZE;
|
||||
if (ptr >= 0 && indexFile.length() >= (ptr + FileSystemConstants.INDEX_SIZE)) {
|
||||
indexFile.seek(ptr);
|
||||
indexFile.readFully(buffer);
|
||||
} else {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
return Index.decode(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of files with the specified type.
|
||||
*
|
||||
* @param type The type.
|
||||
* @return The number of files.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
private int getFileCount(int type) throws IOException {
|
||||
if (type < 0 || type >= indices.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
RandomAccessFile indexFile = indices[type];
|
||||
synchronized (indexFile) {
|
||||
return (int) (indexFile.length() / FileSystemConstants.INDEX_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CRC table.
|
||||
*
|
||||
@@ -171,9 +133,9 @@ public final class IndexedFileSystem implements Closeable {
|
||||
|
||||
// hash the CRCs and place them in the buffer
|
||||
ByteBuffer buf = ByteBuffer.allocate(crcs.length * 4 + 4);
|
||||
for (int i = 0; i < crcs.length; i++) {
|
||||
hash = (hash << 1) + crcs[i];
|
||||
buf.putInt(crcs[i]);
|
||||
for (int crc : crcs) {
|
||||
hash = (hash << 1) + crc;
|
||||
buf.putInt(crc);
|
||||
}
|
||||
|
||||
// place the hash into the buffer
|
||||
@@ -189,18 +151,6 @@ public final class IndexedFileSystem implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a file.
|
||||
*
|
||||
* @param type The file type.
|
||||
* @param file The file id.
|
||||
* @return A {@link ByteBuffer} which contains the contents of the file.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public ByteBuffer getFile(int type, int file) throws IOException {
|
||||
return getFile(new FileDescriptor(type, file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a file.
|
||||
*
|
||||
@@ -234,9 +184,9 @@ public final class IndexedFileSystem implements Closeable {
|
||||
ptr += FileSystemConstants.HEADER_SIZE;
|
||||
|
||||
// parse header
|
||||
int nextFile = ((header[0] & 0xFF) << 8) | (header[1] & 0xFF);
|
||||
int curChunk = ((header[2] & 0xFF) << 8) | (header[3] & 0xFF);
|
||||
int nextBlock = ((header[4] & 0xFF) << 16) | ((header[5] & 0xFF) << 8) | (header[6] & 0xFF);
|
||||
int nextFile = (header[0] & 0xFF) << 8 | header[1] & 0xFF;
|
||||
int curChunk = (header[2] & 0xFF) << 8 | header[3] & 0xFF;
|
||||
int nextBlock = (header[4] & 0xFF) << 16 | (header[5] & 0xFF) << 8 | header[6] & 0xFF;
|
||||
int nextType = header[7] & 0xFF;
|
||||
|
||||
// check expected chunk id is correct
|
||||
@@ -265,7 +215,7 @@ public final class IndexedFileSystem implements Closeable {
|
||||
// if we still have more data to read, check the validity of the
|
||||
// header
|
||||
if (size > read) {
|
||||
if (nextType != (fd.getType() + 1)) {
|
||||
if (nextType != fd.getType() + 1) {
|
||||
throw new IOException("File type mismatch.");
|
||||
}
|
||||
|
||||
@@ -279,21 +229,71 @@ public final class IndexedFileSystem implements Closeable {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (data != null) {
|
||||
synchronized (data) {
|
||||
data.close();
|
||||
}
|
||||
/**
|
||||
* Gets a file.
|
||||
*
|
||||
* @param type The file type.
|
||||
* @param file The file id.
|
||||
* @return A {@link ByteBuffer} which contains the contents of the file.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public ByteBuffer getFile(int type, int file) throws IOException {
|
||||
return getFile(new FileDescriptor(type, file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of files with the specified type.
|
||||
*
|
||||
* @param type The type.
|
||||
* @return The number of files.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
private int getFileCount(int type) throws IOException {
|
||||
if (type < 0 || type >= indices.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
for (RandomAccessFile index : indices) {
|
||||
if (index != null) {
|
||||
synchronized (index) {
|
||||
index.close();
|
||||
}
|
||||
}
|
||||
RandomAccessFile indexFile = indices[type];
|
||||
synchronized (indexFile) {
|
||||
return (int) (indexFile.length() / FileSystemConstants.INDEX_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a file.
|
||||
*
|
||||
* @param fd The {@link FileDescriptor} which points to the file.
|
||||
* @return The {@link Index}.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
private Index getIndex(FileDescriptor fd) throws IOException {
|
||||
int index = fd.getType();
|
||||
if (index < 0 || index >= indices.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[FileSystemConstants.INDEX_SIZE];
|
||||
RandomAccessFile indexFile = indices[index];
|
||||
synchronized (indexFile) {
|
||||
long ptr = (long) fd.getFile() * (long) FileSystemConstants.INDEX_SIZE;
|
||||
if (ptr >= 0 && indexFile.length() >= ptr + FileSystemConstants.INDEX_SIZE) {
|
||||
indexFile.seek(ptr);
|
||||
indexFile.readFully(buffer);
|
||||
} else {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
return Index.decode(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this {@link IndexedFileSystem} is read only.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ public final class Archive {
|
||||
int hash = 0;
|
||||
name = name.toUpperCase();
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
hash = (hash * 61 + name.charAt(i)) - 32;
|
||||
hash = hash * 61 + name.charAt(i) - 32;
|
||||
}
|
||||
for (ArchiveEntry entry : entries) {
|
||||
if (entry.getIdentifier() == hash) {
|
||||
|
||||
@@ -30,15 +30,6 @@ public final class ArchiveEntry {
|
||||
this.buffer = buffer.asReadOnlyBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier of this entry.
|
||||
*
|
||||
* @return The identifier of this entry.
|
||||
*/
|
||||
public int getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer of this entry.
|
||||
*
|
||||
@@ -48,4 +39,13 @@ public final class ArchiveEntry {
|
||||
return buffer.duplicate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier of this entry.
|
||||
*
|
||||
* @return The identifier of this entry.
|
||||
*/
|
||||
public int getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -64,6 +64,17 @@ public final class GameService extends Service {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the unregistration of a player.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
public void finalizePlayerUnregistration(Player player) {
|
||||
synchronized (this) {
|
||||
World.getWorld().unregister(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the event handler chains.
|
||||
*
|
||||
@@ -108,15 +119,6 @@ public final class GameService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the game service.
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
scheduledExecutor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY,
|
||||
GameConstants.PULSE_DELAY, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every pulse.
|
||||
*/
|
||||
@@ -157,6 +159,15 @@ public final class GameService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the game service.
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
scheduledExecutor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY,
|
||||
GameConstants.PULSE_DELAY, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a player. Returns immediately. The player is unregistered at the start of the next cycle.
|
||||
*
|
||||
@@ -166,15 +177,4 @@ public final class GameService extends Service {
|
||||
oldPlayers.add(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the unregistration of a player.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
public void finalizePlayerUnregistration(Player player) {
|
||||
synchronized (this) {
|
||||
World.getWorld().unregister(player);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,15 +28,6 @@ public final class Command {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the command.
|
||||
*
|
||||
* @return The name of the command.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command's arguments.
|
||||
*
|
||||
@@ -46,4 +37,13 @@ public final class Command {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the command.
|
||||
*
|
||||
* @return The name of the command.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,16 +25,6 @@ public final class CommandDispatcher {
|
||||
listeners.put("credits", new CreditsCommandListener());
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener with the
|
||||
*
|
||||
* @param command The command's name.
|
||||
* @param listener The listener.
|
||||
*/
|
||||
public void register(String command, CommandListener listener) {
|
||||
listeners.put(command.toLowerCase(), listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a command to the appropriate listener.
|
||||
*
|
||||
@@ -48,4 +38,14 @@ public final class CommandDispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener with the
|
||||
*
|
||||
* @param command The command's name.
|
||||
* @param listener The listener.
|
||||
*/
|
||||
public void register(String command, CommandListener listener) {
|
||||
listeners.put(command.toLowerCase(), listener);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ public abstract class PrivilegedCommandListener implements CommandListener {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void execute(Player player, Command command) {
|
||||
if (player.getPrivilegeLevel().toInteger() >= level.toInteger()) {
|
||||
executePrivileged(player, command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a privileged command.
|
||||
*
|
||||
@@ -32,11 +39,4 @@ public abstract class PrivilegedCommandListener implements CommandListener {
|
||||
*/
|
||||
public abstract void executePrivileged(Player player, Command command);
|
||||
|
||||
@Override
|
||||
public final void execute(Player player, Command command) {
|
||||
if (player.getPrivilegeLevel().toInteger() >= level.toInteger()) {
|
||||
executePrivileged(player, command);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,25 @@ public final class BankEventHandler extends EventHandler<ItemActionEvent> {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a deposit action.
|
||||
*
|
||||
* @param ctx The event handler context.
|
||||
* @param player The player.
|
||||
* @param event The event.
|
||||
*/
|
||||
private void deposit(EventHandlerContext ctx, Player player, ItemActionEvent event) {
|
||||
int amount = optionToAmount(event.getOption());
|
||||
if (amount == -1) {
|
||||
player.getInterfaceSet().openEnterAmountDialog(
|
||||
new BankDepositEnterAmountListener(player, event.getSlot(), event.getId()));
|
||||
} else {
|
||||
if (!BankUtils.deposit(player, event.getSlot(), event.getId(), amount)) {
|
||||
ctx.breakHandlerChain();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(EventHandlerContext ctx, Player player, ItemActionEvent event) {
|
||||
if (!player.getInterfaceSet().contains(BankConstants.BANK_WINDOW_ID)) {
|
||||
@@ -71,23 +90,4 @@ public final class BankEventHandler extends EventHandler<ItemActionEvent> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a deposit action.
|
||||
*
|
||||
* @param ctx The event handler context.
|
||||
* @param player The player.
|
||||
* @param event The event.
|
||||
*/
|
||||
private void deposit(EventHandlerContext ctx, Player player, ItemActionEvent event) {
|
||||
int amount = optionToAmount(event.getOption());
|
||||
if (amount == -1) {
|
||||
player.getInterfaceSet().openEnterAmountDialog(
|
||||
new BankDepositEnterAmountListener(player, event.getSlot(), event.getId()));
|
||||
} else {
|
||||
if (!BankUtils.deposit(player, event.getSlot(), event.getId(), amount)) {
|
||||
ctx.breakHandlerChain();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,24 +46,6 @@ public final class CharacterDesignVerificationHandler extends EventHandler<Chara
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a {@link Gender#MALE} style combination is valid.
|
||||
*
|
||||
* @param appearance The appearance combination.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
private boolean validMaleStyle(Appearance appearance) {
|
||||
int[] styles = appearance.getStyle();
|
||||
int[] minStyles = new int[] { 0, 10, 18, 26, 33, 36, 42 };
|
||||
int[] maxStyles = new int[] { 8, 17, 25, 31, 34, 40, 43 };
|
||||
for (int i = 0; i < styles.length; i++) {
|
||||
if (styles[i] < minStyles[i] || styles[i] > maxStyles[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a {@link Gender#FEMALE} style combination is valid.
|
||||
*
|
||||
@@ -82,4 +64,22 @@ public final class CharacterDesignVerificationHandler extends EventHandler<Chara
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a {@link Gender#MALE} style combination is valid.
|
||||
*
|
||||
* @param appearance The appearance combination.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
private boolean validMaleStyle(Appearance appearance) {
|
||||
int[] styles = appearance.getStyle();
|
||||
int[] minStyles = new int[] { 0, 10, 18, 26, 33, 36, 42 };
|
||||
int[] maxStyles = new int[] { 8, 17, 25, 31, 34, 40, 43 };
|
||||
for (int i = 0; i < styles.length; i++) {
|
||||
if (styles[i] < minStyles[i] || styles[i] > maxStyles[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public final class EquipEventHandler extends EventHandler<EquipEvent> {
|
||||
Item shield = equipment.get(EquipmentConstants.SHIELD);
|
||||
|
||||
if (equippingDef.isTwoHanded()) {
|
||||
int slotsRequired = weapon != null ? (shield != null ? 1 : 0) : 0;
|
||||
int slotsRequired = weapon != null ? shield != null ? 1 : 0 : 0;
|
||||
if (inventory.freeSlots() < slotsRequired) {
|
||||
ctx.breakHandlerChain();
|
||||
return;
|
||||
|
||||
@@ -5,9 +5,9 @@ import org.apollo.game.event.handler.EventHandlerContext;
|
||||
import org.apollo.game.event.impl.ItemActionEvent;
|
||||
import org.apollo.game.model.Inventory;
|
||||
import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.Player;
|
||||
import org.apollo.game.model.def.ItemDefinition;
|
||||
import org.apollo.game.model.inv.SynchronizationInventoryListener;
|
||||
import org.apollo.game.model.Player;
|
||||
|
||||
/**
|
||||
* An event handler which removes equipped items.
|
||||
|
||||
@@ -44,6 +44,15 @@ public final class ChatEvent extends Event {
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the compressed message.
|
||||
*
|
||||
* @return The compressed message.
|
||||
*/
|
||||
public byte[] getCompressedMessage() {
|
||||
return compressedMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message.
|
||||
*
|
||||
@@ -71,13 +80,4 @@ public final class ChatEvent extends Event {
|
||||
return effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the compressed message.
|
||||
*
|
||||
* @return The compressed message.
|
||||
*/
|
||||
public byte[] getCompressedMessage() {
|
||||
return compressedMessage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,15 +37,6 @@ public final class EquipEvent extends Event {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interface id.
|
||||
*
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item id.
|
||||
*
|
||||
@@ -55,6 +46,15 @@ public final class EquipEvent extends Event {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interface id.
|
||||
*
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slot.
|
||||
*
|
||||
|
||||
@@ -45,12 +45,12 @@ public abstract class ItemActionEvent extends Event {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the option number.
|
||||
* Gets the item id.
|
||||
*
|
||||
* @return The option number.
|
||||
* @return The item id.
|
||||
*/
|
||||
public int getOption() {
|
||||
return option;
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,12 +63,12 @@ public abstract class ItemActionEvent extends Event {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item id.
|
||||
* Gets the option number.
|
||||
*
|
||||
* @return The item id.
|
||||
* @return The option number.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
public int getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,15 +38,6 @@ public abstract class ObjectActionEvent extends Event {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the option number.
|
||||
*
|
||||
* @return The option number.
|
||||
*/
|
||||
public int getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the object.
|
||||
*
|
||||
@@ -56,6 +47,15 @@ public abstract class ObjectActionEvent extends Event {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the option number.
|
||||
*
|
||||
* @return The option number.
|
||||
*/
|
||||
public int getOption() {
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of the object.
|
||||
*
|
||||
|
||||
@@ -72,6 +72,15 @@ public final class PlayerSynchronizationEvent extends Event {
|
||||
return lastKnownRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of local players.
|
||||
*
|
||||
* @return The number of local players.
|
||||
*/
|
||||
public int getLocalPlayers() {
|
||||
return localPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's position.
|
||||
*
|
||||
@@ -81,15 +90,6 @@ public final class PlayerSynchronizationEvent extends Event {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the region has changed.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean hasRegionChanged() {
|
||||
return regionChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current player's segment.
|
||||
*
|
||||
@@ -99,15 +99,6 @@ public final class PlayerSynchronizationEvent extends Event {
|
||||
return segment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of local players.
|
||||
*
|
||||
* @return The number of local players.
|
||||
*/
|
||||
public int getLocalPlayers() {
|
||||
return localPlayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the synchronization segments.
|
||||
*
|
||||
@@ -117,4 +108,13 @@ public final class PlayerSynchronizationEvent extends Event {
|
||||
return segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the region has changed.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean hasRegionChanged() {
|
||||
return regionChanged;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,24 @@ public final class SwitchItemEvent extends Event {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new slot.
|
||||
*
|
||||
* @return The new slot.
|
||||
*/
|
||||
public int getNewSlot() {
|
||||
return newSlot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the old slot.
|
||||
*
|
||||
* @return The old slot.
|
||||
*/
|
||||
public int getOldSlot() {
|
||||
return oldSlot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this event is in insertion mode.
|
||||
*
|
||||
@@ -71,22 +89,4 @@ public final class SwitchItemEvent extends Event {
|
||||
return !inserting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the old slot.
|
||||
*
|
||||
* @return The old slot.
|
||||
*/
|
||||
public int getOldSlot() {
|
||||
return oldSlot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new slot.
|
||||
*
|
||||
* @return The new slot.
|
||||
*/
|
||||
public int getNewSlot() {
|
||||
return newSlot;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,15 +30,6 @@ public final class SwitchTabInterfaceEvent extends Event {
|
||||
this.interfaceId = interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tab id.
|
||||
*
|
||||
* @return The tab id.
|
||||
*/
|
||||
public int getTabId() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interface id.
|
||||
*
|
||||
@@ -48,4 +39,13 @@ public final class SwitchTabInterfaceEvent extends Event {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tab id.
|
||||
*
|
||||
* @return The tab id.
|
||||
*/
|
||||
public int getTabId() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -182,15 +182,6 @@ public final class Animation {
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation's id.
|
||||
*
|
||||
* @return The animation's id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation's delay.
|
||||
*
|
||||
@@ -200,4 +191,13 @@ public final class Animation {
|
||||
return delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the animation's id.
|
||||
*
|
||||
* @return The animation's id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,6 +50,15 @@ public final class Appearance {
|
||||
this.colors = colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's colors.
|
||||
*
|
||||
* @return The player's colors.
|
||||
*/
|
||||
public int[] getColors() {
|
||||
return colors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the gender of the player.
|
||||
*
|
||||
@@ -59,24 +68,6 @@ public final class Appearance {
|
||||
return gender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is male.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isMale() {
|
||||
return gender == Gender.MALE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is female.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isFemale() {
|
||||
return gender == Gender.FEMALE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's styles.
|
||||
*
|
||||
@@ -92,12 +83,21 @@ public final class Appearance {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's colors.
|
||||
* Checks if the player is female.
|
||||
*
|
||||
* @return The player's colors.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public int[] getColors() {
|
||||
return colors;
|
||||
public boolean isFemale() {
|
||||
return gender == Gender.FEMALE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the player is male.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isMale() {
|
||||
return gender == Gender.MALE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -318,8 +318,8 @@ public abstract class Character {
|
||||
* @param second The second direction.
|
||||
*/
|
||||
public void setDirections(Direction first, Direction second) {
|
||||
this.firstDirection = first;
|
||||
this.secondDirection = second;
|
||||
firstDirection = first;
|
||||
secondDirection = second;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,10 +399,10 @@ public abstract class Character {
|
||||
* @param position The position.
|
||||
*/
|
||||
public void teleport(Position position) {
|
||||
this.teleporting = true;
|
||||
teleporting = true;
|
||||
this.position = position;
|
||||
this.walkingQueue.clear();
|
||||
this.stopAction(); // TODO do it on any movement is a must.. walking queue perhaps?
|
||||
walkingQueue.clear();
|
||||
stopAction(); // TODO do it on any movement is a must.. walking queue perhaps?
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,18 +57,6 @@ public enum Direction {
|
||||
*/
|
||||
public static final Direction[] EMPTY_DIRECTION_ARRAY = new Direction[0];
|
||||
|
||||
/**
|
||||
* Checks if the direction represented by the two delta values can connect two points together in a single
|
||||
* direction.
|
||||
*
|
||||
* @param deltaX The difference in X coordinates.
|
||||
* @param deltaY The difference in X coordinates.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public static boolean isConnectable(int deltaX, int deltaY) {
|
||||
return Math.abs(deltaX) == Math.abs(deltaY) || deltaX == 0 || deltaY == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a direction from the differences between X and Y.
|
||||
*
|
||||
@@ -103,6 +91,18 @@ public enum Direction {
|
||||
return Direction.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the direction represented by the two delta values can connect two points together in a single
|
||||
* direction.
|
||||
*
|
||||
* @param deltaX The difference in X coordinates.
|
||||
* @param deltaY The difference in X coordinates.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public static boolean isConnectable(int deltaX, int deltaY) {
|
||||
return Math.abs(deltaX) == Math.abs(deltaY) || deltaX == 0 || deltaY == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The direction as an integer.
|
||||
*/
|
||||
|
||||
@@ -59,15 +59,6 @@ public final class Graphic {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the graphic's id.
|
||||
*
|
||||
* @return The graphic's id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the graphic's delay.
|
||||
*
|
||||
@@ -86,4 +77,13 @@ public final class Graphic {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the graphic's id.
|
||||
*
|
||||
* @return The graphic's id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,6 +70,41 @@ public final class InterfaceSet {
|
||||
player.send(new CloseInterfaceEvent());
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal method for closing the interface, notifying the listener if appropriate, but not sending any events.
|
||||
*/
|
||||
private void closeAndNotify() {
|
||||
amountListener = null; // TODO should we notify??
|
||||
|
||||
interfaces.clear();
|
||||
if (listener != null) {
|
||||
listener.interfaceClosed();
|
||||
listener = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this interface sets contains the specified interface.
|
||||
*
|
||||
* @param id The interface's id.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean contains(int id) {
|
||||
return interfaces.containsValue(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the client has entered the specified amount. Notifies the current listener.
|
||||
*
|
||||
* @param amount The amount.
|
||||
*/
|
||||
public void enteredAmount(int amount) {
|
||||
if (amountListener != null) {
|
||||
amountListener.amountEntered(amount);
|
||||
amountListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sent by the client when it has closed an interface.
|
||||
*/
|
||||
@@ -83,11 +118,35 @@ public final class InterfaceSet {
|
||||
* @param listener The enter amount listener.
|
||||
*/
|
||||
public void openEnterAmountDialog(EnterAmountListener listener) {
|
||||
this.amountListener = listener;
|
||||
amountListener = listener;
|
||||
|
||||
player.send(new EnterAmountEvent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a window.
|
||||
*
|
||||
* @param windowId The window's id.
|
||||
*/
|
||||
public void openWindow(int windowId) {
|
||||
openWindow(null, windowId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a window with the specified listener.
|
||||
*
|
||||
* @param listener The listener for this interface.
|
||||
* @param windowId The window's id.
|
||||
*/
|
||||
public void openWindow(InterfaceListener listener, int windowId) {
|
||||
closeAndNotify();
|
||||
this.listener = listener;
|
||||
|
||||
interfaces.put(InterfaceType.WINDOW, windowId);
|
||||
|
||||
player.send(new OpenInterfaceEvent(windowId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a window and inventory sidebar.
|
||||
*
|
||||
@@ -115,63 +174,4 @@ public final class InterfaceSet {
|
||||
player.send(new OpenInterfaceSidebarEvent(windowId, sidebarId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a window.
|
||||
*
|
||||
* @param windowId The window's id.
|
||||
*/
|
||||
public void openWindow(int windowId) {
|
||||
openWindow(null, windowId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a window with the specified listener.
|
||||
*
|
||||
* @param listener The listener for this interface.
|
||||
* @param windowId The window's id.
|
||||
*/
|
||||
public void openWindow(InterfaceListener listener, int windowId) {
|
||||
closeAndNotify();
|
||||
this.listener = listener;
|
||||
|
||||
interfaces.put(InterfaceType.WINDOW, windowId);
|
||||
|
||||
player.send(new OpenInterfaceEvent(windowId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this interface sets contains the specified interface.
|
||||
*
|
||||
* @param id The interface's id.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean contains(int id) {
|
||||
return interfaces.containsValue(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal method for closing the interface, notifying the listener if appropriate, but not sending any events.
|
||||
*/
|
||||
private void closeAndNotify() {
|
||||
amountListener = null; // TODO should we notify??
|
||||
|
||||
interfaces.clear();
|
||||
if (listener != null) {
|
||||
listener.interfaceClosed();
|
||||
listener = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the client has entered the specified amount. Notifies the current listener.
|
||||
*
|
||||
* @param amount The amount.
|
||||
*/
|
||||
public void enteredAmount(int amount) {
|
||||
if (amountListener != null) {
|
||||
amountListener.amountEntered(amount);
|
||||
amountListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -95,126 +95,8 @@ public final class Inventory implements Cloneable {
|
||||
throw new NullPointerException("mode");
|
||||
}
|
||||
this.capacity = capacity;
|
||||
this.items = new Item[capacity];
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this inventory. Listeners are not copied, they must be added again yourself! This is so cloned
|
||||
* copies don't send updates to their counterparts.
|
||||
*/
|
||||
@Override
|
||||
public Inventory clone() {
|
||||
Inventory copy = new Inventory(capacity, mode);
|
||||
System.arraycopy(items, 0, copy.items, 0, capacity);
|
||||
copy.size = size;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this inventory contains an item with the specified id.
|
||||
*
|
||||
* @param id The item's id.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean contains(int id) {
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Item item = items[i];
|
||||
if (item != null && item.getId() == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of free slots.
|
||||
*
|
||||
* @return The number of free slots.
|
||||
*/
|
||||
public int freeSlots() {
|
||||
return capacity - size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the inventory.
|
||||
*/
|
||||
public void clear() {
|
||||
items = new Item[capacity];
|
||||
size = 0;
|
||||
notifyItemsUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the capacity of this inventory.
|
||||
*
|
||||
* @return The capacity.
|
||||
*/
|
||||
public int capacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of this inventory - the number of used slots.
|
||||
*
|
||||
* @return The size.
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item in the specified slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
* @return The item, or {@code null} if the slot is empty.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
public Item get(int slot) {
|
||||
checkBounds(slot);
|
||||
return items[slot];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item that is in the specified slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
* @param item The item, or {@code null} to remove the item that is in the slot.
|
||||
* @return The item that was in the slot.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
public Item set(int slot, Item item) {
|
||||
if (item == null) {
|
||||
return reset(slot);
|
||||
}
|
||||
checkBounds(slot);
|
||||
|
||||
Item old = items[slot];
|
||||
if (old == null) {
|
||||
size++;
|
||||
}
|
||||
items[slot] = item;
|
||||
notifyItemUpdated(slot);
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the item (if any) that is in the specified slot.
|
||||
*
|
||||
* @param slot
|
||||
* @return The item that was in the slot.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
public Item reset(int slot) {
|
||||
checkBounds(slot);
|
||||
|
||||
Item old = items[slot];
|
||||
if (old != null) {
|
||||
size--;
|
||||
}
|
||||
items[slot] = null;
|
||||
notifyItemUpdated(slot);
|
||||
return old;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,6 +194,178 @@ public final class Inventory implements Cloneable {
|
||||
return new Item(item.getId(), remaining);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener.
|
||||
*
|
||||
* @param listener The listener to add.
|
||||
*/
|
||||
public void addListener(InventoryListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the capacity of this inventory.
|
||||
*
|
||||
* @return The capacity.
|
||||
*/
|
||||
public int capacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the bounds of the specified slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
private void checkBounds(int slot) {
|
||||
if (slot < 0 || slot >= capacity) {
|
||||
throw new IndexOutOfBoundsException("slot out of bounds");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the inventory.
|
||||
*/
|
||||
public void clear() {
|
||||
items = new Item[capacity];
|
||||
size = 0;
|
||||
notifyItemsUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this inventory. Listeners are not copied, they must be added again yourself! This is so cloned
|
||||
* copies don't send updates to their counterparts.
|
||||
*/
|
||||
@Override
|
||||
public Inventory clone() {
|
||||
Inventory copy = new Inventory(capacity, mode);
|
||||
System.arraycopy(items, 0, copy.items, 0, capacity);
|
||||
copy.size = size;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this inventory contains an item with the specified id.
|
||||
*
|
||||
* @param id The item's id.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean contains(int id) {
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Item item = items[i];
|
||||
if (item != null && item.getId() == id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the capacity to exceeded event to be fired.
|
||||
*/
|
||||
public void forceCapacityExceeded() {
|
||||
notifyCapacityExceeded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the refresh of this inventory.
|
||||
*/
|
||||
public void forceRefresh() {
|
||||
notifyItemsUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a refresh of a specific slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
*/
|
||||
public void forceRefresh(int slot) {
|
||||
notifyItemUpdated(slot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of free slots.
|
||||
*
|
||||
* @return The number of free slots.
|
||||
*/
|
||||
public int freeSlots() {
|
||||
return capacity - size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item in the specified slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
* @return The item, or {@code null} if the slot is empty.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
public Item get(int slot) {
|
||||
checkBounds(slot);
|
||||
return items[slot];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a clone of the items array.
|
||||
*
|
||||
* @return A clone of the items array.
|
||||
*/
|
||||
public Item[] getItems() {
|
||||
return items.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the item specified by the definition should be stacked.
|
||||
*
|
||||
* @param def The definition.
|
||||
* @return {@code true} if the item should be stacked, {@code false} otherwise.
|
||||
*/
|
||||
private boolean isStackable(ItemDefinition def) {
|
||||
if (mode == StackMode.STACK_ALWAYS) {
|
||||
return true;
|
||||
} else if (mode == StackMode.STACK_STACKABLE_ITEMS) {
|
||||
return def.isStackable();
|
||||
} else { // will be STACK_NEVER
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that the capacity of this inventory has been exceeded.
|
||||
*/
|
||||
private void notifyCapacityExceeded() {
|
||||
if (firingEvents) {
|
||||
for (InventoryListener listener : listeners) {
|
||||
listener.capacityExceeded(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that all the items have been updated.
|
||||
*/
|
||||
private void notifyItemsUpdated() {
|
||||
if (firingEvents) {
|
||||
for (InventoryListener listener : listeners) {
|
||||
listener.itemsUpdated(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that the specified slot has been updated.
|
||||
*
|
||||
* @param slot The slot.
|
||||
*/
|
||||
private void notifyItemUpdated(int slot) {
|
||||
if (firingEvents) {
|
||||
Item item = items[slot];
|
||||
for (InventoryListener listener : listeners) {
|
||||
listener.itemUpdated(this, slot, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes one item with the specified id.
|
||||
*
|
||||
@@ -322,16 +376,6 @@ public final class Inventory implements Cloneable {
|
||||
return remove(id, 1) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* An alias for {@code remove(item.getId(), item.getAmount())}.
|
||||
*
|
||||
* @param item The item to remove.
|
||||
* @return The amount that was removed.
|
||||
*/
|
||||
public int remove(Item item) {
|
||||
return remove(item.getId(), item.getAmount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes {@code amount} of the item with the specified {@code id}. If the item is stackable, it will remove it
|
||||
* from the stack. If not, it'll remove {@code amount} items.
|
||||
@@ -373,6 +417,74 @@ public final class Inventory implements Cloneable {
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* An alias for {@code remove(item.getId(), item.getAmount())}.
|
||||
*
|
||||
* @param item The item to remove.
|
||||
* @return The amount that was removed.
|
||||
*/
|
||||
public int remove(Item item) {
|
||||
return remove(item.getId(), item.getAmount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the listeners.
|
||||
*/
|
||||
public void removeAllListeners() {
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener.
|
||||
*
|
||||
* @param listener The listener to remove.
|
||||
*/
|
||||
public void removeListener(InventoryListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the item (if any) that is in the specified slot.
|
||||
*
|
||||
* @param slot
|
||||
* @return The item that was in the slot.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
public Item reset(int slot) {
|
||||
checkBounds(slot);
|
||||
|
||||
Item old = items[slot];
|
||||
if (old != null) {
|
||||
size--;
|
||||
}
|
||||
items[slot] = null;
|
||||
notifyItemUpdated(slot);
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item that is in the specified slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
* @param item The item, or {@code null} to remove the item that is in the slot.
|
||||
* @return The item that was in the slot.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
public Item set(int slot, Item item) {
|
||||
if (item == null) {
|
||||
return reset(slot);
|
||||
}
|
||||
checkBounds(slot);
|
||||
|
||||
Item old = items[slot];
|
||||
if (old == null) {
|
||||
size++;
|
||||
}
|
||||
items[slot] = item;
|
||||
notifyItemUpdated(slot);
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts all items to the top left of the container, leaving no gaps.
|
||||
*/
|
||||
@@ -390,14 +502,26 @@ public final class Inventory implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the two items at the specified slots.
|
||||
* Gets the size of this inventory - the number of used slots.
|
||||
*
|
||||
* @param oldSlot The old slot.
|
||||
* @param newSlot The new slot.
|
||||
* @throws IndexOutOufBoundsException If the slot is out of bounds.
|
||||
* @return The size.
|
||||
*/
|
||||
public void swap(int oldSlot, int newSlot) {
|
||||
swap(false, oldSlot, newSlot);
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the firing of events.
|
||||
*/
|
||||
public void startFiringEvents() {
|
||||
firingEvents = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the firing of events.
|
||||
*/
|
||||
public void stopFiringEvents() {
|
||||
firingEvents = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,138 +555,14 @@ public final class Inventory implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener.
|
||||
* Swaps the two items at the specified slots.
|
||||
*
|
||||
* @param listener The listener to add.
|
||||
* @param oldSlot The old slot.
|
||||
* @param newSlot The new slot.
|
||||
* @throws IndexOutOufBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
public void addListener(InventoryListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener.
|
||||
*
|
||||
* @param listener The listener to remove.
|
||||
*/
|
||||
public void removeListener(InventoryListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the listeners.
|
||||
*/
|
||||
public void removeAllListeners() {
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that the capacity of this inventory has been exceeded.
|
||||
*/
|
||||
private void notifyCapacityExceeded() {
|
||||
if (firingEvents) {
|
||||
for (InventoryListener listener : listeners) {
|
||||
listener.capacityExceeded(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that all the items have been updated.
|
||||
*/
|
||||
private void notifyItemsUpdated() {
|
||||
if (firingEvents) {
|
||||
for (InventoryListener listener : listeners) {
|
||||
listener.itemsUpdated(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that the specified slot has been updated.
|
||||
*
|
||||
* @param slot The slot.
|
||||
*/
|
||||
private void notifyItemUpdated(int slot) {
|
||||
if (firingEvents) {
|
||||
Item item = items[slot];
|
||||
for (InventoryListener listener : listeners) {
|
||||
listener.itemUpdated(this, slot, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the bounds of the specified slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||
*/
|
||||
private void checkBounds(int slot) {
|
||||
if (slot < 0 || slot >= capacity) {
|
||||
throw new IndexOutOfBoundsException("slot out of bounds");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the item specified by the definition should be stacked.
|
||||
*
|
||||
* @param def The definition.
|
||||
* @return {@code true} if the item should be stacked, {@code false} otherwise.
|
||||
*/
|
||||
private boolean isStackable(ItemDefinition def) {
|
||||
if (mode == StackMode.STACK_ALWAYS) {
|
||||
return true;
|
||||
} else if (mode == StackMode.STACK_STACKABLE_ITEMS) {
|
||||
return def.isStackable();
|
||||
} else { // will be STACK_NEVER
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a clone of the items array.
|
||||
*
|
||||
* @return A clone of the items array.
|
||||
*/
|
||||
public Item[] getItems() {
|
||||
return items.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the firing of events.
|
||||
*/
|
||||
public void stopFiringEvents() {
|
||||
firingEvents = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the firing of events.
|
||||
*/
|
||||
public void startFiringEvents() {
|
||||
firingEvents = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the refresh of this inventory.
|
||||
*/
|
||||
public void forceRefresh() {
|
||||
notifyItemsUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a refresh of a specific slot.
|
||||
*
|
||||
* @param slot The slot.
|
||||
*/
|
||||
public void forceRefresh(int slot) {
|
||||
notifyItemUpdated(slot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the capacity to exceeded event to be fired.
|
||||
*/
|
||||
public void forceCapacityExceeded() {
|
||||
notifyCapacityExceeded();
|
||||
public void swap(int oldSlot, int newSlot) {
|
||||
swap(false, oldSlot, newSlot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,15 +43,6 @@ public final class Item {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
*
|
||||
* @return The id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount.
|
||||
*
|
||||
@@ -70,6 +61,15 @@ public final class Item {
|
||||
return ItemDefinition.lookup(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
*
|
||||
* @return The id.
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Item.class.getName() + " [id=" + id + ", amount=" + amount + "]";
|
||||
|
||||
@@ -41,6 +41,7 @@ public class Npc extends Character {
|
||||
*
|
||||
* @return The definition.
|
||||
*/
|
||||
@Override
|
||||
public NpcDefinition getNpcDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public final class Player extends Character {
|
||||
* Sets the excessive npcs flag.
|
||||
*/
|
||||
public void flagExcessiveNpcs() {
|
||||
this.excessiveNpcs = true;
|
||||
excessiveNpcs = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,6 +434,15 @@ public final class Player extends Character {
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the player is running or not.
|
||||
*
|
||||
* @return {@code true} if the player is running, otherwise {@code false}.
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the withdrawing notes flag.
|
||||
*
|
||||
@@ -527,7 +536,7 @@ public final class Player extends Character {
|
||||
*/
|
||||
public void setAppearance(Appearance appearance) {
|
||||
this.appearance = appearance;
|
||||
this.getBlockSet().add(SynchronizationBlock.createAppearanceBlock(this));
|
||||
getBlockSet().add(SynchronizationBlock.createAppearanceBlock(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -593,6 +602,16 @@ public final class Player extends Character {
|
||||
this.regionChanged = regionChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the running toggle is enabled.
|
||||
*
|
||||
* @param running The toggle.
|
||||
*/
|
||||
public void setRunning(boolean running) {
|
||||
this.running = running;
|
||||
getWalkingQueue().setRunningQueue(running);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's {@link GameSession}.
|
||||
*
|
||||
@@ -628,23 +647,4 @@ public final class Player extends Character {
|
||||
+ privilegeLevel + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the player is running or not.
|
||||
*
|
||||
* @return {@code true} if the player is running, otherwise {@code false}.
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the running toggle is enabled.
|
||||
*
|
||||
* @param running The toggle.
|
||||
*/
|
||||
public void setRunning(boolean running) {
|
||||
this.running = running;
|
||||
getWalkingQueue().setRunningQueue(running);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -58,150 +58,6 @@ public final class Position {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate.
|
||||
*
|
||||
* @return The x coordinate.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate.
|
||||
*
|
||||
* @return The y coordinate.
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height level.
|
||||
*
|
||||
* @return The height level.
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate of the region.
|
||||
*
|
||||
* @return The region x coordinate.
|
||||
*/
|
||||
public int getTopLeftRegionX() {
|
||||
return (x / 8) - 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate of the region.
|
||||
*
|
||||
* @return The region y coordinate.
|
||||
*/
|
||||
public int getTopLeftRegionY() {
|
||||
return (y / 8) - 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate of the central region.
|
||||
*
|
||||
* @return The x coordinate of the central region.
|
||||
*/
|
||||
public int getCentralRegionX() {
|
||||
return x / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate of the central region.
|
||||
*
|
||||
* @return The y coordinate of the central region.
|
||||
*/
|
||||
public int getCentralRegionY() {
|
||||
return y / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate inside the region of this position.
|
||||
*
|
||||
* @return The local x coordinate.
|
||||
*/
|
||||
public int getLocalX() {
|
||||
return getLocalX(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate inside the region of this position.
|
||||
*
|
||||
* @return The local y coordinate.
|
||||
*/
|
||||
public int getLocalY() {
|
||||
return getLocalY(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local x coordinate inside the region of the {@code base} position.
|
||||
*
|
||||
* @param base The base position.
|
||||
* @return The local x coordinate.
|
||||
*/
|
||||
public int getLocalX(Position base) {
|
||||
return x - (base.getTopLeftRegionX() * 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local y coordinate inside the region of the {@code base} position.
|
||||
*
|
||||
* @param base The base position.
|
||||
* @return The local y coordinate.
|
||||
*/
|
||||
public int getLocalY(Position base) {
|
||||
return y - (base.getTopLeftRegionY() * 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ((height << 30) & 0xC0000000) | ((y << 15) & 0x3FFF8000) | (x & 0x7FFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the distance between this position and another position. Only X and Y are considered (i.e. 2 dimensions).
|
||||
*
|
||||
* @param other The other position.
|
||||
* @return The distance.
|
||||
*/
|
||||
public int getDistance(Position other) {
|
||||
int deltaX = x - other.x;
|
||||
int deltaY = y - other.y;
|
||||
// TODO will rounding up interfere with other stuff?
|
||||
return (int) Math.ceil(Math.sqrt(deltaX * deltaX + deltaY * deltaY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the longest horizontal or vertical delta between the two positions.
|
||||
*
|
||||
* @param other The other position.
|
||||
* @return The longest horizontal or vertical delta.
|
||||
*/
|
||||
public int getLongestDelta(Position other) {
|
||||
int deltaX = x - other.x;
|
||||
int deltaY = y - other.y;
|
||||
return Math.max(deltaX, deltaY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the position is within distance of another.
|
||||
*
|
||||
* @param other The other position.
|
||||
* @param distance The distance.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isWithinDistance(Position other, int distance) {
|
||||
int deltaX = Math.abs(x - other.x);
|
||||
int deltaY = Math.abs(y - other.y);
|
||||
return deltaX <= distance && deltaY <= distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
@@ -226,6 +82,150 @@ public final class Position {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate of the central region.
|
||||
*
|
||||
* @return The x coordinate of the central region.
|
||||
*/
|
||||
public int getCentralRegionX() {
|
||||
return x / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate of the central region.
|
||||
*
|
||||
* @return The y coordinate of the central region.
|
||||
*/
|
||||
public int getCentralRegionY() {
|
||||
return y / 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the distance between this position and another position. Only X and Y are considered (i.e. 2 dimensions).
|
||||
*
|
||||
* @param other The other position.
|
||||
* @return The distance.
|
||||
*/
|
||||
public int getDistance(Position other) {
|
||||
int deltaX = x - other.x;
|
||||
int deltaY = y - other.y;
|
||||
// TODO will rounding up interfere with other stuff?
|
||||
return (int) Math.ceil(Math.sqrt(deltaX * deltaX + deltaY * deltaY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height level.
|
||||
*
|
||||
* @return The height level.
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate inside the region of this position.
|
||||
*
|
||||
* @return The local x coordinate.
|
||||
*/
|
||||
public int getLocalX() {
|
||||
return getLocalX(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local x coordinate inside the region of the {@code base} position.
|
||||
*
|
||||
* @param base The base position.
|
||||
* @return The local x coordinate.
|
||||
*/
|
||||
public int getLocalX(Position base) {
|
||||
return x - base.getTopLeftRegionX() * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate inside the region of this position.
|
||||
*
|
||||
* @return The local y coordinate.
|
||||
*/
|
||||
public int getLocalY() {
|
||||
return getLocalY(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local y coordinate inside the region of the {@code base} position.
|
||||
*
|
||||
* @param base The base position.
|
||||
* @return The local y coordinate.
|
||||
*/
|
||||
public int getLocalY(Position base) {
|
||||
return y - base.getTopLeftRegionY() * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the longest horizontal or vertical delta between the two positions.
|
||||
*
|
||||
* @param other The other position.
|
||||
* @return The longest horizontal or vertical delta.
|
||||
*/
|
||||
public int getLongestDelta(Position other) {
|
||||
int deltaX = x - other.x;
|
||||
int deltaY = y - other.y;
|
||||
return Math.max(deltaX, deltaY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate of the region.
|
||||
*
|
||||
* @return The region x coordinate.
|
||||
*/
|
||||
public int getTopLeftRegionX() {
|
||||
return x / 8 - 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate of the region.
|
||||
*
|
||||
* @return The region y coordinate.
|
||||
*/
|
||||
public int getTopLeftRegionY() {
|
||||
return y / 8 - 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate.
|
||||
*
|
||||
* @return The x coordinate.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate.
|
||||
*
|
||||
* @return The y coordinate.
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return height << 30 & 0xC0000000 | y << 15 & 0x3FFF8000 | x & 0x7FFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the position is within distance of another.
|
||||
*
|
||||
* @param other The other position.
|
||||
* @param distance The distance.
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isWithinDistance(Position other, int distance) {
|
||||
int deltaX = Math.abs(x - other.x);
|
||||
int deltaY = Math.abs(y - other.y);
|
||||
return deltaX <= distance && deltaY <= distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Position.class.getName() + " [x=" + x + ", y=" + y + ", height=" + height + "]";
|
||||
|
||||
@@ -157,15 +157,6 @@ public final class Skill {
|
||||
this.maximumLevel = maximumLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the experience.
|
||||
*
|
||||
* @return The experience.
|
||||
*/
|
||||
public double getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current level.
|
||||
*
|
||||
@@ -175,6 +166,15 @@ public final class Skill {
|
||||
return currentLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the experience.
|
||||
*
|
||||
* @return The experience.
|
||||
*/
|
||||
public double getExperience() {
|
||||
return experience;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum level.
|
||||
*
|
||||
|
||||
@@ -22,6 +22,44 @@ public final class SkillSet {
|
||||
*/
|
||||
public static final double MAXIMUM_EXP = 200000000;
|
||||
|
||||
/**
|
||||
* Gets the minimum experience required for the specified level.
|
||||
*
|
||||
* @param level The level.
|
||||
* @return The minimum experience.
|
||||
*/
|
||||
public static double getExperienceForLevel(int level) {
|
||||
int points = 0;
|
||||
int output = 0;
|
||||
for (int lvl = 1; lvl <= level; lvl++) {
|
||||
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
if (lvl >= level) {
|
||||
return output;
|
||||
}
|
||||
output = (int) Math.floor(points / 4);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum level to get the specified experience.
|
||||
*
|
||||
* @param experience The experience.
|
||||
* @return The minimum level.
|
||||
*/
|
||||
public static int getLevelForExperience(double experience) {
|
||||
int points = 0;
|
||||
int output = 0;
|
||||
for (int lvl = 1; lvl <= 99; lvl++) {
|
||||
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
output = (int) Math.floor(points / 4);
|
||||
if (output >= experience + 1) {
|
||||
return lvl;
|
||||
}
|
||||
}
|
||||
return 99;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of skill listeners.
|
||||
*/
|
||||
@@ -44,41 +82,6 @@ public final class SkillSet {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of skills.
|
||||
*
|
||||
* @return The number of skills.
|
||||
*/
|
||||
public int size() {
|
||||
return skills.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the skill set.
|
||||
*/
|
||||
private void init() {
|
||||
for (int i = 0; i < skills.length; i++) {
|
||||
if (i == Skill.HITPOINTS) {
|
||||
skills[i] = new Skill(1154, 10, 10);
|
||||
} else {
|
||||
skills[i] = new Skill(0, 1, 1);
|
||||
}
|
||||
// DO NOT CALL notifyXXX here!!
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a skill by its id.
|
||||
*
|
||||
* @param id The id.
|
||||
* @return The skill.
|
||||
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||
*/
|
||||
public Skill getSkill(int id) {
|
||||
checkBounds(id);
|
||||
return skills[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds experience to the specified skill.
|
||||
*
|
||||
@@ -113,16 +116,31 @@ public final class SkillSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total level for this skill set.
|
||||
* Adds a listener.
|
||||
*
|
||||
* @return The total level.
|
||||
* @param listener The listener to add.
|
||||
*/
|
||||
public int getTotalLevel() {
|
||||
int total = 0;
|
||||
for (int i = 0; i < skills.length; i++) {
|
||||
total += skills[i].getMaximumLevel();
|
||||
public void addListener(SkillListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the bounds of the id.
|
||||
*
|
||||
* @param id The id.
|
||||
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||
*/
|
||||
private void checkBounds(int id) {
|
||||
if (id < 0 || id >= skills.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces this skill set to refresh.
|
||||
*/
|
||||
public void forceRefresh() {
|
||||
notifySkillsUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,41 +174,42 @@ public final class SkillSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum experience required for the specified level.
|
||||
* Gets a skill by its id.
|
||||
*
|
||||
* @param level The level.
|
||||
* @return The minimum experience.
|
||||
* @param id The id.
|
||||
* @return The skill.
|
||||
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||
*/
|
||||
public static double getExperienceForLevel(int level) {
|
||||
int points = 0;
|
||||
int output = 0;
|
||||
for (int lvl = 1; lvl <= level; lvl++) {
|
||||
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
if (lvl >= level) {
|
||||
return output;
|
||||
}
|
||||
output = (int) Math.floor(points / 4);
|
||||
}
|
||||
return 0;
|
||||
public Skill getSkill(int id) {
|
||||
checkBounds(id);
|
||||
return skills[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum level to get the specified experience.
|
||||
* Gets the total level for this skill set.
|
||||
*
|
||||
* @param experience The experience.
|
||||
* @return The minimum level.
|
||||
* @return The total level.
|
||||
*/
|
||||
public static int getLevelForExperience(double experience) {
|
||||
int points = 0;
|
||||
int output = 0;
|
||||
for (int lvl = 1; lvl <= 99; lvl++) {
|
||||
points += Math.floor(lvl + 300.0 * Math.pow(2.0, lvl / 7.0));
|
||||
output = (int) Math.floor(points / 4);
|
||||
if (output >= (experience + 1)) {
|
||||
return lvl;
|
||||
}
|
||||
public int getTotalLevel() {
|
||||
int total = 0;
|
||||
for (Skill skill : skills) {
|
||||
total += skill.getMaximumLevel();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the skill set.
|
||||
*/
|
||||
private void init() {
|
||||
for (int i = 0; i < skills.length; i++) {
|
||||
if (i == Skill.HITPOINTS) {
|
||||
skills[i] = new Skill(1154, 10, 10);
|
||||
} else {
|
||||
skills[i] = new Skill(0, 1, 1);
|
||||
}
|
||||
// DO NOT CALL notifyXXX here!!
|
||||
}
|
||||
return 99;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,31 +233,6 @@ public final class SkillSet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a skill.
|
||||
*
|
||||
* @param id The id.
|
||||
* @param skill The skill.
|
||||
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||
*/
|
||||
public void setSkill(int id, Skill skill) {
|
||||
checkBounds(id);
|
||||
skills[id] = skill;
|
||||
notifySkillUpdated(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the bounds of the id.
|
||||
*
|
||||
* @param id The id.
|
||||
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||
*/
|
||||
private void checkBounds(int id) {
|
||||
if (id < 0 || id >= skills.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that a skill has been levelled up.
|
||||
*
|
||||
@@ -254,6 +248,17 @@ public final class SkillSet {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that the skills in this listener have been updated.
|
||||
*/
|
||||
private void notifySkillsUpdated() {
|
||||
if (firingEvents) {
|
||||
for (SkillListener listener : listeners) {
|
||||
listener.skillsUpdated(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that a skill has been updated.
|
||||
*
|
||||
@@ -270,44 +275,10 @@ public final class SkillSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies listeners that the skills in this listener have been updated.
|
||||
* Removes all the listeners.
|
||||
*/
|
||||
private void notifySkillsUpdated() {
|
||||
if (firingEvents) {
|
||||
for (SkillListener listener : listeners) {
|
||||
listener.skillsUpdated(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops events from being fired.
|
||||
*/
|
||||
public void stopFiringEvents() {
|
||||
firingEvents = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enables the firing of events.
|
||||
*/
|
||||
public void startFiringEvents() {
|
||||
firingEvents = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces this skill set to refresh.
|
||||
*/
|
||||
public void forceRefresh() {
|
||||
notifySkillsUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener.
|
||||
*
|
||||
* @param listener The listener to add.
|
||||
*/
|
||||
public void addListener(SkillListener listener) {
|
||||
listeners.add(listener);
|
||||
public void removeAllListeners() {
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,10 +291,39 @@ public final class SkillSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the listeners.
|
||||
* Sets a skill.
|
||||
*
|
||||
* @param id The id.
|
||||
* @param skill The skill.
|
||||
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||
*/
|
||||
public void removeAllListeners() {
|
||||
listeners.clear();
|
||||
public void setSkill(int id, Skill skill) {
|
||||
checkBounds(id);
|
||||
skills[id] = skill;
|
||||
notifySkillUpdated(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of skills.
|
||||
*
|
||||
* @return The number of skills.
|
||||
*/
|
||||
public int size() {
|
||||
return skills.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enables the firing of events.
|
||||
*/
|
||||
public void startFiringEvents() {
|
||||
firingEvents = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops events from being fired.
|
||||
*/
|
||||
public void stopFiringEvents() {
|
||||
firingEvents = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,15 +28,6 @@ public final class SlottedItem {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slot.
|
||||
*
|
||||
* @return The slot.
|
||||
*/
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item.
|
||||
*
|
||||
@@ -46,4 +37,13 @@ public final class SlottedItem {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the slot.
|
||||
*
|
||||
* @return The slot.
|
||||
*/
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,11 +11,6 @@ import java.util.Queue;
|
||||
*/
|
||||
public final class WalkingQueue {
|
||||
|
||||
/**
|
||||
* The maximum size of the queue. If any additional steps are added, they are discarded.
|
||||
*/
|
||||
private static final int MAXIMUM_SIZE = 128;
|
||||
|
||||
/**
|
||||
* Represents a single point in the queue.
|
||||
*
|
||||
@@ -51,6 +46,11 @@ public final class WalkingQueue {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum size of the queue. If any additional steps are added, they are discarded.
|
||||
*/
|
||||
private static final int MAXIMUM_SIZE = 128;
|
||||
|
||||
/**
|
||||
* The character whose walking queue this is.
|
||||
*/
|
||||
@@ -80,42 +80,6 @@ public final class WalkingQueue {
|
||||
this.character = character;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every pulse, updates the queue.
|
||||
*/
|
||||
public void pulse() {
|
||||
Position position = character.getPosition();
|
||||
|
||||
Direction first = Direction.NONE;
|
||||
Direction second = Direction.NONE;
|
||||
|
||||
Point next = points.poll();
|
||||
if (next != null) {
|
||||
first = next.direction;
|
||||
position = next.position;
|
||||
|
||||
if (runningQueue /* or run toggled AND enough energy */) {
|
||||
next = points.poll();
|
||||
if (next != null) {
|
||||
second = next.direction;
|
||||
position = next.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
character.setDirections(first, second);
|
||||
character.setPosition(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the running queue flag.
|
||||
*
|
||||
* @param running The running queue flag.
|
||||
*/
|
||||
public void setRunningQueue(boolean running) {
|
||||
this.runningQueue = running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the first step to the queue, attempting to connect the server and client position by looking at the previous
|
||||
* queue.
|
||||
@@ -165,6 +129,31 @@ public final class WalkingQueue {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a step.
|
||||
*
|
||||
* @param x The x coordinate of this step.
|
||||
* @param y The y coordinate of this step.
|
||||
*/
|
||||
private void addStep(int x, int y) {
|
||||
if (points.size() >= MAXIMUM_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point last = getLast();
|
||||
|
||||
int deltaX = x - last.position.getX();
|
||||
int deltaY = y - last.position.getY();
|
||||
|
||||
Direction direction = Direction.fromDeltas(deltaX, deltaY);
|
||||
|
||||
if (direction != Direction.NONE) {
|
||||
Point p = new Point(new Position(x, y, character.getPosition().getHeight()), direction);
|
||||
points.add(p);
|
||||
oldPoints.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a step to the queue.
|
||||
*
|
||||
@@ -199,28 +188,11 @@ public final class WalkingQueue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a step.
|
||||
*
|
||||
* @param x The x coordinate of this step.
|
||||
* @param y The y coordinate of this step.
|
||||
* Clears the walking queue.
|
||||
*/
|
||||
private void addStep(int x, int y) {
|
||||
if (points.size() >= MAXIMUM_SIZE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point last = getLast();
|
||||
|
||||
int deltaX = x - last.position.getX();
|
||||
int deltaY = y - last.position.getY();
|
||||
|
||||
Direction direction = Direction.fromDeltas(deltaX, deltaY);
|
||||
|
||||
if (direction != Direction.NONE) {
|
||||
Point p = new Point(new Position(x, y, character.getPosition().getHeight()), direction);
|
||||
points.add(p);
|
||||
oldPoints.add(p);
|
||||
}
|
||||
public void clear() {
|
||||
points.clear();
|
||||
oldPoints.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,11 +209,39 @@ public final class WalkingQueue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the walking queue.
|
||||
* Called every pulse, updates the queue.
|
||||
*/
|
||||
public void clear() {
|
||||
points.clear();
|
||||
oldPoints.clear();
|
||||
public void pulse() {
|
||||
Position position = character.getPosition();
|
||||
|
||||
Direction first = Direction.NONE;
|
||||
Direction second = Direction.NONE;
|
||||
|
||||
Point next = points.poll();
|
||||
if (next != null) {
|
||||
first = next.direction;
|
||||
position = next.position;
|
||||
|
||||
if (runningQueue /* or run toggled AND enough energy */) {
|
||||
next = points.poll();
|
||||
if (next != null) {
|
||||
second = next.direction;
|
||||
position = next.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
character.setDirections(first, second);
|
||||
character.setPosition(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the running queue flag.
|
||||
*
|
||||
* @param running The running queue flag.
|
||||
*/
|
||||
public void setRunningQueue(boolean running) {
|
||||
runningQueue = running;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.apollo.game.model.def;
|
||||
|
||||
import org.apollo.game.model.Npc;
|
||||
|
||||
/**
|
||||
* Represents a type of {@link Npc}.
|
||||
*
|
||||
|
||||
@@ -15,27 +15,6 @@ import org.apollo.game.model.inv.SynchronizationInventoryListener;
|
||||
*/
|
||||
public final class BankUtils {
|
||||
|
||||
/**
|
||||
* Opens a player's bank.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
public static void openBank(Player player) {
|
||||
InventoryListener invListener = new SynchronizationInventoryListener(player, BankConstants.SIDEBAR_INVENTORY_ID);
|
||||
InventoryListener bankListener = new SynchronizationInventoryListener(player, BankConstants.BANK_INVENTORY_ID);
|
||||
|
||||
player.getInventory().addListener(invListener);
|
||||
player.getBank().addListener(bankListener);
|
||||
|
||||
player.getInventory().forceRefresh();
|
||||
player.getBank().forceRefresh();
|
||||
|
||||
InterfaceListener interListener = new BankInterfaceListener(player, invListener, bankListener);
|
||||
|
||||
player.getInterfaceSet().openWindowWithSidebar(interListener, BankConstants.BANK_WINDOW_ID,
|
||||
BankConstants.SIDEBAR_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deposits an item into the player's bank.
|
||||
*
|
||||
@@ -88,6 +67,27 @@ public final class BankUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a player's bank.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
public static void openBank(Player player) {
|
||||
InventoryListener invListener = new SynchronizationInventoryListener(player, BankConstants.SIDEBAR_INVENTORY_ID);
|
||||
InventoryListener bankListener = new SynchronizationInventoryListener(player, BankConstants.BANK_INVENTORY_ID);
|
||||
|
||||
player.getInventory().addListener(invListener);
|
||||
player.getBank().addListener(bankListener);
|
||||
|
||||
player.getInventory().forceRefresh();
|
||||
player.getBank().forceRefresh();
|
||||
|
||||
InterfaceListener interListener = new BankInterfaceListener(player, invListener, bankListener);
|
||||
|
||||
player.getInterfaceSet().openWindowWithSidebar(interListener, BankConstants.BANK_WINDOW_ID,
|
||||
BankConstants.SIDEBAR_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Withdraws an item from a player's bank.
|
||||
*
|
||||
|
||||
@@ -26,11 +26,9 @@ public final class AppearanceInventoryListener extends InventoryAdapter {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the player's appearance.
|
||||
*/
|
||||
private void update() {
|
||||
player.getBlockSet().add(SynchronizationBlock.createAppearanceBlock(player));
|
||||
@Override
|
||||
public void itemsUpdated(Inventory inventory) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,9 +36,11 @@ public final class AppearanceInventoryListener extends InventoryAdapter {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemsUpdated(Inventory inventory) {
|
||||
update();
|
||||
/**
|
||||
* Updates the player's appearance.
|
||||
*/
|
||||
private void update() {
|
||||
player.getBlockSet().add(SynchronizationBlock.createAppearanceBlock(player));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public final class FullInventoryListener extends InventoryAdapter {
|
||||
*/
|
||||
public FullInventoryListener(Player player, String message) {
|
||||
this.player = player;
|
||||
this.event = new ServerMessageEvent(message);
|
||||
event = new ServerMessageEvent(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,14 +15,14 @@ public abstract class InventoryAdapter implements InventoryListener {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemUpdated(Inventory inventory, int slot, Item item) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemsUpdated(Inventory inventory) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemUpdated(Inventory inventory, int slot, Item item) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,13 @@ public interface InventoryListener {
|
||||
*/
|
||||
public void capacityExceeded(Inventory inventory);
|
||||
|
||||
/**
|
||||
* Called when items have been updated in bulk.
|
||||
*
|
||||
* @param inventory The inventory.
|
||||
*/
|
||||
public void itemsUpdated(Inventory inventory);
|
||||
|
||||
/**
|
||||
* Called when an item has been updated.
|
||||
*
|
||||
@@ -26,11 +33,4 @@ public interface InventoryListener {
|
||||
*/
|
||||
public void itemUpdated(Inventory inventory, int slot, Item item);
|
||||
|
||||
/**
|
||||
* Called when items have been updated in bulk.
|
||||
*
|
||||
* @param inventory The inventory.
|
||||
*/
|
||||
public void itemsUpdated(Inventory inventory);
|
||||
|
||||
}
|
||||
|
||||
@@ -45,14 +45,14 @@ public final class SynchronizationInventoryListener extends InventoryAdapter {
|
||||
this.interfaceId = interfaceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemUpdated(Inventory inventory, int slot, Item item) {
|
||||
player.send(new UpdateSlottedItemsEvent(interfaceId, new SlottedItem(slot, item)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemsUpdated(Inventory inventory) {
|
||||
player.send(new UpdateItemsEvent(interfaceId, inventory.getItems()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void itemUpdated(Inventory inventory, int slot, Item item) {
|
||||
player.send(new UpdateSlottedItemsEvent(interfaceId, new SlottedItem(slot, item)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public final class StaticObject {
|
||||
this.position = position;
|
||||
this.type = (byte) type;
|
||||
this.rotation = (byte) rotation;
|
||||
this.definition = ObjectDefinition.lookup(id);
|
||||
definition = ObjectDefinition.lookup(id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,24 @@ public final class RegionCoordinates {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final RegionCoordinates other = (RegionCoordinates) obj;
|
||||
if (x != other.x) {
|
||||
return false;
|
||||
}
|
||||
if (y != other.y) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the X coordinate.
|
||||
*
|
||||
@@ -46,29 +64,11 @@ public final class RegionCoordinates {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final RegionCoordinates other = (RegionCoordinates) obj;
|
||||
if (this.x != other.x) {
|
||||
return false;
|
||||
}
|
||||
if (this.y != other.y) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
hash = 61 * hash + this.x;
|
||||
hash = 61 * hash + this.y;
|
||||
hash = 61 * hash + x;
|
||||
hash = 61 * hash + y;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@ public abstract class SkillAdapter implements SkillListener {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skillUpdated(SkillSet set, int id, Skill skill) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skillsUpdated(SkillSet set) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skillUpdated(SkillSet set, int id, Skill skill) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ import org.apollo.game.model.SkillSet;
|
||||
public interface SkillListener {
|
||||
|
||||
/**
|
||||
* Called when a single skill is updated.
|
||||
* Called when a skill is levelled up.
|
||||
*
|
||||
* @param set The skill set.
|
||||
* @param id The skill's id.
|
||||
* @param skill The skill.
|
||||
*/
|
||||
public void skillUpdated(SkillSet set, int id, Skill skill);
|
||||
public void levelledUp(SkillSet set, int id, Skill skill);
|
||||
|
||||
/**
|
||||
* Called when all the skills are updated.
|
||||
@@ -27,12 +27,12 @@ public interface SkillListener {
|
||||
public void skillsUpdated(SkillSet set);
|
||||
|
||||
/**
|
||||
* Called when a skill is levelled up.
|
||||
* Called when a single skill is updated.
|
||||
*
|
||||
* @param set The skill set.
|
||||
* @param id The skill's id.
|
||||
* @param skill The skill.
|
||||
*/
|
||||
public void levelledUp(SkillSet set, int id, Skill skill);
|
||||
public void skillUpdated(SkillSet set, int id, Skill skill);
|
||||
|
||||
}
|
||||
|
||||
@@ -32,11 +32,6 @@ public final class SynchronizationSkillListener extends SkillAdapter {
|
||||
player.getBlockSet().add(SynchronizationBlock.createAppearanceBlock(player));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skillUpdated(SkillSet set, int id, Skill skill) {
|
||||
player.send(new UpdateSkillEvent(id, skill));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skillsUpdated(SkillSet set) {
|
||||
for (int id = 0; id < set.size(); id++) {
|
||||
@@ -44,4 +39,9 @@ public final class SynchronizationSkillListener extends SkillAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skillUpdated(SkillSet set, int id, Skill skill) {
|
||||
player.send(new UpdateSkillEvent(id, skill));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,9 +32,14 @@ public abstract class ScheduledTask {
|
||||
*/
|
||||
public ScheduledTask(int delay, boolean immediate) {
|
||||
setDelay(delay);
|
||||
this.pulses = immediate ? 0 : delay;
|
||||
pulses = immediate ? 0 : delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this task.
|
||||
*/
|
||||
public abstract void execute();
|
||||
|
||||
/**
|
||||
* Checks if this task is running.
|
||||
*
|
||||
@@ -44,6 +49,16 @@ public abstract class ScheduledTask {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulses this task: updates the delay and calls {@link #execute()} if necessary.
|
||||
*/
|
||||
final void pulse() {
|
||||
if (running && pulses-- == 0) {
|
||||
execute();
|
||||
pulses = delay;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the delay.
|
||||
*
|
||||
@@ -64,19 +79,4 @@ public abstract class ScheduledTask {
|
||||
running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pulses this task: updates the delay and calls {@link #execute()} if necessary.
|
||||
*/
|
||||
final void pulse() {
|
||||
if (running && pulses-- == 0) {
|
||||
execute();
|
||||
pulses = delay;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this task.
|
||||
*/
|
||||
public abstract void execute();
|
||||
|
||||
}
|
||||
|
||||
@@ -23,15 +23,6 @@ public final class Scheduler {
|
||||
*/
|
||||
private List<ScheduledTask> tasks = new ArrayList<ScheduledTask>();
|
||||
|
||||
/**
|
||||
* Schedules a new task.
|
||||
*
|
||||
* @param task The task to schedule.
|
||||
*/
|
||||
public void schedule(ScheduledTask task) {
|
||||
newTasks.add(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every pulse: executes tasks that are still pending, adds new tasks and stops old tasks.
|
||||
*/
|
||||
@@ -50,4 +41,13 @@ public final class Scheduler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a new task.
|
||||
*
|
||||
* @param task The task to schedule.
|
||||
*/
|
||||
public void schedule(ScheduledTask task) {
|
||||
newTasks.add(task);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.apollo.game.GameService;
|
||||
import org.apollo.game.model.Npc;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.Player;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.sync.task.NpcSynchronizationTask;
|
||||
import org.apollo.game.sync.task.PhasedSynchronizationTask;
|
||||
import org.apollo.game.sync.task.PlayerSynchronizationTask;
|
||||
|
||||
@@ -2,8 +2,8 @@ package org.apollo.game.sync;
|
||||
|
||||
import org.apollo.game.GameService;
|
||||
import org.apollo.game.model.Npc;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.Player;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.sync.task.NpcSynchronizationTask;
|
||||
import org.apollo.game.sync.task.PlayerSynchronizationTask;
|
||||
import org.apollo.game.sync.task.PostNpcSynchronizationTask;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apollo.game.sync.block;
|
||||
|
||||
import org.apollo.game.model.Inventory;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.Inventory;
|
||||
|
||||
/**
|
||||
* The appearance {@link SynchronizationBlock}.
|
||||
|
||||
@@ -4,8 +4,8 @@ import org.apollo.game.event.impl.ChatEvent;
|
||||
import org.apollo.game.model.Animation;
|
||||
import org.apollo.game.model.Direction;
|
||||
import org.apollo.game.model.Graphic;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.Player;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.sync.seg.SynchronizationSegment;
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,8 +13,8 @@ import org.apollo.game.sync.block.ChatBlock;
|
||||
import org.apollo.game.sync.block.SynchronizationBlock;
|
||||
import org.apollo.game.sync.block.SynchronizationBlockSet;
|
||||
import org.apollo.game.sync.seg.AddPlayerSegment;
|
||||
import org.apollo.game.sync.seg.RemoveCharacterSegment;
|
||||
import org.apollo.game.sync.seg.MovementSegment;
|
||||
import org.apollo.game.sync.seg.RemoveCharacterSegment;
|
||||
import org.apollo.game.sync.seg.SynchronizationSegment;
|
||||
import org.apollo.game.sync.seg.TeleportSegment;
|
||||
import org.apollo.util.CharacterRepository;
|
||||
@@ -82,8 +82,7 @@ public final class PlayerSynchronizationTask extends SynchronizationTask {
|
||||
int added = 0;
|
||||
|
||||
CharacterRepository<Player> repository = World.getWorld().getPlayerRepository();
|
||||
for (Iterator<Player> it = repository.iterator(); it.hasNext();) {
|
||||
Player p = it.next();
|
||||
for (Player p : repository) {
|
||||
if (localPlayers.size() >= 255) {
|
||||
player.flagExcessivePlayers();
|
||||
break;
|
||||
|
||||
@@ -25,6 +25,21 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a region update is required.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} otherwise.
|
||||
*/
|
||||
private boolean isRegionUpdateRequired() {
|
||||
Position current = player.getPosition();
|
||||
Position last = player.getLastKnownRegion();
|
||||
|
||||
int deltaX = current.getLocalX(last);
|
||||
int deltaY = current.getLocalY(last);
|
||||
|
||||
return deltaX < 16 || deltaX >= 88 || deltaY < 16 || deltaY >= 88;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
player.getWalkingQueue().pulse();
|
||||
@@ -47,19 +62,4 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a region update is required.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} otherwise.
|
||||
*/
|
||||
private boolean isRegionUpdateRequired() {
|
||||
Position current = player.getPosition();
|
||||
Position last = player.getLastKnownRegion();
|
||||
|
||||
int deltaX = current.getLocalX(last);
|
||||
int deltaY = current.getLocalY(last);
|
||||
|
||||
return deltaX < 16 || deltaX >= 88 || deltaY < 16 || deltaY >= 88;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import java.util.Map;
|
||||
|
||||
import org.apollo.game.event.Event;
|
||||
import org.apollo.game.event.handler.EventHandler;
|
||||
import org.apollo.game.event.handler.chain.EventHandlerChainGroup;
|
||||
import org.apollo.game.event.handler.chain.EventHandlerChain;
|
||||
import org.apollo.game.event.handler.chain.EventHandlerChainGroup;
|
||||
import org.apollo.util.xml.XmlNode;
|
||||
import org.apollo.util.xml.XmlParser;
|
||||
import org.xml.sax.SAXException;
|
||||
@@ -39,7 +39,7 @@ public final class EventHandlerChainParser {
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
*/
|
||||
public EventHandlerChainParser(InputStream is) throws SAXException {
|
||||
this.parser = new XmlParser();
|
||||
parser = new XmlParser();
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,10 +37,26 @@ public final class PluginMetaDataParser {
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
*/
|
||||
public PluginMetaDataParser(InputStream is) throws SAXException {
|
||||
this.parser = new XmlParser();
|
||||
parser = new XmlParser();
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the specified child element, if it exists.
|
||||
*
|
||||
* @param node The root node.
|
||||
* @param name The element name.
|
||||
* @return The node object.
|
||||
* @throws IOException If the element does not exist.
|
||||
*/
|
||||
private XmlNode getElement(XmlNode node, String name) throws IOException {
|
||||
XmlNode child = node.getChild(name);
|
||||
if (child == null) {
|
||||
throw new IOException("no " + name + " element found");
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the XML and creates a meta data object.
|
||||
*
|
||||
@@ -103,20 +119,4 @@ public final class PluginMetaDataParser {
|
||||
return new PluginMetaData(id, name, description, authors, scripts, dependencies, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the specified child element, if it exists.
|
||||
*
|
||||
* @param node The root node.
|
||||
* @param name The element name.
|
||||
* @return The node object.
|
||||
* @throws IOException If the element does not exist.
|
||||
*/
|
||||
private XmlNode getElement(XmlNode node, String name) throws IOException {
|
||||
XmlNode child = node.getChild(name);
|
||||
if (child == null) {
|
||||
throw new IOException("no " + name + " element found");
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public final class PlayerLoaderResponse {
|
||||
throw new IllegalArgumentException("player required for this status code");
|
||||
}
|
||||
this.status = status;
|
||||
this.player = null;
|
||||
player = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,15 +49,6 @@ public final class PlayerLoaderResponse {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status code.
|
||||
*
|
||||
* @return The status code.
|
||||
*/
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player.
|
||||
*
|
||||
@@ -67,4 +58,13 @@ public final class PlayerLoaderResponse {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status code.
|
||||
*
|
||||
* @return The status code.
|
||||
*/
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import org.apollo.game.model.Gender;
|
||||
import org.apollo.game.model.Inventory;
|
||||
import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.Player;
|
||||
import org.apollo.game.model.Player.PrivilegeLevel;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.Skill;
|
||||
import org.apollo.game.model.SkillSet;
|
||||
import org.apollo.game.model.Player.PrivilegeLevel;
|
||||
import org.apollo.io.player.PlayerLoader;
|
||||
import org.apollo.io.player.PlayerLoaderResponse;
|
||||
import org.apollo.net.codec.login.LoginConstants;
|
||||
|
||||
@@ -44,12 +44,12 @@ public final class BinaryPlayerSaver implements PlayerSaver {
|
||||
Appearance appearance = player.getAppearance();
|
||||
out.writeByte(appearance.getGender().toInteger());
|
||||
int[] style = appearance.getStyle();
|
||||
for (int i = 0; i < style.length; i++) {
|
||||
out.writeByte(style[i]);
|
||||
for (int element : style) {
|
||||
out.writeByte(element);
|
||||
}
|
||||
int[] colors = appearance.getColors();
|
||||
for (int i = 0; i < colors.length; i++) {
|
||||
out.writeByte(colors[i]);
|
||||
for (int color : colors) {
|
||||
out.writeByte(color);
|
||||
}
|
||||
out.flush();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.apollo.io.player.impl;
|
||||
|
||||
import org.apollo.game.model.Player;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.Player.PrivilegeLevel;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.io.player.PlayerLoader;
|
||||
import org.apollo.io.player.PlayerLoaderResponse;
|
||||
import org.apollo.net.codec.login.LoginConstants;
|
||||
|
||||
@@ -87,6 +87,14 @@ public final class LoginService extends Service {
|
||||
saver = (PlayerSaver) saverClazz.newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the login service.
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
/* empty - here for consistency with other services */
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits a login request.
|
||||
*
|
||||
@@ -113,12 +121,4 @@ public final class LoginService extends Service {
|
||||
executor.submit(new PlayerSaverWorker(saver, session, player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the login service.
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
/* empty - here for consistency with other services */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,12 +43,7 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
|
||||
* @param context The server context.
|
||||
*/
|
||||
public ApolloHandler(ServerContext context) {
|
||||
this.serverContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
|
||||
e.getChannel().close();
|
||||
serverContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,6 +64,17 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
|
||||
e.getChannel().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
logger.log(Level.WARNING, "Exception occured for channel: " + e.getChannel() + ", closing...", e.getCause());
|
||||
ctx.getChannel().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
if (ctx.getAttachment() == null) {
|
||||
@@ -96,10 +102,4 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
||||
logger.log(Level.WARNING, "Exception occured for channel: " + e.getChannel() + ", closing...", e.getCause());
|
||||
ctx.getChannel().close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public final class DataConstants {
|
||||
*/
|
||||
static {
|
||||
for (int i = 0; i < BIT_MASK.length; i++) {
|
||||
BIT_MASK[i] = ((1 << i) - 1);
|
||||
BIT_MASK[i] = (1 << i) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,19 +40,10 @@ public final class GamePacket {
|
||||
public GamePacket(int opcode, PacketType type, ChannelBuffer payload) {
|
||||
this.opcode = opcode;
|
||||
this.type = type;
|
||||
this.length = payload.readableBytes();
|
||||
length = payload.readableBytes();
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the opcode.
|
||||
*
|
||||
* @return The opcode.
|
||||
*/
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the payload length.
|
||||
*
|
||||
@@ -62,6 +53,15 @@ public final class GamePacket {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the opcode.
|
||||
*
|
||||
* @return The opcode.
|
||||
*/
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the payload.
|
||||
*
|
||||
|
||||
@@ -66,19 +66,25 @@ public final class GamePacketBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GamePacket} based on the current contents of this builder.
|
||||
* Checks that this builder is in the bit access mode.
|
||||
*
|
||||
* @return The {@link GamePacket}.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode, or if the packet is raw.
|
||||
* @throws IllegalStateException If the builder is not in bit access mode.
|
||||
*/
|
||||
public GamePacket toGamePacket() {
|
||||
if (type == PacketType.RAW) {
|
||||
throw new IllegalStateException("Raw packets cannot be converted to a game packet");
|
||||
private void checkBitAccess() {
|
||||
if (mode != AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("For bit-based calls to work, the mode must be bit access");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that this builder is in the byte access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
private void checkByteAccess() {
|
||||
if (mode != AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("Must be in byte access mode to convert to a packet");
|
||||
throw new IllegalStateException("For byte-based calls to work, the mode must be byte access");
|
||||
}
|
||||
return new GamePacket(opcode, type, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,97 +98,6 @@ public final class GamePacketBuilder {
|
||||
return buffer.writerIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the byte access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in byte access mode.
|
||||
*/
|
||||
public void switchToByteAccess() {
|
||||
if (mode == AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("Already in byte access mode");
|
||||
}
|
||||
mode = AccessMode.BYTE_ACCESS;
|
||||
buffer.writerIndex((bitIndex + 7) / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the bit access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in bit access mode.
|
||||
*/
|
||||
public void switchToBitAccess() {
|
||||
if (mode == AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("Already in bit access mode");
|
||||
}
|
||||
mode = AccessMode.BIT_ACCESS;
|
||||
bitIndex = buffer.writerIndex() * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a raw builder. Both builders (this and parameter) must be in byte access mode.
|
||||
*
|
||||
* @param builder The builder.
|
||||
*/
|
||||
public void putRawBuilder(GamePacketBuilder builder) {
|
||||
checkByteAccess();
|
||||
if (builder.type != PacketType.RAW) {
|
||||
throw new IllegalArgumentException("Builder must be raw!");
|
||||
}
|
||||
builder.checkByteAccess();
|
||||
putBytes(builder.buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a raw builder in reverse. Both builders (this and parameter) must be in byte access mode.
|
||||
*
|
||||
* @param builder The builder.
|
||||
*/
|
||||
public void putRawBuilderReverse(GamePacketBuilder builder) {
|
||||
checkByteAccess();
|
||||
if (builder.type != PacketType.RAW) {
|
||||
throw new IllegalArgumentException("Builder must be raw!");
|
||||
}
|
||||
builder.checkByteAccess();
|
||||
putBytesReverse(builder.buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a standard data type with the specified value.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param value The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public void put(DataType type, Number value) {
|
||||
put(type, DataOrder.BIG, DataTransformation.NONE, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a standard data type with the specified value and byte order.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @param value The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public void put(DataType type, DataOrder order, Number value) {
|
||||
put(type, order, DataTransformation.NONE, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a standard data type with the specified value and transformation.
|
||||
*
|
||||
* @param type The type.
|
||||
* @param transformation The transformation.
|
||||
* @param value The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public void put(DataType type, DataTransformation transformation, Number value) {
|
||||
put(type, DataOrder.BIG, transformation, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a standard data type with the specified value, byte order and transformation.
|
||||
*
|
||||
@@ -203,14 +118,14 @@ public final class GamePacketBuilder {
|
||||
if (transformation == DataTransformation.ADD) {
|
||||
buffer.writeByte((byte) (longValue + 128));
|
||||
} else if (transformation == DataTransformation.NEGATE) {
|
||||
buffer.writeByte((byte) (-longValue));
|
||||
buffer.writeByte((byte) -longValue);
|
||||
} else if (transformation == DataTransformation.SUBTRACT) {
|
||||
buffer.writeByte((byte) (128 - longValue));
|
||||
} else {
|
||||
throw new IllegalArgumentException("unknown transformation");
|
||||
}
|
||||
} else {
|
||||
buffer.writeByte((byte) (longValue >> (i * 8)));
|
||||
buffer.writeByte((byte) (longValue >> i * 8));
|
||||
}
|
||||
}
|
||||
} else if (order == DataOrder.LITTLE) {
|
||||
@@ -219,14 +134,14 @@ public final class GamePacketBuilder {
|
||||
if (transformation == DataTransformation.ADD) {
|
||||
buffer.writeByte((byte) (longValue + 128));
|
||||
} else if (transformation == DataTransformation.NEGATE) {
|
||||
buffer.writeByte((byte) (-longValue));
|
||||
buffer.writeByte((byte) -longValue);
|
||||
} else if (transformation == DataTransformation.SUBTRACT) {
|
||||
buffer.writeByte((byte) (128 - longValue));
|
||||
} else {
|
||||
throw new IllegalArgumentException("unknown transformation");
|
||||
}
|
||||
} else {
|
||||
buffer.writeByte((byte) (longValue >> (i * 8)));
|
||||
buffer.writeByte((byte) (longValue >> i * 8));
|
||||
}
|
||||
}
|
||||
} else if (order == DataOrder.MIDDLE) {
|
||||
@@ -257,122 +172,40 @@ public final class GamePacketBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a string into the buffer.
|
||||
*
|
||||
* @param str The string.
|
||||
*/
|
||||
public void putString(String str) {
|
||||
checkByteAccess();
|
||||
char[] chars = str.toCharArray();
|
||||
for (char c : chars) {
|
||||
buffer.writeByte((byte) c);
|
||||
}
|
||||
buffer.writeByte(NetworkConstants.STRING_TERMINATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a smart into the buffer.
|
||||
* Puts a standard data type with the specified value and byte order.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @param value The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public void putSmart(int value) {
|
||||
checkByteAccess();
|
||||
if (value < 128) {
|
||||
buffer.writeByte(value);
|
||||
} else {
|
||||
buffer.writeShort(value);
|
||||
}
|
||||
public void put(DataType type, DataOrder order, Number value) {
|
||||
put(type, order, DataTransformation.NONE, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the bytes from the specified buffer into this packet's buffer.
|
||||
*
|
||||
* @param buffer The source {@link ChannelBuffer}.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
public void putBytes(ChannelBuffer buffer) {
|
||||
byte[] bytes = new byte[buffer.readableBytes()];
|
||||
buffer.markReaderIndex();
|
||||
try {
|
||||
buffer.readBytes(bytes);
|
||||
} finally {
|
||||
buffer.resetReaderIndex();
|
||||
}
|
||||
putBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the bytes from the specified buffer into this packet's buffer, in reverse.
|
||||
*
|
||||
* @param buffer The source {@link ChannelBuffer}.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
public void putBytesReverse(ChannelBuffer buffer) {
|
||||
byte[] bytes = new byte[buffer.readableBytes()];
|
||||
buffer.markReaderIndex();
|
||||
try {
|
||||
buffer.readBytes(bytes);
|
||||
} finally {
|
||||
buffer.resetReaderIndex();
|
||||
}
|
||||
putBytesReverse(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the specified byte array into the buffer.
|
||||
*
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in bit access mode.
|
||||
*/
|
||||
public void putBytes(byte[] bytes) {
|
||||
buffer.writeBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the bytes into the buffer with the specified transformation.
|
||||
* Puts a standard data type with the specified value and transformation.
|
||||
*
|
||||
* @param type The type.
|
||||
* @param transformation The transformation.
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
* @param value The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public void putBytes(DataTransformation transformation, byte[] bytes) {
|
||||
if (transformation == DataTransformation.NONE) {
|
||||
putBytes(bytes);
|
||||
} else {
|
||||
for (byte b : bytes) {
|
||||
put(DataType.BYTE, transformation, b);
|
||||
}
|
||||
}
|
||||
public void put(DataType type, DataTransformation transformation, Number value) {
|
||||
put(type, DataOrder.BIG, transformation, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the specified byte array into the buffer in reverse.
|
||||
* Puts a standard data type with the specified value.
|
||||
*
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
* @param type The data type.
|
||||
* @param value The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public void putBytesReverse(byte[] bytes) {
|
||||
checkByteAccess();
|
||||
for (int i = bytes.length - 1; i >= 0; i--) {
|
||||
buffer.writeByte(bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the specified byte array into the buffer in reverse with the specified transformation.
|
||||
*
|
||||
* @param transformation The transformation.
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
public void putBytesReverse(DataTransformation transformation, byte[] bytes) {
|
||||
if (transformation == DataTransformation.NONE) {
|
||||
putBytesReverse(bytes);
|
||||
} else {
|
||||
for (int i = bytes.length - 1; i >= 0; i--) {
|
||||
put(DataType.BYTE, transformation, bytes[i]);
|
||||
}
|
||||
}
|
||||
public void put(DataType type, Number value) {
|
||||
put(type, DataOrder.BIG, DataTransformation.NONE, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -422,7 +255,7 @@ public final class GamePacketBuilder {
|
||||
for (; numBits > bitOffset; bitOffset = 8) {
|
||||
int tmp = buffer.getByte(bytePos);
|
||||
tmp &= ~DataConstants.BIT_MASK[bitOffset];
|
||||
tmp |= (value >> (numBits - bitOffset)) & DataConstants.BIT_MASK[bitOffset];
|
||||
tmp |= value >> numBits - bitOffset & DataConstants.BIT_MASK[bitOffset];
|
||||
buffer.setByte(bytePos++, tmp);
|
||||
numBits -= bitOffset;
|
||||
}
|
||||
@@ -433,32 +266,199 @@ public final class GamePacketBuilder {
|
||||
buffer.setByte(bytePos, tmp);
|
||||
} else {
|
||||
int tmp = buffer.getByte(bytePos);
|
||||
tmp &= ~(DataConstants.BIT_MASK[numBits] << (bitOffset - numBits));
|
||||
tmp |= (value & DataConstants.BIT_MASK[numBits]) << (bitOffset - numBits);
|
||||
tmp &= ~(DataConstants.BIT_MASK[numBits] << bitOffset - numBits);
|
||||
tmp |= (value & DataConstants.BIT_MASK[numBits]) << bitOffset - numBits;
|
||||
buffer.setByte(bytePos, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that this builder is in the byte access mode.
|
||||
* Puts the specified byte array into the buffer.
|
||||
*
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in bit access mode.
|
||||
*/
|
||||
public void putBytes(byte[] bytes) {
|
||||
buffer.writeBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the bytes from the specified buffer into this packet's buffer.
|
||||
*
|
||||
* @param buffer The source {@link ChannelBuffer}.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
private void checkByteAccess() {
|
||||
if (mode != AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("For byte-based calls to work, the mode must be byte access");
|
||||
public void putBytes(ChannelBuffer buffer) {
|
||||
byte[] bytes = new byte[buffer.readableBytes()];
|
||||
buffer.markReaderIndex();
|
||||
try {
|
||||
buffer.readBytes(bytes);
|
||||
} finally {
|
||||
buffer.resetReaderIndex();
|
||||
}
|
||||
putBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the bytes into the buffer with the specified transformation.
|
||||
*
|
||||
* @param transformation The transformation.
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
public void putBytes(DataTransformation transformation, byte[] bytes) {
|
||||
if (transformation == DataTransformation.NONE) {
|
||||
putBytes(bytes);
|
||||
} else {
|
||||
for (byte b : bytes) {
|
||||
put(DataType.BYTE, transformation, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that this builder is in the bit access mode.
|
||||
* Puts the specified byte array into the buffer in reverse.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is not in bit access mode.
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
private void checkBitAccess() {
|
||||
if (mode != AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("For bit-based calls to work, the mode must be bit access");
|
||||
public void putBytesReverse(byte[] bytes) {
|
||||
checkByteAccess();
|
||||
for (int i = bytes.length - 1; i >= 0; i--) {
|
||||
buffer.writeByte(bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the bytes from the specified buffer into this packet's buffer, in reverse.
|
||||
*
|
||||
* @param buffer The source {@link ChannelBuffer}.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
public void putBytesReverse(ChannelBuffer buffer) {
|
||||
byte[] bytes = new byte[buffer.readableBytes()];
|
||||
buffer.markReaderIndex();
|
||||
try {
|
||||
buffer.readBytes(bytes);
|
||||
} finally {
|
||||
buffer.resetReaderIndex();
|
||||
}
|
||||
putBytesReverse(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the specified byte array into the buffer in reverse with the specified transformation.
|
||||
*
|
||||
* @param transformation The transformation.
|
||||
* @param bytes The byte array.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode.
|
||||
*/
|
||||
public void putBytesReverse(DataTransformation transformation, byte[] bytes) {
|
||||
if (transformation == DataTransformation.NONE) {
|
||||
putBytesReverse(bytes);
|
||||
} else {
|
||||
for (int i = bytes.length - 1; i >= 0; i--) {
|
||||
put(DataType.BYTE, transformation, bytes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a raw builder. Both builders (this and parameter) must be in byte access mode.
|
||||
*
|
||||
* @param builder The builder.
|
||||
*/
|
||||
public void putRawBuilder(GamePacketBuilder builder) {
|
||||
checkByteAccess();
|
||||
if (builder.type != PacketType.RAW) {
|
||||
throw new IllegalArgumentException("Builder must be raw!");
|
||||
}
|
||||
builder.checkByteAccess();
|
||||
putBytes(builder.buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a raw builder in reverse. Both builders (this and parameter) must be in byte access mode.
|
||||
*
|
||||
* @param builder The builder.
|
||||
*/
|
||||
public void putRawBuilderReverse(GamePacketBuilder builder) {
|
||||
checkByteAccess();
|
||||
if (builder.type != PacketType.RAW) {
|
||||
throw new IllegalArgumentException("Builder must be raw!");
|
||||
}
|
||||
builder.checkByteAccess();
|
||||
putBytesReverse(builder.buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a smart into the buffer.
|
||||
*
|
||||
* @param value The value.
|
||||
*/
|
||||
public void putSmart(int value) {
|
||||
checkByteAccess();
|
||||
if (value < 128) {
|
||||
buffer.writeByte(value);
|
||||
} else {
|
||||
buffer.writeShort(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a string into the buffer.
|
||||
*
|
||||
* @param str The string.
|
||||
*/
|
||||
public void putString(String str) {
|
||||
checkByteAccess();
|
||||
char[] chars = str.toCharArray();
|
||||
for (char c : chars) {
|
||||
buffer.writeByte((byte) c);
|
||||
}
|
||||
buffer.writeByte(NetworkConstants.STRING_TERMINATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the bit access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in bit access mode.
|
||||
*/
|
||||
public void switchToBitAccess() {
|
||||
if (mode == AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("Already in bit access mode");
|
||||
}
|
||||
mode = AccessMode.BIT_ACCESS;
|
||||
bitIndex = buffer.writerIndex() * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the byte access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in byte access mode.
|
||||
*/
|
||||
public void switchToByteAccess() {
|
||||
if (mode == AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("Already in byte access mode");
|
||||
}
|
||||
mode = AccessMode.BYTE_ACCESS;
|
||||
buffer.writerIndex((bitIndex + 7) / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link GamePacket} based on the current contents of this builder.
|
||||
*
|
||||
* @return The {@link GamePacket}.
|
||||
* @throws IllegalStateException If the builder is not in byte access mode, or if the packet is raw.
|
||||
*/
|
||||
public GamePacket toGamePacket() {
|
||||
if (type == PacketType.RAW) {
|
||||
throw new IllegalStateException("Raw packets cannot be converted to a game packet");
|
||||
}
|
||||
if (mode != AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("Must be in byte access mode to convert to a packet");
|
||||
}
|
||||
return new GamePacket(opcode, type, buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,6 +70,27 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes in the length state.
|
||||
*
|
||||
* @param ctx The channel handler context.
|
||||
* @param channel The channel.
|
||||
* @param buffer The buffer.
|
||||
* @return The frame, or {@code null}.
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
private Object decodeLength(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
|
||||
if (buffer.readable()) {
|
||||
length = buffer.readUnsignedByte();
|
||||
if (length == 0) {
|
||||
return decodeZeroLengthPacket(ctx, channel, buffer);
|
||||
} else {
|
||||
setState(GameDecoderState.GAME_PAYLOAD);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes in the opcode state.
|
||||
*
|
||||
@@ -82,7 +103,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
private Object decodeOpcode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
|
||||
if (buffer.readable()) {
|
||||
int encryptedOpcode = buffer.readUnsignedByte();
|
||||
opcode = (encryptedOpcode - random.nextInt()) & 0xFF;
|
||||
opcode = encryptedOpcode - random.nextInt() & 0xFF;
|
||||
|
||||
PacketMetaData metaData = release.getIncomingPacketMetaData(opcode);
|
||||
if (metaData == null) {
|
||||
@@ -109,27 +130,6 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes in the length state.
|
||||
*
|
||||
* @param ctx The channel handler context.
|
||||
* @param channel The channel.
|
||||
* @param buffer The buffer.
|
||||
* @return The frame, or {@code null}.
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
private Object decodeLength(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
|
||||
if (buffer.readable()) {
|
||||
length = buffer.readUnsignedByte();
|
||||
if (length == 0) {
|
||||
return decodeZeroLengthPacket(ctx, channel, buffer);
|
||||
} else {
|
||||
setState(GameDecoderState.GAME_PAYLOAD);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes in the payload state.
|
||||
*
|
||||
|
||||
@@ -53,7 +53,7 @@ public final class GamePacketEncoder extends OneToOneEncoder {
|
||||
}
|
||||
|
||||
ChannelBuffer buffer = ChannelBuffers.buffer(headerLength + payloadLength);
|
||||
buffer.writeByte((packet.getOpcode() + random.nextInt()) & 0xFF);
|
||||
buffer.writeByte(packet.getOpcode() + random.nextInt() & 0xFF);
|
||||
if (type == PacketType.VARIABLE_BYTE) {
|
||||
buffer.writeByte(payloadLength);
|
||||
} else if (type == PacketType.VARIABLE_SHORT) {
|
||||
|
||||
@@ -35,197 +35,27 @@ public final class GamePacketReader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of this reader.
|
||||
* Checks that this reader is in the bit access mode.
|
||||
*
|
||||
* @return The length of this reader.
|
||||
* @throws IllegalStateException If the reader is not in bit access mode.
|
||||
*/
|
||||
public int getLength() {
|
||||
checkByteAccess();
|
||||
return buffer.writableBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the byte access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in byte access mode.
|
||||
*/
|
||||
public void switchToByteAccess() {
|
||||
if (mode == AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("Already in byte access mode");
|
||||
}
|
||||
mode = AccessMode.BYTE_ACCESS;
|
||||
buffer.readerIndex((bitIndex + 7) / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the bit access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in bit access mode.
|
||||
*/
|
||||
public void switchToBitAccess() {
|
||||
if (mode == AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("Already in bit access mode");
|
||||
}
|
||||
mode = AccessMode.BIT_ACCESS;
|
||||
bitIndex = buffer.readerIndex() * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string from the buffer.
|
||||
*
|
||||
* @return The string.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public String getString() {
|
||||
checkByteAccess();
|
||||
return ChannelBufferUtil.readString(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a signed smart from the buffer.
|
||||
*
|
||||
* @return The smart.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public int getSignedSmart() {
|
||||
checkByteAccess();
|
||||
int peek = buffer.getByte(buffer.readerIndex());
|
||||
if (peek < 128) {
|
||||
return buffer.readByte() - 64;
|
||||
} else {
|
||||
return buffer.readShort() - 49152;
|
||||
private void checkBitAccess() {
|
||||
if (mode != AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("For bit-based calls to work, the mode must be bit access");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned smart from the buffer.
|
||||
* Checks that this reader is in the byte access mode.
|
||||
*
|
||||
* @return The smart.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalStateException If the reader is not in byte access mode.
|
||||
*/
|
||||
public int getUnsignedSmart() {
|
||||
checkByteAccess();
|
||||
int peek = buffer.getByte(buffer.readerIndex());
|
||||
if (peek < 128) {
|
||||
return buffer.readByte();
|
||||
} else {
|
||||
return buffer.readShort() - 32768;
|
||||
private void checkByteAccess() {
|
||||
if (mode != AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("For byte-based calls to work, the mode must be byte access");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a signed data type from the buffer.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public long getSigned(DataType type) {
|
||||
return getSigned(type, DataOrder.BIG, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a signed data type from the buffer with the specified order.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getSigned(DataType type, DataOrder order) {
|
||||
return getSigned(type, order, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a signed data type from the buffer with the specified transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getSigned(DataType type, DataTransformation transformation) {
|
||||
return getSigned(type, DataOrder.BIG, transformation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a signed data type from the buffer with the specified order and transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getSigned(DataType type, DataOrder order, DataTransformation transformation) {
|
||||
long longValue = get(type, order, transformation);
|
||||
if (type != DataType.LONG) {
|
||||
int max = (int) (Math.pow(2, type.getBytes() * 8 - 1) - 1);
|
||||
if (longValue > max) {
|
||||
longValue -= (max + 1) * 2;
|
||||
}
|
||||
}
|
||||
return longValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public long getUnsigned(DataType type) {
|
||||
return getUnsigned(type, DataOrder.BIG, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer with the specified order.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getUnsigned(DataType type, DataOrder order) {
|
||||
return getUnsigned(type, order, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer with the specified transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getUnsigned(DataType type, DataTransformation transformation) {
|
||||
return getUnsigned(type, DataOrder.BIG, transformation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer with the specified order and transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getUnsigned(DataType type, DataOrder order, DataTransformation transformation) {
|
||||
long longValue = get(type, order, transformation);
|
||||
if (type == DataType.LONG) {
|
||||
throw new IllegalArgumentException("due to java restrictions, longs must be read as signed types");
|
||||
}
|
||||
return longValue & 0xFFFFFFFFFFFFFFFFL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a standard data type from the buffer with the specified order and transformation.
|
||||
*
|
||||
@@ -244,32 +74,32 @@ public final class GamePacketReader {
|
||||
for (int i = length - 1; i >= 0; i--) {
|
||||
if (i == 0 && transformation != DataTransformation.NONE) {
|
||||
if (transformation == DataTransformation.ADD) {
|
||||
longValue |= (buffer.readByte() - 128) & 0xFF;
|
||||
longValue |= buffer.readByte() - 128 & 0xFF;
|
||||
} else if (transformation == DataTransformation.NEGATE) {
|
||||
longValue |= (-buffer.readByte()) & 0xFF;
|
||||
longValue |= -buffer.readByte() & 0xFF;
|
||||
} else if (transformation == DataTransformation.SUBTRACT) {
|
||||
longValue |= (128 - buffer.readByte()) & 0xFF;
|
||||
longValue |= 128 - buffer.readByte() & 0xFF;
|
||||
} else {
|
||||
throw new IllegalArgumentException("unknown transformation");
|
||||
}
|
||||
} else {
|
||||
longValue |= ((buffer.readByte() & 0xFF) << (i * 8));
|
||||
longValue |= (buffer.readByte() & 0xFF) << i * 8;
|
||||
}
|
||||
}
|
||||
} else if (order == DataOrder.LITTLE) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i == 0 && transformation != DataTransformation.NONE) {
|
||||
if (transformation == DataTransformation.ADD) {
|
||||
longValue |= (buffer.readByte() - 128) & 0xFF;
|
||||
longValue |= buffer.readByte() - 128 & 0xFF;
|
||||
} else if (transformation == DataTransformation.NEGATE) {
|
||||
longValue |= (-buffer.readByte()) & 0xFF;
|
||||
longValue |= -buffer.readByte() & 0xFF;
|
||||
} else if (transformation == DataTransformation.SUBTRACT) {
|
||||
longValue |= (128 - buffer.readByte()) & 0xFF;
|
||||
longValue |= 128 - buffer.readByte() & 0xFF;
|
||||
} else {
|
||||
throw new IllegalArgumentException("unknown transformation");
|
||||
}
|
||||
} else {
|
||||
longValue |= ((buffer.readByte() & 0xFF) << (i * 8));
|
||||
longValue |= (buffer.readByte() & 0xFF) << i * 8;
|
||||
}
|
||||
}
|
||||
} else if (order == DataOrder.MIDDLE) {
|
||||
@@ -300,6 +130,48 @@ public final class GamePacketReader {
|
||||
return longValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a bit from the buffer.
|
||||
*
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If the reader is not in bit access mode.
|
||||
*/
|
||||
public int getBit() {
|
||||
return getBits(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets {@code numBits} from the buffer.
|
||||
*
|
||||
* @param numBits The number of bits.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If the reader is not in bit access mode.
|
||||
* @throws IllegalArgumentException If the number of bits is not between 1 and 31 inclusive.
|
||||
*/
|
||||
public int getBits(int numBits) {
|
||||
if (numBits < 0 || numBits > 32) {
|
||||
throw new IllegalArgumentException("Number of bits must be between 1 and 32 inclusive");
|
||||
}
|
||||
|
||||
checkBitAccess();
|
||||
|
||||
int bytePos = bitIndex >> 3;
|
||||
int bitOffset = 8 - (bitIndex & 7);
|
||||
int value = 0;
|
||||
bitIndex += numBits;
|
||||
|
||||
for (; numBits > bitOffset; bitOffset = 8) {
|
||||
value += (buffer.getByte(bytePos++) & DataConstants.BIT_MASK[bitOffset]) << numBits - bitOffset;
|
||||
numBits -= bitOffset;
|
||||
}
|
||||
if (numBits == bitOffset) {
|
||||
value += buffer.getByte(bytePos) & DataConstants.BIT_MASK[bitOffset];
|
||||
} else {
|
||||
value += buffer.getByte(bytePos) >> bitOffset - numBits & DataConstants.BIT_MASK[numBits];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets bytes.
|
||||
*
|
||||
@@ -361,67 +233,195 @@ public final class GamePacketReader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that this reader is in the byte access mode.
|
||||
* Gets the length of this reader.
|
||||
*
|
||||
* @throws IllegalStateException If the reader is not in byte access mode.
|
||||
* @return The length of this reader.
|
||||
*/
|
||||
private void checkByteAccess() {
|
||||
if (mode != AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("For byte-based calls to work, the mode must be byte access");
|
||||
}
|
||||
public int getLength() {
|
||||
checkByteAccess();
|
||||
return buffer.writableBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that this reader is in the bit access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the reader is not in bit access mode.
|
||||
*/
|
||||
private void checkBitAccess() {
|
||||
if (mode != AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("For bit-based calls to work, the mode must be bit access");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a bit from the buffer.
|
||||
* Gets a signed data type from the buffer.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If the reader is not in bit access mode.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public int getBit() {
|
||||
return getBits(1);
|
||||
public long getSigned(DataType type) {
|
||||
return getSigned(type, DataOrder.BIG, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets {@code numBits} from the buffer.
|
||||
* Gets a signed data type from the buffer with the specified order.
|
||||
*
|
||||
* @param numBits The number of bits.
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If the reader is not in bit access mode.
|
||||
* @throws IllegalArgumentException If the number of bits is not between 1 and 31 inclusive.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public int getBits(int numBits) {
|
||||
if (numBits < 0 || numBits > 32) {
|
||||
throw new IllegalArgumentException("Number of bits must be between 1 and 32 inclusive");
|
||||
public long getSigned(DataType type, DataOrder order) {
|
||||
return getSigned(type, order, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a signed data type from the buffer with the specified order and transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getSigned(DataType type, DataOrder order, DataTransformation transformation) {
|
||||
long longValue = get(type, order, transformation);
|
||||
if (type != DataType.LONG) {
|
||||
int max = (int) (Math.pow(2, type.getBytes() * 8 - 1) - 1);
|
||||
if (longValue > max) {
|
||||
longValue -= (max + 1) * 2;
|
||||
}
|
||||
}
|
||||
return longValue;
|
||||
}
|
||||
|
||||
checkBitAccess();
|
||||
/**
|
||||
* Gets a signed data type from the buffer with the specified transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getSigned(DataType type, DataTransformation transformation) {
|
||||
return getSigned(type, DataOrder.BIG, transformation);
|
||||
}
|
||||
|
||||
int bytePos = bitIndex >> 3;
|
||||
int bitOffset = 8 - (bitIndex & 7);
|
||||
int value = 0;
|
||||
bitIndex += numBits;
|
||||
|
||||
for (; numBits > bitOffset; bitOffset = 8) {
|
||||
value += (buffer.getByte(bytePos++) & DataConstants.BIT_MASK[bitOffset]) << numBits - bitOffset;
|
||||
numBits -= bitOffset;
|
||||
}
|
||||
if (numBits == bitOffset) {
|
||||
value += buffer.getByte(bytePos) & DataConstants.BIT_MASK[bitOffset];
|
||||
/**
|
||||
* Gets a signed smart from the buffer.
|
||||
*
|
||||
* @return The smart.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public int getSignedSmart() {
|
||||
checkByteAccess();
|
||||
int peek = buffer.getByte(buffer.readerIndex());
|
||||
if (peek < 128) {
|
||||
return buffer.readByte() - 64;
|
||||
} else {
|
||||
value += buffer.getByte(bytePos) >> bitOffset - numBits & DataConstants.BIT_MASK[numBits];
|
||||
return buffer.readShort() - 49152;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string from the buffer.
|
||||
*
|
||||
* @return The string.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public String getString() {
|
||||
checkByteAccess();
|
||||
return ChannelBufferUtil.readString(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public long getUnsigned(DataType type) {
|
||||
return getUnsigned(type, DataOrder.BIG, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer with the specified order.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getUnsigned(DataType type, DataOrder order) {
|
||||
return getUnsigned(type, order, DataTransformation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer with the specified order and transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param order The byte order.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getUnsigned(DataType type, DataOrder order, DataTransformation transformation) {
|
||||
long longValue = get(type, order, transformation);
|
||||
if (type == DataType.LONG) {
|
||||
throw new IllegalArgumentException("due to java restrictions, longs must be read as signed types");
|
||||
}
|
||||
return longValue & 0xFFFFFFFFFFFFFFFFL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned data type from the buffer with the specified transformation.
|
||||
*
|
||||
* @param type The data type.
|
||||
* @param transformation The data transformation.
|
||||
* @return The value.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
* @throws IllegalArgumentException If the combination is invalid.
|
||||
*/
|
||||
public long getUnsigned(DataType type, DataTransformation transformation) {
|
||||
return getUnsigned(type, DataOrder.BIG, transformation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unsigned smart from the buffer.
|
||||
*
|
||||
* @return The smart.
|
||||
* @throws IllegalStateException If this reader is not in byte access mode.
|
||||
*/
|
||||
public int getUnsignedSmart() {
|
||||
checkByteAccess();
|
||||
int peek = buffer.getByte(buffer.readerIndex());
|
||||
if (peek < 128) {
|
||||
return buffer.readByte();
|
||||
} else {
|
||||
return buffer.readShort() - 32768;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the bit access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in bit access mode.
|
||||
*/
|
||||
public void switchToBitAccess() {
|
||||
if (mode == AccessMode.BIT_ACCESS) {
|
||||
throw new IllegalStateException("Already in bit access mode");
|
||||
}
|
||||
mode = AccessMode.BIT_ACCESS;
|
||||
bitIndex = buffer.readerIndex() * 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches this builder's mode to the byte access mode.
|
||||
*
|
||||
* @throws IllegalStateException If the builder is already in byte access mode.
|
||||
*/
|
||||
public void switchToByteAccess() {
|
||||
if (mode == AccessMode.BYTE_ACCESS) {
|
||||
throw new IllegalStateException("Already in byte access mode");
|
||||
}
|
||||
mode = AccessMode.BYTE_ACCESS;
|
||||
buffer.readerIndex((bitIndex + 7) / 8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public final class JagGrabRequestDecoder extends OneToOneDecoder {
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception {
|
||||
if (msg instanceof String) {
|
||||
String str = ((String) msg);
|
||||
String str = (String) msg;
|
||||
if (str.startsWith("JAGGRAB /")) {
|
||||
String filePath = str.substring(8).trim();
|
||||
return new JagGrabRequest(filePath);
|
||||
|
||||
@@ -150,7 +150,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
}
|
||||
|
||||
int securePayloadLength = payload.readUnsignedByte();
|
||||
if (securePayloadLength != (loginLength - 41)) {
|
||||
if (securePayloadLength != loginLength - 41) {
|
||||
throw new Exception("Secure payload length mismatch");
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,15 @@ public final class LoginRequest {
|
||||
this.archiveCrcs = archiveCrcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the archive CRCs.
|
||||
*
|
||||
* @return The array of archive CRCs.
|
||||
*/
|
||||
public int[] getArchiveCrcs() {
|
||||
return archiveCrcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's credentials.
|
||||
*
|
||||
@@ -78,6 +87,15 @@ public final class LoginRequest {
|
||||
return randomPair;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release number.
|
||||
*
|
||||
* @return The release number.
|
||||
*/
|
||||
public int getReleaseNumber() {
|
||||
return releaseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this client is in low memory mode.
|
||||
*
|
||||
@@ -96,22 +114,4 @@ public final class LoginRequest {
|
||||
return reconnecting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release number.
|
||||
*
|
||||
* @return The release number.
|
||||
*/
|
||||
public int getReleaseNumber() {
|
||||
return releaseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the archive CRCs.
|
||||
*
|
||||
* @return The array of archive CRCs.
|
||||
*/
|
||||
public int[] getArchiveCrcs() {
|
||||
return archiveCrcs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,6 +35,15 @@ public final class LoginResponse {
|
||||
this.flagged = flagged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rights level.
|
||||
*
|
||||
* @return The rights level.
|
||||
*/
|
||||
public int getRights() {
|
||||
return rights;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status.
|
||||
*
|
||||
@@ -53,13 +62,4 @@ public final class LoginResponse {
|
||||
return flagged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rights level.
|
||||
*
|
||||
* @return The rights level.
|
||||
*/
|
||||
public int getRights() {
|
||||
return rights;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -98,6 +98,20 @@ public final class OnDemandRequest implements Comparable<OnDemandRequest> {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(OnDemandRequest o) {
|
||||
int thisPriority = priority.toInteger();
|
||||
int otherPriority = o.priority.toInteger();
|
||||
|
||||
if (thisPriority < otherPriority) {
|
||||
return 1;
|
||||
} else if (thisPriority == otherPriority) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file descriptor.
|
||||
*
|
||||
@@ -116,18 +130,4 @@ public final class OnDemandRequest implements Comparable<OnDemandRequest> {
|
||||
return priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(OnDemandRequest o) {
|
||||
int thisPriority = priority.toInteger();
|
||||
int otherPriority = o.priority.toInteger();
|
||||
|
||||
if (thisPriority < otherPriority) {
|
||||
return 1;
|
||||
} else if (thisPriority == otherPriority) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,6 +45,24 @@ public final class OnDemandResponse {
|
||||
this.chunkData = chunkData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk data.
|
||||
*
|
||||
* @return The chunk data.
|
||||
*/
|
||||
public ChannelBuffer getChunkData() {
|
||||
return chunkData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk id.
|
||||
*
|
||||
* @return The chunk id.
|
||||
*/
|
||||
public int getChunkId() {
|
||||
return chunkId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file descriptor.
|
||||
*
|
||||
@@ -63,22 +81,4 @@ public final class OnDemandResponse {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk id.
|
||||
*
|
||||
* @return The chunk id.
|
||||
*/
|
||||
public int getChunkId() {
|
||||
return chunkId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk data.
|
||||
*
|
||||
* @return The chunk data.
|
||||
*/
|
||||
public ChannelBuffer getChunkData() {
|
||||
return chunkData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,15 +61,6 @@ public final class PacketMetaData {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of packet.
|
||||
*
|
||||
* @return The type of packet.
|
||||
*/
|
||||
public PacketType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of this packet.
|
||||
*
|
||||
@@ -83,4 +74,13 @@ public final class PacketMetaData {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of packet.
|
||||
*
|
||||
* @return The type of packet.
|
||||
*/
|
||||
public PacketType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,48 +45,6 @@ public abstract class Release {
|
||||
this.incomingPacketMetaData = incomingPacketMetaData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release number.
|
||||
*
|
||||
* @return The release number.
|
||||
*/
|
||||
public final int getReleaseNumber() {
|
||||
return releaseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link EventDecoder} for the specified opcode.
|
||||
*
|
||||
* @param opcode The opcode, between 0 and 255 inclusive.
|
||||
* @param decoder The {@link EventDecoder}.
|
||||
*/
|
||||
public final <E extends Event> void register(int opcode, EventDecoder<E> decoder) {
|
||||
if (opcode < 0 || opcode >= decoders.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
decoders[opcode] = decoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link EventEncoder} for the specified event type.
|
||||
*
|
||||
* @param type The event type.
|
||||
* @param encoder The {@link EventEncoder}.
|
||||
*/
|
||||
public final <E extends Event> void register(Class<E> type, EventEncoder<E> encoder) {
|
||||
encoders.put(type, encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets meta data for the specified incoming packet.
|
||||
*
|
||||
* @param opcode The opcode of the incoming packet.
|
||||
* @return The {@link PacketMetaData} object.
|
||||
*/
|
||||
public final PacketMetaData getIncomingPacketMetaData(int opcode) {
|
||||
return incomingPacketMetaData.getMetaData(opcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link EventDecoder} for the specified opcode.
|
||||
*
|
||||
@@ -111,4 +69,46 @@ public abstract class Release {
|
||||
return (EventEncoder<E>) encoders.get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets meta data for the specified incoming packet.
|
||||
*
|
||||
* @param opcode The opcode of the incoming packet.
|
||||
* @return The {@link PacketMetaData} object.
|
||||
*/
|
||||
public final PacketMetaData getIncomingPacketMetaData(int opcode) {
|
||||
return incomingPacketMetaData.getMetaData(opcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release number.
|
||||
*
|
||||
* @return The release number.
|
||||
*/
|
||||
public final int getReleaseNumber() {
|
||||
return releaseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link EventEncoder} for the specified event type.
|
||||
*
|
||||
* @param type The event type.
|
||||
* @param encoder The {@link EventEncoder}.
|
||||
*/
|
||||
public final <E extends Event> void register(Class<E> type, EventEncoder<E> encoder) {
|
||||
encoders.put(type, encoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link EventDecoder} for the specified opcode.
|
||||
*
|
||||
* @param opcode The opcode, between 0 and 255 inclusive.
|
||||
* @param decoder The {@link EventDecoder}.
|
||||
*/
|
||||
public final <E extends Event> void register(int opcode, EventDecoder<E> decoder) {
|
||||
if (opcode < 0 || opcode >= decoders.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
decoders[opcode] = decoder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.apollo.net.release.EventDecoder;
|
||||
*/
|
||||
public final class FirstObjectActionEventDecoder extends EventDecoder<FirstObjectActionEvent> {
|
||||
|
||||
@Override
|
||||
public FirstObjectActionEvent decode(GamePacket packet) {
|
||||
GamePacketReader reader = new GamePacketReader(packet);
|
||||
int x = (int) reader.getUnsigned(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD);
|
||||
|
||||
@@ -2,15 +2,15 @@ package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.event.impl.PlayerSynchronizationEvent;
|
||||
import org.apollo.game.model.Animation;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.Direction;
|
||||
import org.apollo.game.model.EquipmentConstants;
|
||||
import org.apollo.game.model.Gender;
|
||||
import org.apollo.game.model.Graphic;
|
||||
import org.apollo.game.model.Inventory;
|
||||
import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.def.EquipmentDefinition;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.EquipmentConstants;
|
||||
import org.apollo.game.sync.block.AnimationBlock;
|
||||
import org.apollo.game.sync.block.AppearanceBlock;
|
||||
import org.apollo.game.sync.block.ChatBlock;
|
||||
@@ -86,8 +86,7 @@ public final class PlayerSynchronizationEventEncoder extends EventEncoder<Player
|
||||
* @param event The event.
|
||||
* @param builder The builder.
|
||||
*/
|
||||
private void putAddCharacterUpdate(AddPlayerSegment seg, PlayerSynchronizationEvent event,
|
||||
GamePacketBuilder builder) {
|
||||
private void putAddCharacterUpdate(AddPlayerSegment seg, PlayerSynchronizationEvent event, GamePacketBuilder builder) {
|
||||
boolean updateRequired = seg.getBlockSet().size() > 0;
|
||||
Position player = event.getPosition();
|
||||
Position other = seg.getPosition();
|
||||
|
||||
@@ -26,8 +26,7 @@ public final class UpdateItemsEventEncoder extends EventEncoder<UpdateItemsEvent
|
||||
builder.put(DataType.SHORT, event.getInterfaceId());
|
||||
builder.put(DataType.SHORT, items.length);
|
||||
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
Item item = items[i];
|
||||
for (Item item : items) {
|
||||
int id = item == null ? -1 : item.getId();
|
||||
int amount = item == null ? 0 : item.getAmount();
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@ package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.event.impl.PlayerSynchronizationEvent;
|
||||
import org.apollo.game.model.Animation;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.Direction;
|
||||
import org.apollo.game.model.EquipmentConstants;
|
||||
import org.apollo.game.model.Gender;
|
||||
import org.apollo.game.model.Graphic;
|
||||
import org.apollo.game.model.Inventory;
|
||||
import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.def.EquipmentDefinition;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.EquipmentConstants;
|
||||
import org.apollo.game.sync.block.AnimationBlock;
|
||||
import org.apollo.game.sync.block.AppearanceBlock;
|
||||
import org.apollo.game.sync.block.ChatBlock;
|
||||
@@ -86,8 +86,7 @@ public final class PlayerSynchronizationEventEncoder extends EventEncoder<Player
|
||||
* @param event The event.
|
||||
* @param builder The builder.
|
||||
*/
|
||||
private void putAddCharacterUpdate(AddPlayerSegment seg, PlayerSynchronizationEvent event,
|
||||
GamePacketBuilder builder) {
|
||||
private void putAddCharacterUpdate(AddPlayerSegment seg, PlayerSynchronizationEvent event, GamePacketBuilder builder) {
|
||||
boolean updateRequired = seg.getBlockSet().size() > 0;
|
||||
Position player = event.getPosition();
|
||||
Position other = seg.getPosition();
|
||||
|
||||
@@ -26,8 +26,7 @@ public final class UpdateItemsEventEncoder extends EventEncoder<UpdateItemsEvent
|
||||
builder.put(DataType.SHORT, event.getInterfaceId());
|
||||
builder.put(DataType.SHORT, items.length);
|
||||
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
Item item = items[i];
|
||||
for (Item item : items) {
|
||||
int id = item == null ? -1 : item.getId();
|
||||
int amount = item == null ? 0 : item.getAmount();
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import org.apollo.ServerContext;
|
||||
import org.apollo.game.GameConstants;
|
||||
import org.apollo.game.GameService;
|
||||
import org.apollo.game.event.Event;
|
||||
import org.apollo.game.event.handler.chain.EventHandlerChainGroup;
|
||||
import org.apollo.game.event.handler.chain.EventHandlerChain;
|
||||
import org.apollo.game.event.handler.chain.EventHandlerChainGroup;
|
||||
import org.apollo.game.event.impl.LogoutEvent;
|
||||
import org.apollo.game.model.Player;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
@@ -58,13 +58,8 @@ public final class GameSession extends Session {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(Object message) throws Exception {
|
||||
Event event = (Event) message;
|
||||
if (eventQueue.size() >= GameConstants.EVENTS_PER_PULSE) {
|
||||
logger.warning("Too many events in queue for game session, dropping...");
|
||||
} else {
|
||||
eventQueue.add(event);
|
||||
}
|
||||
public void destroy() throws Exception {
|
||||
context.getService(GameService.class).unregisterPlayer(player);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,8 +122,13 @@ public final class GameSession extends Session {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
context.getService(GameService.class).unregisterPlayer(player);
|
||||
public void messageReceived(Object message) throws Exception {
|
||||
Event event = (Event) message;
|
||||
if (eventQueue.size() >= GameConstants.EVENTS_PER_PULSE) {
|
||||
logger.warning("Too many events in queue for game session, dropping...");
|
||||
} else {
|
||||
eventQueue.add(event);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,10 +52,8 @@ public final class LoginSession extends Session {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(Object message) throws Exception {
|
||||
if (message.getClass() == LoginRequest.class) {
|
||||
handleLoginRequest((LoginRequest) message);
|
||||
}
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,8 +133,10 @@ public final class LoginSession extends Session {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
public void messageReceived(Object message) throws Exception {
|
||||
if (message.getClass() == LoginRequest.class) {
|
||||
handleLoginRequest((LoginRequest) message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ public abstract class Session {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys this session.
|
||||
*
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
public abstract void destroy() throws Exception;
|
||||
|
||||
/**
|
||||
* Gets the channel.
|
||||
*
|
||||
@@ -41,11 +48,4 @@ public abstract class Session {
|
||||
*/
|
||||
public abstract void messageReceived(Object message) throws Exception;
|
||||
|
||||
/**
|
||||
* Destroys this session.
|
||||
*
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
public abstract void destroy() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@ public final class UpdateSession extends Session {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(Object message) throws Exception {
|
||||
UpdateDispatcher dispatcher = context.getService(UpdateService.class).getDispatcher();
|
||||
@@ -45,9 +50,4 @@ public final class UpdateSession extends Session {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,15 +31,6 @@ public final class IsaacRandomPair {
|
||||
this.decodingRandom = decodingRandom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random number generator used for encoding.
|
||||
*
|
||||
* @return The random number generator used for encoding.
|
||||
*/
|
||||
public IsaacRandom getEncodingRandom() {
|
||||
return encodingRandom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random number generator used for decoding.
|
||||
*
|
||||
@@ -49,4 +40,13 @@ public final class IsaacRandomPair {
|
||||
return decodingRandom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random number generator used for encoding.
|
||||
*
|
||||
* @return The random number generator used for encoding.
|
||||
*/
|
||||
public IsaacRandom getEncodingRandom() {
|
||||
return encodingRandom;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,21 +44,12 @@ public final class PlayerCredentials {
|
||||
*/
|
||||
public PlayerCredentials(String username, String password, int usernameHash, int uid) {
|
||||
this.username = username;
|
||||
this.encodedUsername = NameUtil.encodeBase37(username);
|
||||
encodedUsername = NameUtil.encodeBase37(username);
|
||||
this.password = password;
|
||||
this.usernameHash = usernameHash;
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's username.
|
||||
*
|
||||
* @return The player's username.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's username encoded as a long.
|
||||
*
|
||||
@@ -77,15 +68,6 @@ public final class PlayerCredentials {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username hash.
|
||||
*
|
||||
* @return The username hash.
|
||||
*/
|
||||
public int getUsernameHash() {
|
||||
return usernameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the computer's uid.
|
||||
*
|
||||
@@ -95,4 +77,22 @@ public final class PlayerCredentials {
|
||||
return uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's username.
|
||||
*
|
||||
* @return The player's username.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username hash.
|
||||
*
|
||||
* @return The username hash.
|
||||
*/
|
||||
public int getUsernameHash() {
|
||||
return usernameHash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,15 @@ public final class ChannelRequest<T> implements Comparable<ChannelRequest<T>> {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public int compareTo(ChannelRequest<T> o) {
|
||||
if (request instanceof Comparable<?> && o.request instanceof Comparable<?>) {
|
||||
return ((Comparable<T>) request).compareTo(o.request);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the channel.
|
||||
*
|
||||
@@ -49,13 +58,4 @@ public final class ChannelRequest<T> implements Comparable<ChannelRequest<T>> {
|
||||
return request;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public int compareTo(ChannelRequest<T> o) {
|
||||
if (request instanceof Comparable<?> && o.request instanceof Comparable<?>) {
|
||||
return ((Comparable<T>) request).compareTo(o.request);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,59 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
|
||||
WWW_DIRECTORY)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error page.
|
||||
*
|
||||
* @param status The HTTP status.
|
||||
* @param description The error description.
|
||||
* @return The error page as a buffer.
|
||||
*/
|
||||
private ChannelBuffer createErrorPage(HttpResponseStatus status, String description) {
|
||||
String title = status.getCode() + " " + status.getReasonPhrase();
|
||||
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
|
||||
bldr.append("<!DOCTYPE html><html><head><title>");
|
||||
bldr.append(title);
|
||||
bldr.append("</title></head><body><h1>");
|
||||
bldr.append(title);
|
||||
bldr.append("</h1><p>");
|
||||
bldr.append(description);
|
||||
bldr.append("</p><hr /><address>");
|
||||
bldr.append(SERVER_IDENTIFIER);
|
||||
bldr.append(" Server</address></body></html>");
|
||||
|
||||
return ChannelBuffers.copiedBuffer(bldr.toString(), Charset.defaultCharset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MIME type of a file by its name.
|
||||
*
|
||||
* @param name The file name.
|
||||
* @return The MIME type.
|
||||
*/
|
||||
private String getMimeType(String name) {
|
||||
if (name.endsWith("/")) {
|
||||
name = name.concat("index.html");
|
||||
}
|
||||
if (name.endsWith(".htm") || name.endsWith(".html")) {
|
||||
return "text/html";
|
||||
} else if (name.endsWith(".css")) {
|
||||
return "text/css";
|
||||
} else if (name.endsWith(".js")) {
|
||||
return "text/javascript";
|
||||
} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
|
||||
return "image/jpeg";
|
||||
} else if (name.endsWith(".gif")) {
|
||||
return "image/gif";
|
||||
} else if (name.endsWith(".png")) {
|
||||
return "image/png";
|
||||
} else if (name.endsWith(".txt")) {
|
||||
return "text/plain";
|
||||
}
|
||||
return "application/octect-stream";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ChannelRequest<HttpRequest> nextRequest(UpdateDispatcher dispatcher) throws InterruptedException {
|
||||
return dispatcher.nextHttpRequest();
|
||||
@@ -92,57 +145,4 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
|
||||
channel.write(resp).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MIME type of a file by its name.
|
||||
*
|
||||
* @param name The file name.
|
||||
* @return The MIME type.
|
||||
*/
|
||||
private String getMimeType(String name) {
|
||||
if (name.endsWith("/")) {
|
||||
name = name.concat("index.html");
|
||||
}
|
||||
if (name.endsWith(".htm") || name.endsWith(".html")) {
|
||||
return "text/html";
|
||||
} else if (name.endsWith(".css")) {
|
||||
return "text/css";
|
||||
} else if (name.endsWith(".js")) {
|
||||
return "text/javascript";
|
||||
} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
|
||||
return "image/jpeg";
|
||||
} else if (name.endsWith(".gif")) {
|
||||
return "image/gif";
|
||||
} else if (name.endsWith(".png")) {
|
||||
return "image/png";
|
||||
} else if (name.endsWith(".txt")) {
|
||||
return "text/plain";
|
||||
}
|
||||
return "application/octect-stream";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an error page.
|
||||
*
|
||||
* @param status The HTTP status.
|
||||
* @param description The error description.
|
||||
* @return The error page as a buffer.
|
||||
*/
|
||||
private ChannelBuffer createErrorPage(HttpResponseStatus status, String description) {
|
||||
String title = status.getCode() + " " + status.getReasonPhrase();
|
||||
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
|
||||
bldr.append("<!DOCTYPE html><html><head><title>");
|
||||
bldr.append(title);
|
||||
bldr.append("</title></head><body><h1>");
|
||||
bldr.append(title);
|
||||
bldr.append("</h1><p>");
|
||||
bldr.append(description);
|
||||
bldr.append("</p><hr /><address>");
|
||||
bldr.append(SERVER_IDENTIFIER);
|
||||
bldr.append(" Server</address></body></html>");
|
||||
|
||||
return ChannelBuffers.copiedBuffer(bldr.toString(), Charset.defaultCharset());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,13 +40,13 @@ public abstract class RequestWorker<T, P> implements Runnable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops this worker. The worker's thread may need to be interrupted.
|
||||
* Gets the next request.
|
||||
*
|
||||
* @param dispatcher The dispatcher.
|
||||
* @return The next request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
public final void stop() {
|
||||
synchronized (this) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
protected abstract ChannelRequest<T> nextRequest(UpdateDispatcher dispatcher) throws InterruptedException;
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
@@ -75,15 +75,6 @@ public abstract class RequestWorker<T, P> implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next request.
|
||||
*
|
||||
* @param dispatcher The dispatcher.
|
||||
* @return The next request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
protected abstract ChannelRequest<T> nextRequest(UpdateDispatcher dispatcher) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Services a request.
|
||||
*
|
||||
@@ -94,4 +85,13 @@ public abstract class RequestWorker<T, P> implements Runnable {
|
||||
*/
|
||||
protected abstract void service(P provider, Channel channel, T request) throws IOException;
|
||||
|
||||
/**
|
||||
* Stops this worker. The worker's thread may need to be interrupted.
|
||||
*/
|
||||
public final void stop() {
|
||||
synchronized (this) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,46 +37,16 @@ public final class UpdateDispatcher {
|
||||
private final BlockingQueue<ChannelRequest<HttpRequest>> httpQueue = new LinkedBlockingQueue<ChannelRequest<HttpRequest>>();
|
||||
|
||||
/**
|
||||
* Gets the next 'on-demand' request from the queue, blocking if none are available.
|
||||
*
|
||||
* @return The 'on-demand' request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
ChannelRequest<OnDemandRequest> nextOnDemandRequest() throws InterruptedException {
|
||||
return onDemandQueue.take();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next JAGGRAB request from the queue, blocking if none are available.
|
||||
*
|
||||
* @return The JAGGRAB request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
ChannelRequest<JagGrabRequest> nextJagGrabRequest() throws InterruptedException {
|
||||
return jagGrabQueue.take();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next HTTP request from the queue, blocking if none are available.
|
||||
*
|
||||
* @return The HTTP request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
ChannelRequest<HttpRequest> nextHttpRequest() throws InterruptedException {
|
||||
return httpQueue.take();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an 'on-demand' request.
|
||||
* Dispatches a HTTP request.
|
||||
*
|
||||
* @param channel The channel.
|
||||
* @param request The request.
|
||||
*/
|
||||
public void dispatch(Channel channel, OnDemandRequest request) {
|
||||
if (onDemandQueue.size() >= MAXIMUM_QUEUE_SIZE) {
|
||||
public void dispatch(Channel channel, HttpRequest request) {
|
||||
if (httpQueue.size() >= MAXIMUM_QUEUE_SIZE) {
|
||||
channel.close();
|
||||
}
|
||||
onDemandQueue.add(new ChannelRequest<OnDemandRequest>(channel, request));
|
||||
httpQueue.add(new ChannelRequest<HttpRequest>(channel, request));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,16 +63,46 @@ public final class UpdateDispatcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a HTTP request.
|
||||
* Dispatches an 'on-demand' request.
|
||||
*
|
||||
* @param channel The channel.
|
||||
* @param request The request.
|
||||
*/
|
||||
public void dispatch(Channel channel, HttpRequest request) {
|
||||
if (httpQueue.size() >= MAXIMUM_QUEUE_SIZE) {
|
||||
public void dispatch(Channel channel, OnDemandRequest request) {
|
||||
if (onDemandQueue.size() >= MAXIMUM_QUEUE_SIZE) {
|
||||
channel.close();
|
||||
}
|
||||
httpQueue.add(new ChannelRequest<HttpRequest>(channel, request));
|
||||
onDemandQueue.add(new ChannelRequest<OnDemandRequest>(channel, request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next HTTP request from the queue, blocking if none are available.
|
||||
*
|
||||
* @return The HTTP request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
ChannelRequest<HttpRequest> nextHttpRequest() throws InterruptedException {
|
||||
return httpQueue.take();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next JAGGRAB request from the queue, blocking if none are available.
|
||||
*
|
||||
* @return The JAGGRAB request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
ChannelRequest<JagGrabRequest> nextJagGrabRequest() throws InterruptedException {
|
||||
return jagGrabQueue.take();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next 'on-demand' request from the queue, blocking if none are available.
|
||||
*
|
||||
* @return The 'on-demand' request.
|
||||
* @throws InterruptedException If the thread is interrupted.
|
||||
*/
|
||||
ChannelRequest<OnDemandRequest> nextOnDemandRequest() throws InterruptedException {
|
||||
return onDemandQueue.take();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class ByteBufferUtil {
|
||||
* @return The tri byte.
|
||||
*/
|
||||
public static int readUnsignedTriByte(ByteBuffer buffer) {
|
||||
return ((buffer.get() & 0xFF) << 16) | ((buffer.get() & 0xFF) << 8) | (buffer.get() & 0xFF);
|
||||
return (buffer.get() & 0xFF) << 16 | (buffer.get() & 0xFF) << 8 | buffer.get() & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,7 @@ public final class ChannelBufferUtil {
|
||||
public static String readString(ChannelBuffer buffer) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int character;
|
||||
while (buffer.readable() && ((character = buffer.readUnsignedByte()) != NetworkConstants.STRING_TERMINATOR)) {
|
||||
while (buffer.readable() && (character = buffer.readUnsignedByte()) != NetworkConstants.STRING_TERMINATOR) {
|
||||
builder.append((char) character);
|
||||
}
|
||||
return builder.toString();
|
||||
|
||||
@@ -13,115 +13,6 @@ import org.apollo.game.model.Character;
|
||||
*/
|
||||
public final class CharacterRepository<T extends Character> implements Iterable<T> {
|
||||
|
||||
/**
|
||||
* The array of characters in this repository.
|
||||
*/
|
||||
private final Character[] characters;
|
||||
|
||||
/**
|
||||
* The current size of this repository.
|
||||
*/
|
||||
private int size = 0;
|
||||
|
||||
/**
|
||||
* The position of the next free index.
|
||||
*/
|
||||
private int pointer = 0;
|
||||
|
||||
/**
|
||||
* Creates a new character repository with the specified capacity.
|
||||
*
|
||||
* @param capacity The maximum number of characters that can be present in the repository.
|
||||
*/
|
||||
public CharacterRepository(int capacity) {
|
||||
this.characters = new Character[capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of this repository.
|
||||
*
|
||||
* @return The number of characters in this repository.
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the capacity of this repository.
|
||||
*
|
||||
* @return The maximum size of this repository.
|
||||
*/
|
||||
public int capacity() {
|
||||
return characters.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a character to the repository.
|
||||
*
|
||||
* @param character The character to add.
|
||||
* @return {@code true} if the character was added, {@code false} if the size has reached the capacity of this
|
||||
* repository.
|
||||
*/
|
||||
public boolean add(T character) {
|
||||
if (size == characters.length) {
|
||||
return false;
|
||||
}
|
||||
int index = -1;
|
||||
for (int i = pointer; i < characters.length; i++) {
|
||||
if (characters[i] == null) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == -1) {
|
||||
for (int i = 0; i < pointer; i++) {
|
||||
if (characters[i] == null) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index == -1) {
|
||||
return false; // shouldn't happen, but just in case
|
||||
}
|
||||
characters[index] = character;
|
||||
character.setIndex(index + 1);
|
||||
if (index == (characters.length - 1)) {
|
||||
pointer = 0;
|
||||
} else {
|
||||
pointer = index;
|
||||
}
|
||||
size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a character from the repository.
|
||||
*
|
||||
* @param character The character to remove.
|
||||
* @return {@code true} if the character was removed, {@code false} if it was not (e.g. if it was never added or has
|
||||
* been removed already).
|
||||
*/
|
||||
public boolean remove(T character) {
|
||||
int index = character.getIndex() - 1;
|
||||
if (index < 0 || index >= characters.length) {
|
||||
return false;
|
||||
}
|
||||
if (characters[index] == character) {
|
||||
characters[index] = null;
|
||||
character.setIndex(-1);
|
||||
size--;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return new CharacterRepositoryIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link Iterator} implementation for the {@link CharacterRepository} class.
|
||||
*
|
||||
@@ -181,4 +72,113 @@ public final class CharacterRepository<T extends Character> implements Iterable<
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The array of characters in this repository.
|
||||
*/
|
||||
private final Character[] characters;
|
||||
|
||||
/**
|
||||
* The current size of this repository.
|
||||
*/
|
||||
private int size = 0;
|
||||
|
||||
/**
|
||||
* The position of the next free index.
|
||||
*/
|
||||
private int pointer = 0;
|
||||
|
||||
/**
|
||||
* Creates a new character repository with the specified capacity.
|
||||
*
|
||||
* @param capacity The maximum number of characters that can be present in the repository.
|
||||
*/
|
||||
public CharacterRepository(int capacity) {
|
||||
this.characters = new Character[capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a character to the repository.
|
||||
*
|
||||
* @param character The character to add.
|
||||
* @return {@code true} if the character was added, {@code false} if the size has reached the capacity of this
|
||||
* repository.
|
||||
*/
|
||||
public boolean add(T character) {
|
||||
if (size == characters.length) {
|
||||
return false;
|
||||
}
|
||||
int index = -1;
|
||||
for (int i = pointer; i < characters.length; i++) {
|
||||
if (characters[i] == null) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index == -1) {
|
||||
for (int i = 0; i < pointer; i++) {
|
||||
if (characters[i] == null) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index == -1) {
|
||||
return false; // shouldn't happen, but just in case
|
||||
}
|
||||
characters[index] = character;
|
||||
character.setIndex(index + 1);
|
||||
if (index == characters.length - 1) {
|
||||
pointer = 0;
|
||||
} else {
|
||||
pointer = index;
|
||||
}
|
||||
size++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the capacity of this repository.
|
||||
*
|
||||
* @return The maximum size of this repository.
|
||||
*/
|
||||
public int capacity() {
|
||||
return characters.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return new CharacterRepositoryIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a character from the repository.
|
||||
*
|
||||
* @param character The character to remove.
|
||||
* @return {@code true} if the character was removed, {@code false} if it was not (e.g. if it was never added or has
|
||||
* been removed already).
|
||||
*/
|
||||
public boolean remove(T character) {
|
||||
int index = character.getIndex() - 1;
|
||||
if (index < 0 || index >= characters.length) {
|
||||
return false;
|
||||
}
|
||||
if (characters[index] == character) {
|
||||
characters[index] = null;
|
||||
character.setIndex(-1);
|
||||
size--;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of this repository.
|
||||
*
|
||||
* @return The number of characters in this repository.
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user