mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-08 00:39:10 +00:00
Resolve merge conflict.
This commit is contained in:
@@ -13,12 +13,12 @@ class OpenDoorAction < DistancedAction
|
||||
|
||||
def executeAction
|
||||
mob.turn_to(@door.position)
|
||||
DoorUtil::toggle(@door, mob)
|
||||
DoorUtil::toggle(@door)
|
||||
stop
|
||||
end
|
||||
|
||||
def equals(other)
|
||||
return (get_class == other.get_class && @door_object == other.door_object)
|
||||
return (get_class == other.get_class && @door == other.door)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -28,6 +28,7 @@ on :message, :first_object_action do |player, message|
|
||||
if DoorUtil::is_door?(message.id)
|
||||
puts "Player: #{player.position}, door: #{message.position}"
|
||||
door = DoorUtil::get_door_object(message.position, message.id)
|
||||
player.start_action(OpenDoorAction.new(player, door)) unless door.nil?
|
||||
DoorUtil::toggle(door) unless door.nil?
|
||||
# player.start_action(OpenDoorAction.new(player, door)) unless door.nil?
|
||||
end
|
||||
end
|
||||
@@ -46,7 +46,7 @@ module DoorUtil
|
||||
end
|
||||
|
||||
# Toggles the given door.
|
||||
def self.toggle(door, player)
|
||||
def self.toggle(door)
|
||||
position = door.position
|
||||
region = $world.region_repository.from_position(position)
|
||||
region.remove_entity(door)
|
||||
@@ -59,7 +59,7 @@ module DoorUtil
|
||||
else
|
||||
toggled_position = translate_door_position(door)
|
||||
toggled_orientation = translate_door_orientation(door)
|
||||
toggled_door = DynamicGameObject.createPublic(door.id, toggled_position, door.type, toggled_orientation)
|
||||
toggled_door = DynamicGameObject.createPublic($world, door.id, toggled_position, door.type, toggled_orientation)
|
||||
|
||||
toggled_region = $world.region_repository.from_position(toggled_position)
|
||||
toggled_region.add_entity(toggled_door)
|
||||
|
||||
@@ -1,78 +1,77 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>org.apollo</artifactId>
|
||||
<version>1.0</version>
|
||||
<groupId>apollo</groupId>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>org.apollo</artifactId>
|
||||
<version>1.0</version>
|
||||
<groupId>apollo</groupId>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<testSourceDirectory>test</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<build>
|
||||
<sourceDirectory>src</sourceDirectory>
|
||||
<testSourceDirectory>test</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<configuration>
|
||||
<mainClass>org.apollo.Server</mainClass>
|
||||
<arguments>
|
||||
<argument>-server</argument>
|
||||
<argument>-Xmx750M</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<configuration>
|
||||
<mainClass>org.apollo.Server</mainClass>
|
||||
<arguments>
|
||||
<argument>-server</argument>
|
||||
<argument>-Xmx750M</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.9</version>
|
||||
</dependency>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.9</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jruby</groupId>
|
||||
<artifactId>jruby-complete</artifactId>
|
||||
<version>1.7.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jruby</groupId>
|
||||
<artifactId>jruby-complete</artifactId>
|
||||
<version>1.7.19</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.0.26.Final</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.0.27.Final</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.lambdaworks</groupId>
|
||||
<artifactId>scrypt</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lambdaworks</groupId>
|
||||
<artifactId>scrypt</artifactId>
|
||||
<version>1.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
<version>0.9.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
<version>0.9.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -31,58 +31,49 @@ public final class IsaacRandom {
|
||||
private static final int GOLDEN_RATIO = 0x9e3779b9;
|
||||
|
||||
/**
|
||||
* The log of the size of the result and memory arrays.
|
||||
* The log of the size of the result and state arrays.
|
||||
*/
|
||||
private static final int LOG_SIZE = 8;
|
||||
private static final int LOG_SIZE = Long.BYTES;
|
||||
|
||||
/**
|
||||
* The size of the result and memory arrays.
|
||||
* The size of the result and states arrays.
|
||||
*/
|
||||
private static final int SIZE = 1 << LOG_SIZE;
|
||||
|
||||
/**
|
||||
* A mask for pseudorandom lookup.
|
||||
* A mask for pseudo-random lookup.
|
||||
*/
|
||||
private static int MASK = SIZE - 1 << 2;
|
||||
|
||||
/**
|
||||
* The accumulator.
|
||||
* The results given to the user.
|
||||
*/
|
||||
private int a;
|
||||
|
||||
/**
|
||||
* The last result.
|
||||
*/
|
||||
private int b;
|
||||
|
||||
/**
|
||||
* The counter.
|
||||
*/
|
||||
private int c;
|
||||
|
||||
/**
|
||||
* The count through the results in the results array.
|
||||
*/
|
||||
private int count;
|
||||
private final int[] results = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The internal state.
|
||||
*/
|
||||
private int[] mem;
|
||||
private final int[] state = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The results given to the user.
|
||||
* The count through the results in the results array.
|
||||
*/
|
||||
private int[] rsl;
|
||||
private int count = SIZE;
|
||||
|
||||
/**
|
||||
* Creates the random number generator without an initial seed.
|
||||
* The accumulator.
|
||||
*/
|
||||
public IsaacRandom() {
|
||||
mem = new int[SIZE];
|
||||
rsl = new int[SIZE];
|
||||
init(false);
|
||||
}
|
||||
private int accumulator;
|
||||
|
||||
/**
|
||||
* The last result.
|
||||
*/
|
||||
private int last;
|
||||
|
||||
/**
|
||||
* The counter.
|
||||
*/
|
||||
private int counter;
|
||||
|
||||
/**
|
||||
* Creates the random number generator with the specified seed.
|
||||
@@ -90,20 +81,75 @@ public final class IsaacRandom {
|
||||
* @param seed The seed.
|
||||
*/
|
||||
public IsaacRandom(int[] seed) {
|
||||
mem = new int[SIZE];
|
||||
rsl = new int[SIZE];
|
||||
for (int i = 0; i < seed.length; ++i) {
|
||||
rsl[i] = seed[i];
|
||||
}
|
||||
init(true);
|
||||
int length = Math.min(seed.length, results.length);
|
||||
System.arraycopy(seed, 0, results, 0, length);
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises this random number generator.
|
||||
*
|
||||
* @param hasSeed Set to {@code true} if a seed was passed to the constructor.
|
||||
* Generates 256 results.
|
||||
*/
|
||||
private void init(boolean hasSeed) {
|
||||
private void isaac() {
|
||||
int i, j, x, y;
|
||||
|
||||
last += ++counter;
|
||||
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 13;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 6;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 2;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 16;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
}
|
||||
|
||||
for (j = 0; j < SIZE / 2;) {
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 13;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 6;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 2;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 16;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this random number generator.
|
||||
*/
|
||||
private void init() {
|
||||
int i;
|
||||
int a, b, c, d, e, f, g, h;
|
||||
a = b = c = d = e = f = g = h = GOLDEN_RATIO;
|
||||
@@ -136,16 +182,15 @@ public final class IsaacRandom {
|
||||
}
|
||||
|
||||
for (i = 0; i < SIZE; i += 8) { /* fill in mem[] with messy stuff */
|
||||
if (hasSeed) {
|
||||
a += rsl[i];
|
||||
b += rsl[i + 1];
|
||||
c += rsl[i + 2];
|
||||
d += rsl[i + 3];
|
||||
e += rsl[i + 4];
|
||||
f += rsl[i + 5];
|
||||
g += rsl[i + 6];
|
||||
h += rsl[i + 7];
|
||||
}
|
||||
a += results[i];
|
||||
b += results[i + 1];
|
||||
c += results[i + 2];
|
||||
d += results[i + 3];
|
||||
e += results[i + 4];
|
||||
f += results[i + 5];
|
||||
g += results[i + 6];
|
||||
h += results[i + 7];
|
||||
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
@@ -170,123 +215,60 @@ public final class IsaacRandom {
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
mem[i] = a;
|
||||
mem[i + 1] = b;
|
||||
mem[i + 2] = c;
|
||||
mem[i + 3] = d;
|
||||
mem[i + 4] = e;
|
||||
mem[i + 5] = f;
|
||||
mem[i + 6] = g;
|
||||
mem[i + 7] = h;
|
||||
state[i] = a;
|
||||
state[i + 1] = b;
|
||||
state[i + 2] = c;
|
||||
state[i + 3] = d;
|
||||
state[i + 4] = e;
|
||||
state[i + 5] = f;
|
||||
state[i + 6] = g;
|
||||
state[i + 7] = h;
|
||||
}
|
||||
|
||||
if (hasSeed) { /* second pass makes all of seed affect all of mem */
|
||||
for (i = 0; i < SIZE; i += 8) {
|
||||
a += mem[i];
|
||||
b += mem[i + 1];
|
||||
c += mem[i + 2];
|
||||
d += mem[i + 3];
|
||||
e += mem[i + 4];
|
||||
f += mem[i + 5];
|
||||
g += mem[i + 6];
|
||||
h += mem[i + 7];
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
mem[i] = a;
|
||||
mem[i + 1] = b;
|
||||
mem[i + 2] = c;
|
||||
mem[i + 3] = d;
|
||||
mem[i + 4] = e;
|
||||
mem[i + 5] = f;
|
||||
mem[i + 6] = g;
|
||||
mem[i + 7] = h;
|
||||
}
|
||||
for (i = 0; i < SIZE; i += 8) {
|
||||
a += state[i];
|
||||
b += state[i + 1];
|
||||
c += state[i + 2];
|
||||
d += state[i + 3];
|
||||
e += state[i + 4];
|
||||
f += state[i + 5];
|
||||
g += state[i + 6];
|
||||
h += state[i + 7];
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
state[i] = a;
|
||||
state[i + 1] = b;
|
||||
state[i + 2] = c;
|
||||
state[i + 3] = d;
|
||||
state[i + 4] = e;
|
||||
state[i + 5] = f;
|
||||
state[i + 6] = g;
|
||||
state[i + 7] = h;
|
||||
}
|
||||
|
||||
isaac();
|
||||
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 >> LOG_SIZE & 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 >> LOG_SIZE & 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 >> LOG_SIZE & 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 >> LOG_SIZE & 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 >> LOG_SIZE & 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 >> LOG_SIZE & 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 >> LOG_SIZE & 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 >> LOG_SIZE & MASK) >> 2] + x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,7 +281,7 @@ public final class IsaacRandom {
|
||||
isaac();
|
||||
count = SIZE - 1;
|
||||
}
|
||||
return rsl[count];
|
||||
return results[count];
|
||||
}
|
||||
|
||||
}
|
||||
+16
-13
@@ -10,6 +10,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -25,6 +26,8 @@ import org.apollo.net.release.r317.Release317;
|
||||
import org.apollo.util.plugin.PluginContext;
|
||||
import org.apollo.util.plugin.PluginManager;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
|
||||
/**
|
||||
* The core class of the Apollo server.
|
||||
*
|
||||
@@ -43,8 +46,9 @@ public final class Server {
|
||||
* @param args The command-line arguments passed to the application.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
|
||||
try {
|
||||
long start = System.currentTimeMillis();
|
||||
Server server = new Server();
|
||||
server.init(args.length == 1 ? args[0] : Release317.class.getName());
|
||||
|
||||
@@ -53,10 +57,11 @@ public final class Server {
|
||||
SocketAddress jaggrab = new InetSocketAddress(NetworkConstants.JAGGRAB_PORT);
|
||||
|
||||
server.bind(service, http, jaggrab);
|
||||
logger.fine("Starting apollo took " + (System.currentTimeMillis() - start) + " ms.");
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.SEVERE, "Error whilst starting server.", t);
|
||||
}
|
||||
|
||||
logger.fine("Starting apollo took " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,10 +86,8 @@ public final class Server {
|
||||
|
||||
/**
|
||||
* Creates the Apollo server.
|
||||
*
|
||||
* @throws Exception If an error occurs whilst creating services.
|
||||
*/
|
||||
public Server() throws Exception {
|
||||
public Server() {
|
||||
logger.info("Starting Apollo...");
|
||||
}
|
||||
|
||||
@@ -98,14 +101,14 @@ public final class Server {
|
||||
public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) {
|
||||
try {
|
||||
logger.fine("Binding service listener to address: " + serviceAddress + "...");
|
||||
serviceBootstrap.bind(serviceAddress).syncUninterruptibly();
|
||||
serviceBootstrap.bind(serviceAddress).sync();
|
||||
|
||||
logger.fine("Binding HTTP listener to address: " + httpAddress + "...");
|
||||
httpBootstrap.bind(httpAddress).syncUninterruptibly();
|
||||
httpBootstrap.bind(httpAddress).sync();
|
||||
|
||||
logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
|
||||
jagGrabBootstrap.bind(jagGrabAddress).syncUninterruptibly();
|
||||
} catch (Exception e) {
|
||||
jagGrabBootstrap.bind(jagGrabAddress).sync();
|
||||
} catch (InterruptedException e) {
|
||||
logger.log(Level.SEVERE, "Binding to a port failed: ensure apollo isn't already running.", e);
|
||||
System.exit(1);
|
||||
}
|
||||
@@ -122,8 +125,9 @@ public final class Server {
|
||||
public void init(String releaseClassName) throws Exception {
|
||||
Class<?> clazz = Class.forName(releaseClassName);
|
||||
Release release = (Release) clazz.newInstance();
|
||||
int releaseNo = release.getReleaseNumber();
|
||||
|
||||
logger.info("Initialized release #" + release.getReleaseNumber() + ".");
|
||||
logger.info("Initialized release #" + releaseNo + ".");
|
||||
|
||||
serviceBootstrap.group(loopGroup);
|
||||
httpBootstrap.group(loopGroup);
|
||||
@@ -131,7 +135,8 @@ public final class Server {
|
||||
|
||||
World world = new World();
|
||||
ServiceManager serviceManager = new ServiceManager(world);
|
||||
ServerContext context = new ServerContext(release, serviceManager);
|
||||
IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs", Integer.toString(releaseNo)), true);
|
||||
ServerContext context = new ServerContext(release, serviceManager, fs);
|
||||
ApolloHandler handler = new ApolloHandler(context);
|
||||
|
||||
ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler);
|
||||
@@ -149,8 +154,6 @@ public final class Server {
|
||||
PluginManager manager = new PluginManager(world, new PluginContext(context));
|
||||
serviceManager.startAll();
|
||||
|
||||
int releaseNo = release.getReleaseNumber();
|
||||
IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs", Integer.toString(releaseNo)), true);
|
||||
world.init(releaseNo, fs, manager);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.apollo;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apollo.fs.IndexedFileSystem;
|
||||
import org.apollo.net.release.Release;
|
||||
|
||||
/**
|
||||
@@ -21,16 +24,23 @@ public final class ServerContext {
|
||||
*/
|
||||
private final ServiceManager serviceManager;
|
||||
|
||||
/**
|
||||
* The IndexedFileSystem.
|
||||
*/
|
||||
private final IndexedFileSystem fileSystem;
|
||||
|
||||
/**
|
||||
* Creates a new server context.
|
||||
*
|
||||
* @param release The current release.
|
||||
* @param serviceManager The service manager.
|
||||
* @param fileSystem The indexed file system.
|
||||
*/
|
||||
ServerContext(Release release, ServiceManager serviceManager) {
|
||||
this.release = release;
|
||||
this.serviceManager = serviceManager;
|
||||
protected ServerContext(Release release, ServiceManager serviceManager, IndexedFileSystem fileSystem) {
|
||||
this.release = Objects.requireNonNull(release);
|
||||
this.serviceManager = Objects.requireNonNull(serviceManager);
|
||||
this.serviceManager.setContext(this);
|
||||
this.fileSystem = Objects.requireNonNull(fileSystem);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,6 +52,15 @@ public final class ServerContext {
|
||||
return release;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IndexeFileSystem
|
||||
*
|
||||
* @return The IndexedFileSystem.
|
||||
*/
|
||||
public IndexedFileSystem getFileSystem() {
|
||||
return fileSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a service. This method is shorthand for {@code getServiceManager().getService(...)}.
|
||||
*
|
||||
|
||||
@@ -27,7 +27,7 @@ public final class ServiceManager {
|
||||
/**
|
||||
* The service map.
|
||||
*/
|
||||
private Map<Class<? extends Service>, Service> services = new HashMap<>();
|
||||
private final Map<Class<? extends Service>, Service> services = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Creates and initializes the {@link ServiceManager}.
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
@@ -24,6 +25,11 @@ public final class IndexedFileSystem implements Closeable {
|
||||
*/
|
||||
private ByteBuffer crcTable;
|
||||
|
||||
/**
|
||||
* The {@link #crcTable} represented as an {@code int} array.
|
||||
*/
|
||||
private int[] crcs;
|
||||
|
||||
/**
|
||||
* The data file.
|
||||
*/
|
||||
@@ -32,7 +38,7 @@ public final class IndexedFileSystem implements Closeable {
|
||||
/**
|
||||
* The index files.
|
||||
*/
|
||||
private RandomAccessFile[] indices = new RandomAccessFile[256];
|
||||
private final RandomAccessFile[] indices = new RandomAccessFile[256];
|
||||
|
||||
/**
|
||||
* Read only flag.
|
||||
@@ -143,6 +149,23 @@ public final class IndexedFileSystem implements Closeable {
|
||||
throw new IllegalStateException("Cannot get CRC table from a writable file system.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CRC table as an {@code int} array.
|
||||
*
|
||||
* @return The CRC table as an {@code int} array.
|
||||
* @throws IOException If there is an error accessing files to create the table.
|
||||
*/
|
||||
public int[] getCrcs() throws IOException {
|
||||
if (crcs != null) {
|
||||
return crcs;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = getCrcTable();
|
||||
crcs = new int[(buffer.remaining() / Integer.BYTES) - 1];
|
||||
Arrays.setAll(crcs, crc -> buffer.getInt());
|
||||
return crcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a file.
|
||||
*
|
||||
|
||||
@@ -133,7 +133,7 @@ public final class GameObjectDecoder {
|
||||
if (block) {
|
||||
for (int dx = 0; dx < definition.getWidth(); dx++) {
|
||||
for (int dy = 0; dy < definition.getLength(); dy++) {
|
||||
int localX = (x % Region.SIZE) + dx, localY = (y % Region.SIZE) + dy;
|
||||
int localX = x % Region.SIZE + dx, localY = y % Region.SIZE + dy;
|
||||
|
||||
if (localX > 7 || localY > 7) {
|
||||
int nextLocalX = localX > 7 ? x + localX - 7 : x + localX;
|
||||
@@ -141,11 +141,13 @@ public final class GameObjectDecoder {
|
||||
Position nextPosition = new Position(nextLocalX, nextLocalY);
|
||||
Region next = regions.fromPosition(nextPosition);
|
||||
|
||||
int nextX = (nextPosition.getX() % Region.SIZE) + dx, nextY = (nextPosition.getY() % Region.SIZE) + dy;
|
||||
if (nextX > 7)
|
||||
int nextX = nextPosition.getX() % Region.SIZE + dx, nextY = nextPosition.getY() % Region.SIZE + dy;
|
||||
if (nextX > 7) {
|
||||
nextX -= 7;
|
||||
if (nextY > 7)
|
||||
}
|
||||
if (nextY > 7) {
|
||||
nextY -= 7;
|
||||
}
|
||||
|
||||
next.getMatrix(height).block(nextX, nextY);
|
||||
continue;
|
||||
@@ -181,7 +183,7 @@ public final class GameObjectDecoder {
|
||||
}
|
||||
|
||||
if (block) {
|
||||
int localX = (x % Region.SIZE), localY = (y % Region.SIZE);
|
||||
int localX = x % Region.SIZE, localY = y % Region.SIZE;
|
||||
current.block(localX, localY);
|
||||
}
|
||||
}
|
||||
@@ -209,7 +211,7 @@ public final class GameObjectDecoder {
|
||||
|
||||
int localY = packed & 0x3F;
|
||||
int localX = packed >> 6 & 0x3F;
|
||||
int height = (packed >> 12) & 0x3;
|
||||
int height = packed >> 12 & 0x3;
|
||||
|
||||
int attributes = buffer.get() & 0xFF;
|
||||
int type = attributes >> 2;
|
||||
|
||||
@@ -121,17 +121,13 @@ public final class NpcDefinitionDecoder {
|
||||
} else if (opcode == 102 || opcode == 103) {
|
||||
buffer.getShort();
|
||||
} else if (opcode == 106) {
|
||||
@SuppressWarnings("unused")
|
||||
int morphVariableBitsIndex = wrap(buffer.getShort());
|
||||
@SuppressWarnings("unused")
|
||||
int morphismCount = wrap(buffer.getShort());
|
||||
wrap(buffer.getShort());
|
||||
wrap(buffer.getShort());
|
||||
|
||||
int count = buffer.get() & 0xFF;
|
||||
int[] morphisms = new int[count + 1];
|
||||
Arrays.setAll(morphisms, index -> wrap(buffer.getShort()));
|
||||
} else if (opcode == 107) {
|
||||
@SuppressWarnings("unused")
|
||||
boolean clickable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,11 @@ import org.apollo.io.MessageHandlerChainSetParser;
|
||||
import org.apollo.login.LoginService;
|
||||
import org.apollo.net.session.GameSession;
|
||||
import org.apollo.util.MobRepository;
|
||||
import org.apollo.util.ThreadUtil;
|
||||
import org.apollo.util.xml.XmlNode;
|
||||
import org.apollo.util.xml.XmlParser;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
* The {@link GameService} class schedules and manages the execution of the {@link GamePulseHandler} class.
|
||||
*
|
||||
@@ -52,7 +51,7 @@ public final class GameService extends Service {
|
||||
/**
|
||||
* The scheduled executor service.
|
||||
*/
|
||||
private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat("GameService").build());
|
||||
private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(ThreadUtil.build("GameService"));
|
||||
|
||||
/**
|
||||
* The {@link ClientSynchronizer}.
|
||||
|
||||
@@ -30,7 +30,7 @@ public final class MessageHandlerChainSet {
|
||||
public <M extends Message> boolean notify(Player player, M message) {
|
||||
@SuppressWarnings("unchecked")
|
||||
MessageHandlerChain<M> chain = (MessageHandlerChain<M>) chains.get(message.getClass());
|
||||
return (chain == null) || chain.notify(player, message);
|
||||
return chain == null || chain.notify(player, message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -98,8 +98,7 @@ public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> {
|
||||
return;
|
||||
}
|
||||
|
||||
if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null
|
||||
&& EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) {
|
||||
if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null && EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) {
|
||||
equipment.set(EquipmentConstants.SHIELD, inventory.reset(inventorySlot));
|
||||
inventory.add(equipment.reset(EquipmentConstants.WEAPON));
|
||||
return;
|
||||
|
||||
@@ -27,8 +27,7 @@ public final class ItemOnObjectVerificationHandler extends MessageHandler<ItemOn
|
||||
|
||||
@Override
|
||||
public void handle(Player player, ItemOnObjectMessage message) {
|
||||
if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID
|
||||
&& message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) {
|
||||
if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID && message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) {
|
||||
message.terminate();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public final class ForwardPrivateChatMessage extends Message {
|
||||
*/
|
||||
public ForwardPrivateChatMessage(String username, PrivilegeLevel level, byte[] message) {
|
||||
this.username = username;
|
||||
this.privilege = level;
|
||||
privilege = level;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ import org.apollo.game.model.area.RegionCoordinates;
|
||||
public final class GroupedRegionUpdateMessage extends Message {
|
||||
|
||||
/**
|
||||
* The Position of the Player.
|
||||
* The last known region Position of the Player.
|
||||
*/
|
||||
private final Position player;
|
||||
private final Position lastKnownRegion;
|
||||
|
||||
/**
|
||||
* The Position of the Region being updated.
|
||||
@@ -31,13 +31,13 @@ public final class GroupedRegionUpdateMessage extends Message {
|
||||
/**
|
||||
* Creates the GroupedRegionUpdateMessage.
|
||||
*
|
||||
* @param player The {@link Position} of the Player.
|
||||
* @param lastKnownRegion The last known region {@link Position} of the Player.
|
||||
* @param coordinates The {@link RegionCoordinates} of the Region being updated.
|
||||
* @param messages The {@link List} of {@link RegionUpdateMessage}s.
|
||||
*/
|
||||
public GroupedRegionUpdateMessage(Position player, RegionCoordinates coordinates, List<RegionUpdateMessage> messages) {
|
||||
this.player = player;
|
||||
this.region = new Position(coordinates.getAbsoluteX(), coordinates.getAbsoluteY());
|
||||
public GroupedRegionUpdateMessage(Position lastKnownRegion, RegionCoordinates coordinates, List<RegionUpdateMessage> messages) {
|
||||
this.lastKnownRegion = lastKnownRegion;
|
||||
region = new Position(coordinates.getAbsoluteX(), coordinates.getAbsoluteY());
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ public final class GroupedRegionUpdateMessage extends Message {
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getPlayerPosition() {
|
||||
return player;
|
||||
public Position getLastKnownRegion() {
|
||||
return lastKnownRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,7 +33,7 @@ public final class ItemOnObjectMessage extends InventoryItemMessage {
|
||||
public ItemOnObjectMessage(int interfaceId, int itemId, int itemSlot, int objectId, int x, int y) {
|
||||
super(0, interfaceId, itemId, itemSlot);
|
||||
this.objectId = objectId;
|
||||
this.position = new Position(x, y);
|
||||
position = new Position(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,8 +33,8 @@ public final class RemoveObjectMessage extends RegionUpdateMessage {
|
||||
*/
|
||||
public RemoveObjectMessage(GameObject object, int positionOffset) {
|
||||
this.positionOffset = positionOffset;
|
||||
this.type = object.getType();
|
||||
this.orientation = object.getOrientation();
|
||||
type = object.getType();
|
||||
orientation = object.getOrientation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,10 +37,10 @@ public final class SendObjectMessage extends RegionUpdateMessage {
|
||||
* @param positionOffset The offset of the object's position from the region's central position.
|
||||
*/
|
||||
public SendObjectMessage(GameObject object, int positionOffset) {
|
||||
this.id = object.getId();
|
||||
id = object.getId();
|
||||
this.positionOffset = positionOffset;
|
||||
this.type = object.getType();
|
||||
this.orientation = object.getOrientation();
|
||||
type = object.getType();
|
||||
orientation = object.getOrientation();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,7 +44,7 @@ public final class SetPlayerActionMessage extends Message {
|
||||
public SetPlayerActionMessage(String text, int slot, boolean primaryInteraction) {
|
||||
this.text = text;
|
||||
this.slot = slot;
|
||||
this.primaryAction = primaryInteraction;
|
||||
primaryAction = primaryInteraction;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ public final class WalkMessage extends Message {
|
||||
/**
|
||||
* The running flag.
|
||||
*/
|
||||
private boolean run;
|
||||
private final boolean run;
|
||||
|
||||
/**
|
||||
* The steps.
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class Item {
|
||||
Preconditions.checkArgument(amount >= 0, "Amount cannot be negative.");
|
||||
this.id = id;
|
||||
this.amount = amount;
|
||||
this.definition = ItemDefinition.lookup(id);
|
||||
definition = ItemDefinition.lookup(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -192,7 +192,7 @@ public final class Position {
|
||||
* @return The y coordinate.
|
||||
*/
|
||||
public int getY() {
|
||||
return (packed >> 15) & 0x7FFF;
|
||||
return packed >> 15 & 0x7FFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -80,7 +80,7 @@ public final class World {
|
||||
/**
|
||||
* The command dispatcher.
|
||||
*/
|
||||
private CommandDispatcher commandDispatcher = new CommandDispatcher();
|
||||
private final CommandDispatcher commandDispatcher = new CommandDispatcher();
|
||||
|
||||
/**
|
||||
* The EventListenerChainSet for this World.
|
||||
@@ -208,7 +208,7 @@ public final class World {
|
||||
* @throws Exception If any definitions could not be loaded or there was a failure when loading plugins.
|
||||
*/
|
||||
public void init(int release, IndexedFileSystem fs, PluginManager manager) throws Exception {
|
||||
this.releaseNumber = release;
|
||||
releaseNumber = release;
|
||||
|
||||
ItemDefinitionDecoder itemDecoder = new ItemDefinitionDecoder(fs);
|
||||
ItemDefinition[] items = itemDecoder.decode();
|
||||
@@ -385,12 +385,12 @@ public final class World {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entities to regions in the {@link RegionRepository}.
|
||||
* Adds entities to regions in the {@link RegionRepository}. By default, we do not notify listeners.
|
||||
*
|
||||
* @param entities The entities.
|
||||
*/
|
||||
private void placeEntities(Entity... entities) {
|
||||
Arrays.stream(entities).forEach(entity -> regions.fromPosition(entity.getPosition()).addEntity(entity));
|
||||
Arrays.stream(entities).forEach(entity -> regions.fromPosition(entity.getPosition()).addEntity(entity, false));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,280 +31,302 @@ import com.google.common.collect.ImmutableSet;
|
||||
*/
|
||||
public final class Region {
|
||||
|
||||
/**
|
||||
* A {@link RegionListener} for {@link UpdateOperation}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
private static final class UpdateRegionListener implements RegionListener {
|
||||
/**
|
||||
* A {@link RegionListener} for {@link UpdateOperation}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
private static final class UpdateRegionListener implements RegionListener {
|
||||
|
||||
@Override
|
||||
public void execute(Region region, Entity entity, EntityUpdateType update) {
|
||||
EntityType type = entity.getEntityType();
|
||||
if (type != EntityType.PLAYER && type != EntityType.NPC && (type != EntityType.STATIC_OBJECT || update == EntityUpdateType.REMOVE)) {
|
||||
region.record(entity, update);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void execute(Region region, Entity entity, EntityUpdateType update) {
|
||||
EntityType type = entity.getEntityType();
|
||||
if (type != EntityType.PLAYER && type != EntityType.NPC) {
|
||||
region.record(entity, update);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The width and length of a Region, in tiles.
|
||||
*/
|
||||
public static final int SIZE = 8;
|
||||
/**
|
||||
* The width and length of a Region, in tiles.
|
||||
*/
|
||||
public static final int SIZE = 8;
|
||||
|
||||
static final long start = System.currentTimeMillis();
|
||||
static final long start = System.currentTimeMillis();
|
||||
|
||||
/**
|
||||
* The default size of newly-created sets, to reduce memory usage.
|
||||
*/
|
||||
private static final int DEFAULT_SET_SIZE = 2;
|
||||
/**
|
||||
* The default size of newly-created sets, to reduce memory usage.
|
||||
*/
|
||||
private static final int DEFAULT_SET_SIZE = 2;
|
||||
|
||||
/**
|
||||
* The RegionCoordinates of this Region.
|
||||
*/
|
||||
private final RegionCoordinates coordinates;
|
||||
/**
|
||||
* The RegionCoordinates of this Region.
|
||||
*/
|
||||
private final RegionCoordinates coordinates;
|
||||
|
||||
/**
|
||||
* The Map of Positions to Entities in that Position.
|
||||
*/
|
||||
private final Map<Position, Set<Entity>> entities = new HashMap<>();
|
||||
/**
|
||||
* The Map of Positions to Entities in that Position.
|
||||
*/
|
||||
private final Map<Position, Set<Entity>> entities = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A List of RegionListeners registered to this Region.
|
||||
*/
|
||||
private final List<RegionListener> listeners = new ArrayList<>();
|
||||
/**
|
||||
* A List of RegionListeners registered to this Region.
|
||||
*/
|
||||
private final List<RegionListener> listeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The CollisionMatrix.
|
||||
*/
|
||||
private final CollisionMatrix[] matrices = CollisionMatrix.createMatrices(Position.HEIGHT_LEVELS, SIZE, SIZE);
|
||||
/**
|
||||
* The CollisionMatrix.
|
||||
*/
|
||||
private final CollisionMatrix[] matrices = CollisionMatrix.createMatrices(Position.HEIGHT_LEVELS, SIZE, SIZE);
|
||||
|
||||
/**
|
||||
* The Set containing RegionUpdateMessages which can be sent to add every non-Mob Entity in this Region.
|
||||
*/
|
||||
private final List<List<RegionUpdateMessage>> snapshots = new ArrayList<>(Position.HEIGHT_LEVELS);
|
||||
/**
|
||||
* The Set containing RegionUpdateMessages which can be sent to add every non-Mob Entity in this Region.
|
||||
*/
|
||||
private final List<Map<Entity, RegionUpdateMessage>> snapshots = new ArrayList<>(Position.HEIGHT_LEVELS);
|
||||
|
||||
/**
|
||||
* The Set containing UpdateOperations.
|
||||
*/
|
||||
private final List<List<RegionUpdateMessage>> updates = new ArrayList<>(Position.HEIGHT_LEVELS);
|
||||
/**
|
||||
* The Set containing UpdateOperations.
|
||||
*/
|
||||
private final List<List<RegionUpdateMessage>> updates = new ArrayList<>(Position.HEIGHT_LEVELS);
|
||||
|
||||
/**
|
||||
* Creates a new Region.
|
||||
*
|
||||
* @param x The x coordinate of the Region.
|
||||
* @param y The y coordinate of the Region.
|
||||
*/
|
||||
public Region(int x, int y) {
|
||||
this(new RegionCoordinates(x, y));
|
||||
}
|
||||
/**
|
||||
* Creates a new Region.
|
||||
*
|
||||
* @param x The x coordinate of the Region.
|
||||
* @param y The y coordinate of the Region.
|
||||
*/
|
||||
public Region(int x, int y) {
|
||||
this(new RegionCoordinates(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Region with the specified {@link RegionCoordinates}.
|
||||
*
|
||||
* @param coordinates The coordinates.
|
||||
*/
|
||||
public Region(RegionCoordinates coordinates) {
|
||||
this.coordinates = coordinates;
|
||||
listeners.add(new UpdateRegionListener());
|
||||
/**
|
||||
* Creates a new Region with the specified {@link RegionCoordinates}.
|
||||
*
|
||||
* @param coordinates The coordinates.
|
||||
*/
|
||||
public Region(RegionCoordinates coordinates) {
|
||||
this.coordinates = coordinates;
|
||||
listeners.add(new UpdateRegionListener());
|
||||
|
||||
for (int height = 0; height < Position.HEIGHT_LEVELS; height++) {
|
||||
snapshots.add(new ArrayList<>());
|
||||
updates.add(new ArrayList<>(DEFAULT_SET_SIZE));
|
||||
}
|
||||
}
|
||||
for (int height = 0; height < Position.HEIGHT_LEVELS; height++) {
|
||||
snapshots.add(new HashMap<>());
|
||||
updates.add(new ArrayList<>(DEFAULT_SET_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Entity} from to Region. Note that this does not spawn the Entity, or do any other action other than
|
||||
* register it to this Region.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @throws IllegalArgumentException If the Entity does not belong in this Region.
|
||||
*/
|
||||
public void addEntity(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
checkPosition(position);
|
||||
/**
|
||||
* Adds a {@link Entity} to the Region. Note that this does not spawn the Entity, or do any other action other than
|
||||
* register it to this Region.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @param notify A flag indicating whether the {@link RegionListener}s for this Region should be notified.
|
||||
* @throws IllegalArgumentException If the Entity does not belong in this Region.
|
||||
*/
|
||||
public void addEntity(Entity entity, boolean notify) {
|
||||
Position position = entity.getPosition();
|
||||
checkPosition(position);
|
||||
|
||||
Set<Entity> local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
|
||||
local.add(entity);
|
||||
Set<Entity> local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
|
||||
local.add(entity);
|
||||
|
||||
if ((System.currentTimeMillis() - start) / 1000 > 10 && (entity instanceof GameObject)) {
|
||||
System.out.println("Adding entity " + entity + " to " + entity.getPosition());
|
||||
}
|
||||
if ((System.currentTimeMillis() - start) / 1000 > 10 && (entity instanceof GameObject)) {
|
||||
System.out.println("Adding entity " + entity + " to " + entity.getPosition());
|
||||
}
|
||||
|
||||
notifyListeners(entity, EntityUpdateType.ADD);
|
||||
}
|
||||
if (notify) {
|
||||
notifyListeners(entity, EntityUpdateType.ADD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this Region contains the specified Entity.
|
||||
* <p>
|
||||
* This method operates in constant time.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @return {@code true} if this Region contains the Entity, otherwise {@code false}.
|
||||
*/
|
||||
public boolean contains(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
Set<Entity> local = entities.get(position);
|
||||
/**
|
||||
* Adds a {@link Entity} to the Region. Note that this does not spawn the Entity, or do any other action other than
|
||||
* register it to this Region.
|
||||
* <p/>
|
||||
* By default, this method notifies RegionListeners for this region of the addition.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @throws IllegalArgumentException If the Entity does not belong in this Region.
|
||||
*/
|
||||
public void addEntity(Entity entity) {
|
||||
addEntity(entity, true);
|
||||
}
|
||||
|
||||
return local != null && local.contains(entity);
|
||||
}
|
||||
/**
|
||||
* Checks if this Region contains the specified Entity.
|
||||
* <p/>
|
||||
* This method operates in constant time.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @return {@code true} if this Region contains the Entity, otherwise {@code false}.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets this Region's {@link RegionCoordinates}.
|
||||
*
|
||||
* @return The Region coordinates.
|
||||
*/
|
||||
public RegionCoordinates getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
public boolean contains(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
Set<Entity> local = entities.get(position);
|
||||
|
||||
/**
|
||||
* Gets a shallow copy of the {@link Set} of {@link Entity} objects at the specified {@link Position}. The returned
|
||||
* type will be immutable.
|
||||
*
|
||||
* @param position The position containing the entities.
|
||||
* @return The list.
|
||||
*/
|
||||
public Set<Entity> getEntities(Position position) {
|
||||
Set<Entity> set = entities.get(position);
|
||||
return (set == null) ? ImmutableSet.of() : ImmutableSet.copyOf(set);
|
||||
}
|
||||
return local != null && local.contains(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a shallow copy of the {@link Set} of {@link Entity}s with the specified {@link EntityType}(s). The returned
|
||||
* type will be immutable. Type will be inferred from the call, so ensure that the Entity type and the reference
|
||||
* correspond, or this method will fail at runtime.
|
||||
*
|
||||
* @param position The {@link Position} containing the entities.
|
||||
* @param types The {@link EntityType}s.
|
||||
* @return The set of entities.
|
||||
*/
|
||||
public <T extends Entity> Set<T> getEntities(Position position, EntityType... types) {
|
||||
Set<Entity> local = entities.get(position);
|
||||
if (local == null) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
/**
|
||||
* Gets this Region's {@link RegionCoordinates}.
|
||||
*
|
||||
* @return The Region coordinates.
|
||||
*/
|
||||
public RegionCoordinates getCoordinates() {
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
Set<EntityType> set = new HashSet<>(Arrays.asList(types));
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<T> filtered = (Set<T>) local.stream().filter(entity -> set.contains(entity.getEntityType())).collect(Collectors.toSet());
|
||||
return ImmutableSet.copyOf(filtered);
|
||||
}
|
||||
/**
|
||||
* Gets a shallow copy of the {@link Set} of {@link Entity} objects at the specified {@link Position}. The returned
|
||||
* type will be immutable.
|
||||
*
|
||||
* @param position The position containing the entities.
|
||||
* @return The list.
|
||||
*/
|
||||
public Set<Entity> getEntities(Position position) {
|
||||
Set<Entity> set = entities.get(position);
|
||||
return (set == null) ? ImmutableSet.of() : ImmutableSet.copyOf(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link CollisionMatrix} at the specified height level.
|
||||
*
|
||||
* @param height The height level.
|
||||
* @return The CollisionMatrix.
|
||||
*/
|
||||
public CollisionMatrix getMatrix(int height) {
|
||||
Preconditions.checkElementIndex(height, matrices.length, "Matrix height level must be [0, " + matrices.length + ").");
|
||||
return matrices[height];
|
||||
}
|
||||
/**
|
||||
* Gets a shallow copy of the {@link Set} of {@link Entity}s with the specified {@link EntityType}(s). The returned
|
||||
* type will be immutable. Type will be inferred from the call, so ensure that the Entity type and the reference
|
||||
* correspond, or this method will fail at runtime.
|
||||
*
|
||||
* @param position The {@link Position} containing the entities.
|
||||
* @param types The {@link EntityType}s.
|
||||
* @return The set of entities.
|
||||
*/
|
||||
public <T extends Entity> Set<T> getEntities(Position position, EntityType... types) {
|
||||
Set<Entity> local = entities.get(position);
|
||||
if (local == null) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Set} containing {@link RegionUpdateMessage}s that add every {@link Entity} in this Region.
|
||||
*
|
||||
* @param height The height level to get the Set of RegionUpdateMessages for.
|
||||
* @return The Set of RegionUpdateMessages.
|
||||
*/
|
||||
public List<RegionUpdateMessage> getSnapshot(int height) {
|
||||
List<RegionUpdateMessage> copy = new ArrayList<>(snapshots.get(height));
|
||||
Collections.sort(copy);
|
||||
return ImmutableList.copyOf(copy);
|
||||
}
|
||||
Set<EntityType> set = new HashSet<>(Arrays.asList(types));
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<T> filtered = (Set<T>) local.stream().filter(entity -> set.contains(entity.getEntityType())).collect(Collectors.toSet());
|
||||
return ImmutableSet.copyOf(filtered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the updates that have occurred in the last tick in this Region, as a {@link Set} of
|
||||
* {@link RegionUpdateMessage}s.
|
||||
*
|
||||
* @param height The height level to get the Set of RegionUpdateMessages for.
|
||||
* @return The Set of RegionUpdateMessages.
|
||||
*/
|
||||
public List<RegionUpdateMessage> getUpdates(int height) {
|
||||
List<RegionUpdateMessage> original = this.updates.get(height);
|
||||
List<RegionUpdateMessage> updates = new ArrayList<>(original);
|
||||
original.clear();
|
||||
/**
|
||||
* Gets the {@link CollisionMatrix} at the specified height level.
|
||||
*
|
||||
* @param height The height level.
|
||||
* @return The CollisionMatrix.
|
||||
*/
|
||||
public CollisionMatrix getMatrix(int height) {
|
||||
Preconditions.checkElementIndex(height, matrices.length, "Matrix height level must be [0, " + matrices.length + ").");
|
||||
return matrices[height];
|
||||
}
|
||||
|
||||
Collections.sort(updates);
|
||||
return ImmutableList.copyOf(updates);
|
||||
}
|
||||
/**
|
||||
* Gets a {@link Set} containing {@link RegionUpdateMessage}s that add every {@link Entity} in this Region.
|
||||
*
|
||||
* @param height The height level to get the Set of RegionUpdateMessages for.
|
||||
* @return The Set of RegionUpdateMessages.
|
||||
*/
|
||||
public List<RegionUpdateMessage> getSnapshot(int height) {
|
||||
List<RegionUpdateMessage> copy = new ArrayList<>(snapshots.get(height).values());
|
||||
Collections.sort(copy);
|
||||
return ImmutableList.copyOf(copy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the {@link RegionListener}s registered to this Region that an update has occurred.
|
||||
*
|
||||
* @param entity The {@link Entity} that was updated.
|
||||
* @param type The {@link EntityUpdateType} that occurred.
|
||||
*/
|
||||
public void notifyListeners(Entity entity, EntityUpdateType type) {
|
||||
listeners.forEach(listener -> listener.execute(this, entity, type));
|
||||
}
|
||||
/**
|
||||
* Gets the updates that have occurred in the last tick in this Region, as a {@link Set} of
|
||||
* {@link RegionUpdateMessage}s.
|
||||
*
|
||||
* @param height The height level to get the Set of RegionUpdateMessages for.
|
||||
* @return The Set of RegionUpdateMessages.
|
||||
*/
|
||||
public List<RegionUpdateMessage> getUpdates(int height) {
|
||||
List<RegionUpdateMessage> original = this.updates.get(height);
|
||||
List<RegionUpdateMessage> updates = new ArrayList<>(original);
|
||||
original.clear();
|
||||
|
||||
/**
|
||||
* Removes a {@link Entity} from this Region.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @throws IllegalArgumentException If the Entity does not belong in this Region, or if it was never added.
|
||||
*/
|
||||
public void removeEntity(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
checkPosition(position);
|
||||
Collections.sort(updates);
|
||||
return ImmutableList.copyOf(updates);
|
||||
}
|
||||
|
||||
Set<Entity> local = entities.get(position);
|
||||
/**
|
||||
* Notifies the {@link RegionListener}s registered to this Region that an update has occurred.
|
||||
*
|
||||
* @param entity The {@link Entity} that was updated.
|
||||
* @param type The {@link EntityUpdateType} that occurred.
|
||||
*/
|
||||
public void notifyListeners(Entity entity, EntityUpdateType type) {
|
||||
listeners.forEach(listener -> listener.execute(this, entity, type));
|
||||
}
|
||||
|
||||
if (local == null || !local.remove(entity)) {
|
||||
throw new IllegalArgumentException("Entity belongs in this Region (" + this + ") but does not exist.");
|
||||
}
|
||||
/**
|
||||
* Removes a {@link Entity} from this Region.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @throws IllegalArgumentException If the Entity does not belong in this Region, or if it was never added.
|
||||
*/
|
||||
public void removeEntity(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
checkPosition(position);
|
||||
|
||||
notifyListeners(entity, EntityUpdateType.REMOVE);
|
||||
}
|
||||
Set<Entity> local = entities.get(position);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("coordinates", coordinates).toString();
|
||||
}
|
||||
if (local == null || !local.remove(entity)) {
|
||||
throw new IllegalArgumentException("Entity belongs in this Region (" + this + ") but does not exist.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not an Entity of the specified {@link EntityType type} can traverse the tile at the specified
|
||||
* coordinate pair.
|
||||
*
|
||||
* @param position The {@link Position} of the tile.
|
||||
* @param entity The {@link EntityType}.
|
||||
* @param direction The {@link Direction} the Entity is approaching from.
|
||||
* @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not.
|
||||
*/
|
||||
public boolean traversable(Position position, EntityType entity, Direction direction) {
|
||||
CollisionMatrix matrix = matrices[position.getHeight()];
|
||||
int x = position.getX(), y = position.getY();
|
||||
notifyListeners(entity, EntityUpdateType.REMOVE);
|
||||
}
|
||||
|
||||
return !matrix.untraversable(x % SIZE, y % SIZE, entity, direction);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("coordinates", coordinates).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the specified {@link Position} is included in this Region.
|
||||
*
|
||||
* @param position The position.
|
||||
* @throws IllegalArgumentException If the specified position is not included in this Region.
|
||||
*/
|
||||
private void checkPosition(Position position) {
|
||||
Preconditions.checkArgument(coordinates.equals(RegionCoordinates.fromPosition(position)), "Position is not included in this Region.");
|
||||
}
|
||||
/**
|
||||
* Returns whether or not an Entity of the specified {@link EntityType type} can traverse the tile at the specified
|
||||
* coordinate pair.
|
||||
*
|
||||
* @param position The {@link Position} of the tile.
|
||||
* @param entity The {@link EntityType}.
|
||||
* @param direction The {@link Direction} the Entity is approaching from.
|
||||
* @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not.
|
||||
*/
|
||||
public boolean traversable(Position position, EntityType entity, Direction direction) {
|
||||
CollisionMatrix matrix = matrices[position.getHeight()];
|
||||
int x = position.getX(), y = position.getY();
|
||||
|
||||
/**
|
||||
* Records the specified {@link Entity} as being updated this pulse.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @param type The {@link EntityUpdateType}.
|
||||
* @throws UnsupportedOperationException If the specified Entity cannot be operated on in this manner.
|
||||
*/
|
||||
private void record(Entity entity, EntityUpdateType type) {
|
||||
RegionUpdateMessage message = entity.toUpdateOperation(this, type).toMessage();
|
||||
int height = entity.getPosition().getHeight();
|
||||
return !matrix.untraversable(x % SIZE, y % SIZE, entity, direction);
|
||||
}
|
||||
|
||||
updates.get(height).add(message);
|
||||
snapshots.get(height).add(message);
|
||||
}
|
||||
/**
|
||||
* Checks that the specified {@link Position} is included in this Region.
|
||||
*
|
||||
* @param position The position.
|
||||
* @throws IllegalArgumentException If the specified position is not included in this Region.
|
||||
*/
|
||||
private void checkPosition(Position position) {
|
||||
Preconditions.checkArgument(coordinates.equals(RegionCoordinates.fromPosition(position)), "Position is not included in this Region.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Records the specified {@link Entity} as being updated this pulse.
|
||||
*
|
||||
* @param entity The Entity.
|
||||
* @param type The {@link EntityUpdateType}.
|
||||
* @throws UnsupportedOperationException If the specified Entity cannot be operated on in this manner.
|
||||
*/
|
||||
private void record(Entity entity, EntityUpdateType type) {
|
||||
RegionUpdateMessage message = entity.toUpdateOperation(this, type).toMessage();
|
||||
int height = entity.getPosition().getHeight();
|
||||
|
||||
updates.get(height).add(message);
|
||||
snapshots.get(height).remove(entity);
|
||||
|
||||
if ((entity.getEntityType() == EntityType.STATIC_OBJECT && type == EntityUpdateType.REMOVE) ||
|
||||
(entity.getEntityType() != EntityType.STATIC_OBJECT && type == EntityUpdateType.ADD)) {
|
||||
snapshots.get(height).put(entity, message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public enum CollisionFlag {
|
||||
* @return The array of CollisionFlags.
|
||||
*/
|
||||
public static CollisionFlag[] forType(EntityType type) {
|
||||
return (type == EntityType.PROJECTILE) ? projectiles() : mobs();
|
||||
return type == EntityType.PROJECTILE ? projectiles() : mobs();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -95,7 +95,7 @@ public abstract class UpdateOperation<E extends Entity> {
|
||||
Preconditions.checkArgument(dx >= 0 && dx < Region.SIZE, position + " not in expected Region of " + region + ".");
|
||||
Preconditions.checkArgument(dy >= 0 && dy < Region.SIZE, position + " not in expected Region of " + region + ".");
|
||||
|
||||
return (dx << 4) | dy;
|
||||
return dx << 4 | dy;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public final class EquipmentDefinition {
|
||||
/**
|
||||
* The array of skill requirement levels.
|
||||
*/
|
||||
private int[] levels = { 1, 1, 1, 1, 1, 1, 1 };
|
||||
private final int[] levels = { 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
/**
|
||||
* The slot this equipment goes into.
|
||||
|
||||
@@ -114,7 +114,7 @@ public final class ItemDefinition {
|
||||
/**
|
||||
* The ground actions array.
|
||||
*/
|
||||
private String[] groundActions = new String[5];
|
||||
private final String[] groundActions = new String[5];
|
||||
|
||||
/**
|
||||
* The item's id.
|
||||
@@ -124,7 +124,7 @@ public final class ItemDefinition {
|
||||
/**
|
||||
* The inventory actions array.
|
||||
*/
|
||||
private String[] inventoryActions = new String[5];
|
||||
private final String[] inventoryActions = new String[5];
|
||||
|
||||
/**
|
||||
* A flag indicating if this item is members only.
|
||||
|
||||
@@ -80,7 +80,7 @@ public final class NpcDefinition {
|
||||
/**
|
||||
* An array of interaction options.
|
||||
*/
|
||||
private String[] interactions = new String[5];
|
||||
private final String[] interactions = new String[5];
|
||||
|
||||
/**
|
||||
* The name of the npc.
|
||||
|
||||
@@ -535,7 +535,7 @@ public abstract class Mob extends Entity {
|
||||
* @param position The position to face.
|
||||
*/
|
||||
public final void turnTo(Position position) {
|
||||
this.facingPosition = position;
|
||||
facingPosition = position;
|
||||
blockSet.add(SynchronizationBlock.createTurnToPositionBlock(position));
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ public final class Player extends Mob {
|
||||
/**
|
||||
* This player's credentials.
|
||||
*/
|
||||
private PlayerCredentials credentials;
|
||||
private final PlayerCredentials credentials;
|
||||
|
||||
/**
|
||||
* A flag which indicates there are npcs that couldn't be added.
|
||||
@@ -870,7 +870,7 @@ public final class Player extends Mob {
|
||||
* @param brightness The screen brightness.
|
||||
*/
|
||||
public void setScreenBrightness(ScreenBrightness brightness) {
|
||||
this.screenBrightness = brightness;
|
||||
screenBrightness = brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -223,7 +223,7 @@ public final class SkillSet {
|
||||
continue;
|
||||
}
|
||||
|
||||
current += (current < max ? 1 : -1);
|
||||
current += current < max ? 1 : -1;
|
||||
setSkill(id, new Skill(skills[id].getExperience(), current, max));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public final class AttributeMap {
|
||||
/**
|
||||
* The map of attribute names to attributes.
|
||||
*/
|
||||
private Map<String, Attribute<?>> attributes = new HashMap<>(DEFAULT_MAP_SIZE);
|
||||
private final Map<String, Attribute<?>> attributes = new HashMap<>(DEFAULT_MAP_SIZE);
|
||||
|
||||
/**
|
||||
* Gets the {@link Attribute} with the specified name.
|
||||
|
||||
@@ -30,13 +30,13 @@ public final class NumericalAttribute extends Attribute<Number> {
|
||||
|
||||
@Override
|
||||
public byte[] encode() {
|
||||
long encoded = (type == AttributeType.DOUBLE) ? Double.doubleToLongBits((double) value) : (long) value;
|
||||
long encoded = type == AttributeType.DOUBLE ? Double.doubleToLongBits((double) value) : (long) value;
|
||||
return Longs.toByteArray(encoded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (type == AttributeType.DOUBLE) ? Double.toString((double) value) : Long.toString((long) value);
|
||||
return type == AttributeType.DOUBLE ? Double.toString((double) value) : Long.toString((long) value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public final class DynamicGameObject extends GameObject {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
Player player = get();
|
||||
return (player == null) ? 0 : player.hashCode();
|
||||
return player == null ? 0 : player.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public abstract class GameObject extends Entity {
|
||||
*/
|
||||
public GameObject(World world, int id, Position position, int type, int orientation) {
|
||||
super(world, position);
|
||||
this.packed = id << 8 | (type & 0x3F) << 2 | orientation & 0x3;
|
||||
packed = id << 8 | (type & 0x3F) << 2 | orientation & 0x3;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,7 +81,7 @@ public abstract class GameObject extends Entity {
|
||||
* @return The type.
|
||||
*/
|
||||
public int getType() {
|
||||
return (packed >> 2) & 0x3F;
|
||||
return packed >> 2 & 0x3F;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -88,7 +88,7 @@ public final class SimplePathfindingAlgorithm extends PathfindingAlgorithm {
|
||||
}
|
||||
|
||||
Position last = new Position(x, y, height);
|
||||
if (!start.equals(last) && dy != 0 && traversable(last, boundaries, (dy > 0) ? Direction.SOUTH : Direction.NORTH)) {
|
||||
if (!start.equals(last) && dy != 0 && traversable(last, boundaries, dy > 0 ? Direction.SOUTH : Direction.NORTH)) {
|
||||
return addVertical(last, target, positions);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public final class SimplePathfindingAlgorithm extends PathfindingAlgorithm {
|
||||
}
|
||||
|
||||
Position last = new Position(x, y, height);
|
||||
if (!last.equals(target) && dx != 0 && traversable(last, boundaries, (dx > 0) ? Direction.WEST : Direction.EAST)) {
|
||||
if (!last.equals(target) && dx != 0 && traversable(last, boundaries, dx > 0 ? Direction.WEST : Direction.EAST)) {
|
||||
return addHorizontal(last, target, positions);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public final class EventListenerChainSet {
|
||||
public <E extends Event> boolean notify(E event) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EventListenerChain<E> chain = (EventListenerChain<E>) chains.get(event.getClass());
|
||||
return (chain == null) || chain.notify(event);
|
||||
return chain == null || chain.notify(event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,9 +6,6 @@ import org.apollo.game.model.event.Event;
|
||||
|
||||
/**
|
||||
* An {@link Event} created when a Mob's Position is being updated.
|
||||
* <p>
|
||||
* This Event intentionally ignores the result of execution - it should not be possible for a plugin to prevent this
|
||||
* Event from happening, only to listen for it.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
|
||||
@@ -51,7 +51,7 @@ public final class InterfaceSet {
|
||||
/**
|
||||
* A map of open interfaces.
|
||||
*/
|
||||
private Map<InterfaceType, Integer> interfaces = new HashMap<>();
|
||||
private final Map<InterfaceType, Integer> interfaces = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The current listener.
|
||||
@@ -150,7 +150,7 @@ public final class InterfaceSet {
|
||||
public void openDialogue(DialogueListener listener, int dialogueId) {
|
||||
closeAndNotify();
|
||||
|
||||
this.dialogueListener = Optional.ofNullable(listener);
|
||||
dialogueListener = Optional.ofNullable(listener);
|
||||
this.listener = Optional.ofNullable(listener);
|
||||
|
||||
interfaces.put(InterfaceType.DIALOGUE, dialogueId);
|
||||
@@ -175,7 +175,7 @@ public final class InterfaceSet {
|
||||
public void openDialogueOverlay(DialogueListener listener, int dialogueId) {
|
||||
closeAndNotify();
|
||||
|
||||
this.dialogueListener = Optional.ofNullable(listener);
|
||||
dialogueListener = Optional.ofNullable(listener);
|
||||
this.listener = Optional.ofNullable(listener);
|
||||
|
||||
interfaces.put(InterfaceType.DIALOGUE, dialogueId);
|
||||
|
||||
@@ -18,7 +18,8 @@ public interface DialogueListener extends InterfaceListener {
|
||||
* </p>
|
||||
*
|
||||
* @param button The button interface id.
|
||||
* @return {@code true} if the {@link MessageHandlerChain} should be broken, {@code false} if it should be continued.
|
||||
* @return {@code true} if the {@link MessageHandlerChain} should be broken, {@code false} if it should be
|
||||
* continued.
|
||||
*/
|
||||
public boolean buttonClicked(int button);
|
||||
|
||||
|
||||
@@ -540,7 +540,7 @@ public final class Inventory {
|
||||
int removed = Math.min(amount, itemAmount);
|
||||
int remainder = itemAmount - removed;
|
||||
|
||||
set(slot, (remainder > 0) ? new Item(item.getId(), remainder) : null);
|
||||
set(slot, remainder > 0 ? new Item(item.getId(), remainder) : null);
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ public final class NpcMovementTask extends ScheduledTask {
|
||||
int currentX = current.getX(), currentY = current.getY();
|
||||
|
||||
boolean negativeX = RANDOM.nextBoolean(), negativeY = RANDOM.nextBoolean();
|
||||
int x = RANDOM.nextInt(negativeX ? (currentX - min.getX()) : (max.getX() - currentX));
|
||||
int y = RANDOM.nextInt(negativeY ? (currentY - min.getY()) : (max.getY() - currentY));
|
||||
int x = RANDOM.nextInt(negativeX ? currentX - min.getX() : max.getX() - currentX);
|
||||
int y = RANDOM.nextInt(negativeY ? currentY - min.getY() : max.getY() - currentY);
|
||||
|
||||
int dx = negativeX ? -x : x;
|
||||
int dy = negativeY ? -y : y;
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Phaser;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import org.apollo.game.GameService;
|
||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
||||
@@ -22,8 +21,7 @@ import org.apollo.game.sync.task.PreNpcSynchronizationTask;
|
||||
import org.apollo.game.sync.task.PrePlayerSynchronizationTask;
|
||||
import org.apollo.game.sync.task.SynchronizationTask;
|
||||
import org.apollo.util.MobRepository;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import org.apollo.util.ThreadUtil;
|
||||
|
||||
/**
|
||||
* An implementation of {@link ClientSynchronizer} which runs in a thread pool. A {@link Phaser} is used to ensure that
|
||||
@@ -49,12 +47,10 @@ public final class ParallelClientSynchronizer extends ClientSynchronizer {
|
||||
|
||||
/**
|
||||
* Creates the parallel client synchronizer backed by a thread pool with a number of threads equal to the number of
|
||||
* processing cores available (this is found by the {@link Runtime#availableProcessors()} method.
|
||||
* processing cores available (this is found by the {@link ThreadUtil#AVAILABLE_PROCESSORS} method.
|
||||
*/
|
||||
public ParallelClientSynchronizer() {
|
||||
int processors = Runtime.getRuntime().availableProcessors();
|
||||
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("ClientSynchronizer").build();
|
||||
executor = Executors.newFixedThreadPool(processors, factory);
|
||||
executor = Executors.newFixedThreadPool(ThreadUtil.AVAILABLE_PROCESSORS, ThreadUtil.build("ClientSynchronizer"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -49,8 +49,7 @@ public final class NpcSynchronizationTask extends SynchronizationTask {
|
||||
|
||||
for (Iterator<Npc> it = localNpcs.iterator(); it.hasNext();) {
|
||||
Npc npc = it.next();
|
||||
if (!npc.isActive() || npc.isTeleporting()
|
||||
|| npc.getPosition().getLongestDelta(playerPosition) > player.getViewingDistance()) {
|
||||
if (!npc.isActive() || npc.isTeleporting() || npc.getPosition().getLongestDelta(playerPosition) > player.getViewingDistance()) {
|
||||
it.remove();
|
||||
segments.add(new RemoveMobSegment());
|
||||
} else {
|
||||
@@ -69,8 +68,7 @@ public final class NpcSynchronizationTask extends SynchronizationTask {
|
||||
}
|
||||
|
||||
Position npcPosition = npc.getPosition();
|
||||
if (npcPosition.isWithinDistance(playerPosition, player.getViewingDistance()) && !localNpcs.contains(npc)
|
||||
&& npcPosition.getHeight() == playerPosition.getHeight()) {
|
||||
if (npcPosition.isWithinDistance(playerPosition, player.getViewingDistance()) && !localNpcs.contains(npc) && npcPosition.getHeight() == playerPosition.getHeight()) {
|
||||
localNpcs.add(npc);
|
||||
added++;
|
||||
npc.turnTo(npc.getFacingPosition());
|
||||
|
||||
@@ -80,8 +80,7 @@ public final class PlayerSynchronizationTask extends SynchronizationTask {
|
||||
int added = 0;
|
||||
|
||||
MobRepository<Player> repository = player.getWorld().getPlayerRepository();
|
||||
for (Iterator<Player> it = repository.iterator(); it.hasNext();) {
|
||||
Player other = it.next();
|
||||
for (Player other : repository) {
|
||||
if (localPlayers.size() >= 255) {
|
||||
player.flagExcessivePlayers();
|
||||
break;
|
||||
|
||||
@@ -181,7 +181,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
player.send(new ClearRegionMessage(position, coordinates));
|
||||
}
|
||||
|
||||
Optional<GroupedRegionUpdateMessage> message = toUpdateMessage(local, position, coordinates, repository);
|
||||
Optional<GroupedRegionUpdateMessage> message = toUpdateMessage(local, player.getLastKnownRegion(), coordinates, repository);
|
||||
if (message.isPresent()) {
|
||||
messages.add(message.get());
|
||||
}
|
||||
@@ -208,7 +208,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
int deltaX = current.getLocalX(last);
|
||||
int deltaY = current.getLocalY(last);
|
||||
|
||||
return deltaX <= Position.MAX_DISTANCE || deltaX >= (VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1) || deltaY <= Position.MAX_DISTANCE || deltaY >= (VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1);
|
||||
return deltaX <= Position.MAX_DISTANCE || deltaX >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1 || deltaY <= Position.MAX_DISTANCE || deltaY >= VIEWPORT_WIDTH - Position.MAX_DISTANCE - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,12 +216,12 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
* {@link Optional#empty()} if no update message is required.
|
||||
*
|
||||
* @param mode The RegionUpdateMode for the Message.
|
||||
* @param position The {@link Position} of the Player.
|
||||
* @param lastKnownRegion The last known region {@link Position} of the Player.
|
||||
* @param coordinates The {@link RegionCoordinates} of the {@link Region}.
|
||||
* @param repository The {@link RegionRepository} containing the Regions.
|
||||
* @return The Optional containing the GroupedRegionUpdateMessage.
|
||||
*/
|
||||
private Optional<GroupedRegionUpdateMessage> toUpdateMessage(RegionUpdateMode mode, Position position, RegionCoordinates coordinates, RegionRepository repository) {
|
||||
private Optional<GroupedRegionUpdateMessage> toUpdateMessage(RegionUpdateMode mode, Position lastKnownRegion, RegionCoordinates coordinates, RegionRepository repository) {
|
||||
List<RegionUpdateMessage> messages;
|
||||
|
||||
/*
|
||||
@@ -237,7 +237,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
messages = updates.get(coordinates);
|
||||
if (messages == null) {
|
||||
synchronized (updates) {
|
||||
messages = updates.computeIfAbsent(coordinates, coords -> repository.get(coords).getUpdates(position.getHeight()));
|
||||
messages = updates.computeIfAbsent(coordinates, coords -> repository.get(coords).getUpdates(lastKnownRegion.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
messages = snapshots.get(coordinates);
|
||||
if (messages == null) {
|
||||
synchronized (snapshots) {
|
||||
messages = snapshots.computeIfAbsent(coordinates, coords -> repository.get(coords).getSnapshot(position.getHeight()));
|
||||
messages = snapshots.computeIfAbsent(coordinates, coords -> repository.get(coords).getSnapshot(lastKnownRegion.getHeight()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
||||
throw new IllegalArgumentException("Unrecognised RegionUpdateMode " + mode + ".");
|
||||
}
|
||||
|
||||
return messages.isEmpty() ? Optional.empty() : Optional.of(new GroupedRegionUpdateMessage(position, coordinates, messages));
|
||||
return messages.isEmpty() ? Optional.empty() : Optional.of(new GroupedRegionUpdateMessage(lastKnownRegion, coordinates, messages));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public final class BinaryPlayerSerializer extends PlayerSerializer {
|
||||
int y = in.readUnsignedShort();
|
||||
int height = in.readUnsignedByte();
|
||||
|
||||
Gender gender = (in.readUnsignedByte() == Gender.MALE.toInteger()) ? Gender.MALE : Gender.FEMALE;
|
||||
Gender gender = in.readUnsignedByte() == Gender.MALE.toInteger() ? Gender.MALE : Gender.FEMALE;
|
||||
int[] style = new int[7];
|
||||
for (int slot = 0; slot < style.length; slot++) {
|
||||
style[slot] = in.readUnsignedByte();
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.apollo.login;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -16,12 +17,11 @@ import org.apollo.net.codec.login.LoginRequest;
|
||||
import org.apollo.net.release.Release;
|
||||
import org.apollo.net.session.GameSession;
|
||||
import org.apollo.net.session.LoginSession;
|
||||
import org.apollo.util.ThreadUtil;
|
||||
import org.apollo.util.xml.XmlNode;
|
||||
import org.apollo.util.xml.XmlParser;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
* The {@link LoginService} manages {@link LoginRequest}s.
|
||||
*
|
||||
@@ -33,7 +33,7 @@ public final class LoginService extends Service {
|
||||
/**
|
||||
* The {@link ExecutorService} to which workers are submitted.
|
||||
*/
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("LoginService").build());
|
||||
private final ExecutorService executor = Executors.newCachedThreadPool(ThreadUtil.build("LoginService"));
|
||||
|
||||
/**
|
||||
* The current {@link PlayerSerializer}.
|
||||
@@ -79,9 +79,6 @@ public final class LoginService extends Service {
|
||||
this.serializer = (PlayerSerializer) clazz.getConstructor(World.class).newInstance(world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the login service.
|
||||
*/
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
@@ -92,15 +89,44 @@ public final class LoginService extends Service {
|
||||
*
|
||||
* @param session The session submitting this request.
|
||||
* @param request The login request.
|
||||
* @throws IOException If some I/O exception occurs.
|
||||
*/
|
||||
public void submitLoadRequest(LoginSession session, LoginRequest request) {
|
||||
Release release = session.getRelease();
|
||||
if (release.getReleaseNumber() != request.getReleaseNumber()) {
|
||||
// TODO check archive 0 CRCs
|
||||
session.handlePlayerLoaderResponse(request, new PlayerLoaderResponse(LoginConstants.STATUS_GAME_UPDATED));
|
||||
} else {
|
||||
executor.submit(new PlayerLoaderWorker(serializer, session, request));
|
||||
public void submitLoadRequest(LoginSession session, LoginRequest request) throws IOException {
|
||||
int response = LoginConstants.STATUS_OK;
|
||||
|
||||
if (requiresUpdate(session, request)) {
|
||||
response = LoginConstants.STATUS_GAME_UPDATED;
|
||||
}
|
||||
|
||||
if (response == LoginConstants.STATUS_OK) {
|
||||
executor.submit(new PlayerLoaderWorker(serializer, session, request));
|
||||
} else {
|
||||
session.handlePlayerLoaderResponse(request, new PlayerLoaderResponse(response));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an update is required whenever a {@link Player} submits a login request.
|
||||
*
|
||||
* @param session The login session.
|
||||
* @param request The login request.
|
||||
* @return {@code true} if an update is required, otherwise return {@code false}.
|
||||
* @throws IOException If some I/O exception occurs.
|
||||
*/
|
||||
private boolean requiresUpdate(LoginSession session, LoginRequest request) throws IOException {
|
||||
Release release = getContext().getRelease();
|
||||
if (release.getReleaseNumber() != request.getReleaseNumber()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int[] clientCrcs = request.getArchiveCrcs();
|
||||
int[] serverCrcs = getContext().getFileSystem().getCrcs();
|
||||
|
||||
if (Arrays.equals(clientCrcs, serverCrcs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -66,13 +66,14 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object message) {
|
||||
public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
|
||||
try {
|
||||
Attribute<Session> attribute = ctx.attr(NetworkConstants.SESSION_KEY);
|
||||
Channel channel = ctx.channel();
|
||||
Attribute<Session> attribute = channel.attr(NetworkConstants.SESSION_KEY);
|
||||
Session session = attribute.get();
|
||||
|
||||
if (message instanceof HttpRequest || message instanceof JagGrabRequest) {
|
||||
session = new UpdateSession(ctx.channel(), serverContext);
|
||||
session = new UpdateSession(channel, serverContext);
|
||||
}
|
||||
|
||||
if (session != null) {
|
||||
@@ -86,11 +87,11 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
switch (handshakeMessage.getServiceId()) {
|
||||
case HandshakeConstants.SERVICE_GAME:
|
||||
attribute.set(new LoginSession(ctx, serverContext));
|
||||
attribute.set(new LoginSession(channel, serverContext));
|
||||
break;
|
||||
|
||||
case HandshakeConstants.SERVICE_UPDATE:
|
||||
attribute.set(new UpdateSession(ctx.channel(), serverContext));
|
||||
attribute.set(new UpdateSession(channel, serverContext));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
||||
int read;
|
||||
if (reader.getLength() == 2) {
|
||||
read = (int) reader.getUnsigned(DataType.SHORT);
|
||||
int clicks = (read >> 12);
|
||||
int dX = (read >> 6) & 0x3f;
|
||||
int clicks = read >> 12;
|
||||
int dX = read >> 6 & 0x3f;
|
||||
int dY = read & 0x3f;
|
||||
return new FlaggedMouseEventMessage(clicks, dX, dY, true);
|
||||
} else if (reader.getLength() == 3) {
|
||||
@@ -29,7 +29,7 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
||||
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
|
||||
}
|
||||
|
||||
int clicks = (read >> 19);
|
||||
int clicks = read >> 19;
|
||||
int x = (read & 0x7f) % 765;
|
||||
int y = (read & 0x7f) / 765;
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ public final class GroupedRegionUpdateMessageEncoder extends MessageEncoder<Grou
|
||||
@Override
|
||||
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(60, PacketType.VARIABLE_SHORT);
|
||||
Position player = message.getPlayerPosition(), region = message.getRegionPosition();
|
||||
Position lastKnownRegion = message.getLastKnownRegion(), region = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, player.getLocalY(region));
|
||||
System.out.println("Grum: local x: " + player.getLocalX(region) + ", local y: " + player.getLocalY(region));
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, player.getLocalX(region));
|
||||
builder.put(DataType.BYTE, region.getLocalY(lastKnownRegion));
|
||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, region.getLocalX(lastKnownRegion));
|
||||
System.out.println("Grum: local x: " + lastKnownRegion.getLocalX(region) + ", local y: " + lastKnownRegion.getLocalY(region));
|
||||
|
||||
for (RegionUpdateMessage update : message.getMessages()) {
|
||||
System.out.println("==== Sending " + update + " as part of grum");
|
||||
|
||||
@@ -19,9 +19,9 @@ public final class MouseClickedMessageDecoder extends MessageDecoder<MouseClicke
|
||||
int value = (int) reader.getUnsigned(DataType.INT);
|
||||
|
||||
long delay = (value >> 20) * 50;
|
||||
boolean right = ((value >> 19) & 0x1) == 1;
|
||||
boolean right = (value >> 19 & 0x1) == 1;
|
||||
|
||||
int cords = (value & 0x3FFFF);
|
||||
int cords = value & 0x3FFFF;
|
||||
int x = cords % 765;
|
||||
int y = cords / 765;
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
||||
|
||||
if (reader.getLength() == 2) {
|
||||
read = (int) reader.getUnsigned(DataType.SHORT);
|
||||
clicks = (read >> 12);
|
||||
x = (read >> 6) & 0x3f;
|
||||
clicks = read >> 12;
|
||||
x = read >> 6 & 0x3f;
|
||||
y = read & 0x3f;
|
||||
return new FlaggedMouseEventMessage(clicks, x, y, true);
|
||||
} else if (reader.getLength() == 3) {
|
||||
@@ -30,7 +30,7 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
||||
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
|
||||
}
|
||||
|
||||
clicks = (read >> 19);
|
||||
clicks = read >> 19;
|
||||
x = (read & 0x7f) % 765;
|
||||
y = (read & 0x7f) / 765;
|
||||
return new FlaggedMouseEventMessage(clicks, x, y, false);
|
||||
|
||||
@@ -39,7 +39,7 @@ public final class GroupedRegionUpdateMessageEncoder extends MessageEncoder<Grou
|
||||
@Override
|
||||
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(183, PacketType.VARIABLE_SHORT);
|
||||
Position base = message.getPlayerPosition(), region = message.getRegionPosition();
|
||||
Position base = message.getLastKnownRegion(), region = message.getRegionPosition();
|
||||
|
||||
builder.put(DataType.BYTE, region.getLocalX(base));
|
||||
builder.put(DataType.BYTE, DataTransformation.ADD, region.getLocalY(base));
|
||||
|
||||
@@ -19,9 +19,9 @@ public final class MouseClickedMessageDecoder extends MessageDecoder<MouseClicke
|
||||
int value = (int) reader.getUnsigned(DataType.INT);
|
||||
|
||||
long delay = (value >> 20) * 50;
|
||||
boolean right = ((value >> 19) & 0x1) == 1;
|
||||
boolean right = (value >> 19 & 0x1) == 1;
|
||||
|
||||
int cords = (value & 0x3FFFF);
|
||||
int cords = value & 0x3FFFF;
|
||||
int x = cords % 765;
|
||||
int y = cords / 765;
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.apollo.game.message.Message;
|
||||
import org.apollo.game.message.MessageHandlerChainSet;
|
||||
import org.apollo.game.message.impl.LogoutMessage;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.util.CollectionUtil;
|
||||
|
||||
/**
|
||||
* A game session.
|
||||
@@ -84,13 +83,14 @@ public final class GameSession extends Session {
|
||||
* @param chainSet The {@link MessageHandlerChainSet}
|
||||
*/
|
||||
public void handlePendingMessages(MessageHandlerChainSet chainSet) {
|
||||
CollectionUtil.pollAll(messageQueue, message -> {
|
||||
Message message;
|
||||
while ((message = messageQueue.poll()) != null) {
|
||||
try {
|
||||
chainSet.notify(player, message);
|
||||
} catch (Exception reason) {
|
||||
logger.log(Level.SEVERE, "Uncaught exception thrown while handling message: " + message, reason);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,8 +3,8 @@ package org.apollo.net.session;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apollo.ServerContext;
|
||||
@@ -13,7 +13,6 @@ import org.apollo.game.model.World.RegistrationStatus;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.io.player.PlayerLoaderResponse;
|
||||
import org.apollo.login.LoginService;
|
||||
import org.apollo.net.ApolloHandler;
|
||||
import org.apollo.net.NetworkConstants;
|
||||
import org.apollo.net.codec.game.GameMessageDecoder;
|
||||
import org.apollo.net.codec.game.GameMessageEncoder;
|
||||
@@ -32,26 +31,20 @@ import org.apollo.security.IsaacRandomPair;
|
||||
*/
|
||||
public final class LoginSession extends Session {
|
||||
|
||||
/**
|
||||
* The context of the {@link ApolloHandler}.
|
||||
*/
|
||||
private final ChannelHandlerContext channelContext;
|
||||
|
||||
/**
|
||||
* The server context.
|
||||
*/
|
||||
private final ServerContext serverContext;
|
||||
private final ServerContext context;
|
||||
|
||||
/**
|
||||
* Creates a login session for the specified channel.
|
||||
*
|
||||
* @param ctx The context of the {@link ApolloHandler}.
|
||||
* @param serverContext The server context.
|
||||
* @param channel The channel.
|
||||
* @param context The server context.
|
||||
*/
|
||||
public LoginSession(ChannelHandlerContext ctx, ServerContext serverContext) {
|
||||
super(ctx.channel());
|
||||
this.channelContext = ctx;
|
||||
this.serverContext = serverContext;
|
||||
public LoginSession(Channel channel, ServerContext context) {
|
||||
super(channel);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,22 +52,14 @@ public final class LoginSession extends Session {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the release.
|
||||
*
|
||||
* @return The release.
|
||||
*/
|
||||
public Release getRelease() {
|
||||
return serverContext.getRelease();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a login request.
|
||||
*
|
||||
* @param request The login request.
|
||||
* @throws IOException If some I/O exception occurs.
|
||||
*/
|
||||
private void handleLoginRequest(LoginRequest request) {
|
||||
LoginService loginService = serverContext.getService(LoginService.class);
|
||||
private void handleLoginRequest(LoginRequest request) throws IOException {
|
||||
LoginService loginService = context.getService(LoginService.class);
|
||||
loginService.submitLoadRequest(this, request);
|
||||
}
|
||||
|
||||
@@ -85,7 +70,7 @@ public final class LoginSession extends Session {
|
||||
* @param response The response.
|
||||
*/
|
||||
public void handlePlayerLoaderResponse(LoginRequest request, PlayerLoaderResponse response) {
|
||||
GameService service = serverContext.getService(GameService.class);
|
||||
GameService service = context.getService(GameService.class);
|
||||
Channel channel = getChannel();
|
||||
|
||||
Optional<Player> optional = response.getPlayer();
|
||||
@@ -96,14 +81,14 @@ public final class LoginSession extends Session {
|
||||
Player player = optional.get();
|
||||
rights = player.getPrivilegeLevel().toInteger();
|
||||
|
||||
GameSession session = new GameSession(channel, serverContext, player);
|
||||
GameSession session = new GameSession(channel, context, player);
|
||||
RegistrationStatus registration = service.registerPlayer(player, session);
|
||||
|
||||
if (registration != RegistrationStatus.OK) {
|
||||
optional = Optional.empty();
|
||||
rights = 0;
|
||||
|
||||
status = (registration == RegistrationStatus.ALREADY_ONLINE) ? LoginConstants.STATUS_ACCOUNT_ONLINE : LoginConstants.STATUS_SERVER_FULL;
|
||||
status = registration == RegistrationStatus.ALREADY_ONLINE ? LoginConstants.STATUS_ACCOUNT_ONLINE : LoginConstants.STATUS_SERVER_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,18 +98,18 @@ public final class LoginSession extends Session {
|
||||
|
||||
if (optional.isPresent()) {
|
||||
IsaacRandomPair randomPair = request.getRandomPair();
|
||||
Release release = serverContext.getRelease();
|
||||
Release release = context.getRelease();
|
||||
|
||||
channel.pipeline().addFirst("messageEncoder", new GameMessageEncoder(release));
|
||||
channel.pipeline().addBefore("messageEncoder", "gameEncoder", new GamePacketEncoder(randomPair.getEncodingRandom()));
|
||||
|
||||
channel.pipeline().addBefore("handler", "gameDecoder", new GamePacketDecoder(randomPair.getDecodingRandom(), serverContext.getRelease()));
|
||||
channel.pipeline().addBefore("handler", "gameDecoder", new GamePacketDecoder(randomPair.getDecodingRandom(), context.getRelease()));
|
||||
channel.pipeline().addAfter("gameDecoder", "messageDecoder", new GameMessageDecoder(release));
|
||||
|
||||
channel.pipeline().remove("loginDecoder");
|
||||
channel.pipeline().remove("loginEncoder");
|
||||
|
||||
channelContext.attr(NetworkConstants.SESSION_KEY).set(optional.get().getSession());
|
||||
channel.attr(NetworkConstants.SESSION_KEY).set(optional.get().getSession());
|
||||
} else {
|
||||
future.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
@@ -135,7 +120,7 @@ public final class LoginSession extends Session {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(Object message) {
|
||||
public void messageReceived(Object message) throws Exception {
|
||||
if (message.getClass() == LoginRequest.class) {
|
||||
handleLoginRequest((LoginRequest) message);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ public abstract class Session {
|
||||
* Processes a message received from the channel.
|
||||
*
|
||||
* @param message The message.
|
||||
* @throws Exception If some error occurs.
|
||||
*/
|
||||
public abstract void messageReceived(Object message);
|
||||
public abstract void messageReceived(Object message) throws Exception;
|
||||
|
||||
}
|
||||
@@ -31,12 +31,11 @@ public final class RsaKeyGenerator {
|
||||
do {
|
||||
p = BigInteger.probablePrime(BIT_COUNT / 2, random);
|
||||
q = BigInteger.probablePrime(BIT_COUNT / 2, random);
|
||||
phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
|
||||
phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
|
||||
|
||||
modulus = p.multiply(q);
|
||||
privateKey = publicKey.modInverse(phi);
|
||||
} while (modulus.bitLength() != BIT_COUNT || privateKey.bitLength() != BIT_COUNT
|
||||
|| !phi.gcd(publicKey).equals(BigInteger.ONE));
|
||||
} while (modulus.bitLength() != BIT_COUNT || privateKey.bitLength() != BIT_COUNT || !phi.gcd(publicKey).equals(BigInteger.ONE));
|
||||
|
||||
System.out.println("modulus: " + modulus);
|
||||
System.out.println("public key: " + publicKey);
|
||||
|
||||
@@ -23,27 +23,18 @@ public final class TextUtil {
|
||||
* @return The string with correct capitalization.
|
||||
*/
|
||||
public static String capitalize(String str) {
|
||||
char[] chars = str.toCharArray();
|
||||
boolean sentenceStart = true;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
char c = chars[i];
|
||||
if (sentenceStart) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
chars[i] -= 0x20;
|
||||
sentenceStart = false;
|
||||
} else if (c >= 'A' && c <= 'Z') {
|
||||
sentenceStart = false;
|
||||
}
|
||||
} else {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
chars[i] += 0x20;
|
||||
}
|
||||
}
|
||||
if (c == '.' || c == '!' || c == '?') {
|
||||
sentenceStart = true;
|
||||
boolean capitalize = true;
|
||||
StringBuilder bldr = new StringBuilder(str);
|
||||
for (int index = 0, length = str.length(); index < length; index++) {
|
||||
char character = bldr.charAt(index);
|
||||
if (character == '.' || character == '!' || character == '?') {
|
||||
capitalize = true;
|
||||
} else if (capitalize && !Character.isWhitespace(character)) {
|
||||
bldr.setCharAt(index, Character.toUpperCase(character));
|
||||
capitalize = false;
|
||||
}
|
||||
}
|
||||
return new String(chars, 0, chars.length);
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
* A static utility class which provides ease of use functionality for {@link Thread}s
|
||||
*
|
||||
* @author Ryley Kimmel <ryley.kimmel@live.com>
|
||||
*/
|
||||
public final class ThreadUtil {
|
||||
|
||||
/**
|
||||
* Returns the amount of available processors available to the Java virtual machine.
|
||||
*/
|
||||
public static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
/**
|
||||
* A {@link Logger} used to debug messages to the console.
|
||||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger(ThreadUtil.class.getSimpleName());
|
||||
|
||||
/**
|
||||
* The default {@link UncaughtExceptionHandler} which raises an error from the logger with the exception and name of
|
||||
* the specified thread the exception occurred in.
|
||||
*/
|
||||
private static final UncaughtExceptionHandler DEFAULT_EXCEPTION_HANDLER = (thread, exception) -> LOGGER.log(Level.SEVERE, "Exception occured in thread " + thread.getName(), exception);
|
||||
|
||||
/**
|
||||
* Builds a {@link ThreadFactory} using the specified {@code String} name-format, {@link ThreadPriority} and
|
||||
* {@link UncaughtExceptionHandler}.
|
||||
*
|
||||
* @param name The name-format used when creating threads, may not be {@code null}.
|
||||
* @param priority The priority used when creating threads, may not be {@code null}.
|
||||
* @param handler The {@link UncaughtExceptionHandler} used when creating threads, may not be {@code null}.
|
||||
* @return A new {@link ThreadFactory} from the specified parameters, never {@code null}.
|
||||
*/
|
||||
public static ThreadFactory build(String name, ThreadPriority priority, UncaughtExceptionHandler handler) {
|
||||
Objects.requireNonNull(priority);
|
||||
|
||||
ThreadFactoryBuilder bldr = new ThreadFactoryBuilder();
|
||||
bldr.setNameFormat(name);
|
||||
bldr.setPriority(priority.getValue());
|
||||
bldr.setUncaughtExceptionHandler(handler);
|
||||
return bldr.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link ThreadFactory} using the specified {@code String} name-format, {@link ThreadPriority} and the
|
||||
* default {@link UncaughtExceptionHandler}.
|
||||
*
|
||||
* @param name The name-format used when creating threads, may not be {@code null}.
|
||||
* @param priority The priority used when creating threads, may not be {@code null}.
|
||||
* @return A new {@link ThreadFactory} from the specified parameters, never {@code null}.
|
||||
* @see {@link #DEFAULT_EXCEPTION_HANDLER}
|
||||
*/
|
||||
public static ThreadFactory build(String name, ThreadPriority priority) {
|
||||
return build(name, priority, DEFAULT_EXCEPTION_HANDLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link ThreadFactory} using the specified {@code String} name-format, normal thread priority and the
|
||||
* default {@link UncaughtExceptionHandler}.
|
||||
*
|
||||
* @param name The name-format used when creating threads, may not be {@code null}.
|
||||
* @return A new {@link ThreadFactory} from the specified parameters, never {@code null}.
|
||||
* @see {@link #DEFAULT_EXCEPTION_HANDLER}
|
||||
* @see {@link ThreadPriority#NORMAL_PRIORITY}
|
||||
*/
|
||||
public static ThreadFactory build(String name) {
|
||||
return build(name, ThreadPriority.NORMAL_PRIORITY, DEFAULT_EXCEPTION_HANDLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration representing the priority of a {@link Thread}.
|
||||
*
|
||||
* @author Ryley Kimmel <ryley.kimmel@live.com>
|
||||
*/
|
||||
public enum ThreadPriority {
|
||||
|
||||
/**
|
||||
* Represents the minimum priority of a thread.
|
||||
*/
|
||||
MINIMUM_PRIORITY(1),
|
||||
|
||||
/**
|
||||
* Represents the normal priority of a thread.
|
||||
*/
|
||||
NORMAL_PRIORITY(5),
|
||||
|
||||
/**
|
||||
* Represents the maximum priority of a thread.
|
||||
*/
|
||||
MAXIMUM_PRIORITY(10);
|
||||
|
||||
/**
|
||||
* The value of this thread priority.
|
||||
*/
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ThreadPriority} with the specified value.
|
||||
*
|
||||
* @param value The value of this thread priority, must be within the bounds of {@link Thread#MIN_PRIORITY} and
|
||||
* {@link Thread#MAX_PRIORITY}.
|
||||
*/
|
||||
private ThreadPriority(int value) {
|
||||
// fail-fast for invalid priority values
|
||||
checkArgument(value >= Thread.MIN_PRIORITY, "Thread priority (%s) must be >= %s", value, Thread.MIN_PRIORITY);
|
||||
checkArgument(value <= Thread.MAX_PRIORITY, "Thread priority (%s) must be <= %s", value, Thread.MAX_PRIORITY);
|
||||
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this thread priority.
|
||||
*/
|
||||
public final int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents the default-public constructor to discourage instantiation of this class.
|
||||
*/
|
||||
private ThreadUtil() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public final class PluginManager {
|
||||
/**
|
||||
* A set of all author names.
|
||||
*/
|
||||
private SortedSet<String> authors = new TreeSet<>();
|
||||
private final SortedSet<String> authors = new TreeSet<>();
|
||||
|
||||
/**
|
||||
* The plugin context.
|
||||
@@ -164,8 +164,7 @@ public final class PluginManager {
|
||||
* @throws DependencyException If a dependency error occurs.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
private void start(PluginEnvironment env, PluginMetaData plugin, Map<String, PluginMetaData> plugins,
|
||||
Set<PluginMetaData> started) throws DependencyException, IOException {
|
||||
private void start(PluginEnvironment env, PluginMetaData plugin, Map<String, PluginMetaData> plugins, Set<PluginMetaData> started) throws DependencyException, IOException {
|
||||
// TODO check for cyclic dependencies! this way just won't cut it, we need an exception
|
||||
if (started.contains(plugin)) {
|
||||
return;
|
||||
|
||||
@@ -74,7 +74,7 @@ public final class XmlParser {
|
||||
/**
|
||||
* The stack of nodes, used when traversing the document and going through child nodes.
|
||||
*/
|
||||
private Stack<XmlNode> nodeStack = new Stack<>();
|
||||
private final Stack<XmlNode> nodeStack = new Stack<>();
|
||||
|
||||
/**
|
||||
* The current root node.
|
||||
|
||||
Reference in New Issue
Block a user