mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-07 16:49:12 +00:00
Resolve merge conflict.
This commit is contained in:
@@ -13,12 +13,12 @@ class OpenDoorAction < DistancedAction
|
|||||||
|
|
||||||
def executeAction
|
def executeAction
|
||||||
mob.turn_to(@door.position)
|
mob.turn_to(@door.position)
|
||||||
DoorUtil::toggle(@door, mob)
|
DoorUtil::toggle(@door)
|
||||||
stop
|
stop
|
||||||
end
|
end
|
||||||
|
|
||||||
def equals(other)
|
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
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -28,6 +28,7 @@ on :message, :first_object_action do |player, message|
|
|||||||
if DoorUtil::is_door?(message.id)
|
if DoorUtil::is_door?(message.id)
|
||||||
puts "Player: #{player.position}, door: #{message.position}"
|
puts "Player: #{player.position}, door: #{message.position}"
|
||||||
door = DoorUtil::get_door_object(message.position, message.id)
|
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
|
||||||
end
|
end
|
||||||
@@ -46,7 +46,7 @@ module DoorUtil
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Toggles the given door.
|
# Toggles the given door.
|
||||||
def self.toggle(door, player)
|
def self.toggle(door)
|
||||||
position = door.position
|
position = door.position
|
||||||
region = $world.region_repository.from_position(position)
|
region = $world.region_repository.from_position(position)
|
||||||
region.remove_entity(door)
|
region.remove_entity(door)
|
||||||
@@ -59,7 +59,7 @@ module DoorUtil
|
|||||||
else
|
else
|
||||||
toggled_position = translate_door_position(door)
|
toggled_position = translate_door_position(door)
|
||||||
toggled_orientation = translate_door_orientation(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 = $world.region_repository.from_position(toggled_position)
|
||||||
toggled_region.add_entity(toggled_door)
|
toggled_region.add_entity(toggled_door)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<project xmlns="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"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -58,7 +57,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.netty</groupId>
|
<groupId>io.netty</groupId>
|
||||||
<artifactId>netty-all</artifactId>
|
<artifactId>netty-all</artifactId>
|
||||||
<version>4.0.26.Final</version>
|
<version>4.0.27.Final</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@@ -31,58 +31,49 @@ public final class IsaacRandom {
|
|||||||
private static final int GOLDEN_RATIO = 0x9e3779b9;
|
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;
|
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;
|
private static int MASK = SIZE - 1 << 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The accumulator.
|
* The results given to the user.
|
||||||
*/
|
*/
|
||||||
private int a;
|
private final int[] results = new int[SIZE];
|
||||||
|
|
||||||
/**
|
|
||||||
* The last result.
|
|
||||||
*/
|
|
||||||
private int b;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The counter.
|
|
||||||
*/
|
|
||||||
private int c;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The count through the results in the results array.
|
|
||||||
*/
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The internal state.
|
* 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() {
|
private int accumulator;
|
||||||
mem = new int[SIZE];
|
|
||||||
rsl = new int[SIZE];
|
/**
|
||||||
init(false);
|
* The last result.
|
||||||
}
|
*/
|
||||||
|
private int last;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The counter.
|
||||||
|
*/
|
||||||
|
private int counter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the random number generator with the specified seed.
|
* Creates the random number generator with the specified seed.
|
||||||
@@ -90,20 +81,75 @@ public final class IsaacRandom {
|
|||||||
* @param seed The seed.
|
* @param seed The seed.
|
||||||
*/
|
*/
|
||||||
public IsaacRandom(int[] seed) {
|
public IsaacRandom(int[] seed) {
|
||||||
mem = new int[SIZE];
|
int length = Math.min(seed.length, results.length);
|
||||||
rsl = new int[SIZE];
|
System.arraycopy(seed, 0, results, 0, length);
|
||||||
for (int i = 0; i < seed.length; ++i) {
|
init();
|
||||||
rsl[i] = seed[i];
|
|
||||||
}
|
|
||||||
init(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises this random number generator.
|
* Generates 256 results.
|
||||||
*
|
|
||||||
* @param hasSeed Set to {@code true} if a seed was passed to the constructor.
|
|
||||||
*/
|
*/
|
||||||
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 i;
|
||||||
int a, b, c, d, e, f, g, h;
|
int a, b, c, d, e, f, g, h;
|
||||||
a = b = c = d = e = f = g = h = GOLDEN_RATIO;
|
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 */
|
for (i = 0; i < SIZE; i += 8) { /* fill in mem[] with messy stuff */
|
||||||
if (hasSeed) {
|
a += results[i];
|
||||||
a += rsl[i];
|
b += results[i + 1];
|
||||||
b += rsl[i + 1];
|
c += results[i + 2];
|
||||||
c += rsl[i + 2];
|
d += results[i + 3];
|
||||||
d += rsl[i + 3];
|
e += results[i + 4];
|
||||||
e += rsl[i + 4];
|
f += results[i + 5];
|
||||||
f += rsl[i + 5];
|
g += results[i + 6];
|
||||||
g += rsl[i + 6];
|
h += results[i + 7];
|
||||||
h += rsl[i + 7];
|
|
||||||
}
|
|
||||||
a ^= b << 11;
|
a ^= b << 11;
|
||||||
d += a;
|
d += a;
|
||||||
b += c;
|
b += c;
|
||||||
@@ -170,26 +215,25 @@ public final class IsaacRandom {
|
|||||||
h ^= a >>> 9;
|
h ^= a >>> 9;
|
||||||
c += h;
|
c += h;
|
||||||
a += b;
|
a += b;
|
||||||
mem[i] = a;
|
state[i] = a;
|
||||||
mem[i + 1] = b;
|
state[i + 1] = b;
|
||||||
mem[i + 2] = c;
|
state[i + 2] = c;
|
||||||
mem[i + 3] = d;
|
state[i + 3] = d;
|
||||||
mem[i + 4] = e;
|
state[i + 4] = e;
|
||||||
mem[i + 5] = f;
|
state[i + 5] = f;
|
||||||
mem[i + 6] = g;
|
state[i + 6] = g;
|
||||||
mem[i + 7] = h;
|
state[i + 7] = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSeed) { /* second pass makes all of seed affect all of mem */
|
|
||||||
for (i = 0; i < SIZE; i += 8) {
|
for (i = 0; i < SIZE; i += 8) {
|
||||||
a += mem[i];
|
a += state[i];
|
||||||
b += mem[i + 1];
|
b += state[i + 1];
|
||||||
c += mem[i + 2];
|
c += state[i + 2];
|
||||||
d += mem[i + 3];
|
d += state[i + 3];
|
||||||
e += mem[i + 4];
|
e += state[i + 4];
|
||||||
f += mem[i + 5];
|
f += state[i + 5];
|
||||||
g += mem[i + 6];
|
g += state[i + 6];
|
||||||
h += mem[i + 7];
|
h += state[i + 7];
|
||||||
a ^= b << 11;
|
a ^= b << 11;
|
||||||
d += a;
|
d += a;
|
||||||
b += c;
|
b += c;
|
||||||
@@ -214,79 +258,17 @@ public final class IsaacRandom {
|
|||||||
h ^= a >>> 9;
|
h ^= a >>> 9;
|
||||||
c += h;
|
c += h;
|
||||||
a += b;
|
a += b;
|
||||||
mem[i] = a;
|
state[i] = a;
|
||||||
mem[i + 1] = b;
|
state[i + 1] = b;
|
||||||
mem[i + 2] = c;
|
state[i + 2] = c;
|
||||||
mem[i + 3] = d;
|
state[i + 3] = d;
|
||||||
mem[i + 4] = e;
|
state[i + 4] = e;
|
||||||
mem[i + 5] = f;
|
state[i + 5] = f;
|
||||||
mem[i + 6] = g;
|
state[i + 6] = g;
|
||||||
mem[i + 7] = h;
|
state[i + 7] = h;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isaac();
|
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();
|
isaac();
|
||||||
count = SIZE - 1;
|
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.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
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.PluginContext;
|
||||||
import org.apollo.util.plugin.PluginManager;
|
import org.apollo.util.plugin.PluginManager;
|
||||||
|
|
||||||
|
import com.google.common.base.Stopwatch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The core class of the Apollo server.
|
* 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.
|
* @param args The command-line arguments passed to the application.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
Server server = new Server();
|
Server server = new Server();
|
||||||
server.init(args.length == 1 ? args[0] : Release317.class.getName());
|
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);
|
SocketAddress jaggrab = new InetSocketAddress(NetworkConstants.JAGGRAB_PORT);
|
||||||
|
|
||||||
server.bind(service, http, jaggrab);
|
server.bind(service, http, jaggrab);
|
||||||
logger.fine("Starting apollo took " + (System.currentTimeMillis() - start) + " ms.");
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.log(Level.SEVERE, "Error whilst starting server.", 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.
|
* Creates the Apollo server.
|
||||||
*
|
|
||||||
* @throws Exception If an error occurs whilst creating services.
|
|
||||||
*/
|
*/
|
||||||
public Server() throws Exception {
|
public Server() {
|
||||||
logger.info("Starting Apollo...");
|
logger.info("Starting Apollo...");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,14 +101,14 @@ public final class Server {
|
|||||||
public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) {
|
public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) {
|
||||||
try {
|
try {
|
||||||
logger.fine("Binding service listener to address: " + serviceAddress + "...");
|
logger.fine("Binding service listener to address: " + serviceAddress + "...");
|
||||||
serviceBootstrap.bind(serviceAddress).syncUninterruptibly();
|
serviceBootstrap.bind(serviceAddress).sync();
|
||||||
|
|
||||||
logger.fine("Binding HTTP listener to address: " + httpAddress + "...");
|
logger.fine("Binding HTTP listener to address: " + httpAddress + "...");
|
||||||
httpBootstrap.bind(httpAddress).syncUninterruptibly();
|
httpBootstrap.bind(httpAddress).sync();
|
||||||
|
|
||||||
logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
|
logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
|
||||||
jagGrabBootstrap.bind(jagGrabAddress).syncUninterruptibly();
|
jagGrabBootstrap.bind(jagGrabAddress).sync();
|
||||||
} catch (Exception e) {
|
} catch (InterruptedException e) {
|
||||||
logger.log(Level.SEVERE, "Binding to a port failed: ensure apollo isn't already running.", e);
|
logger.log(Level.SEVERE, "Binding to a port failed: ensure apollo isn't already running.", e);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
@@ -122,8 +125,9 @@ public final class Server {
|
|||||||
public void init(String releaseClassName) throws Exception {
|
public void init(String releaseClassName) throws Exception {
|
||||||
Class<?> clazz = Class.forName(releaseClassName);
|
Class<?> clazz = Class.forName(releaseClassName);
|
||||||
Release release = (Release) clazz.newInstance();
|
Release release = (Release) clazz.newInstance();
|
||||||
|
int releaseNo = release.getReleaseNumber();
|
||||||
|
|
||||||
logger.info("Initialized release #" + release.getReleaseNumber() + ".");
|
logger.info("Initialized release #" + releaseNo + ".");
|
||||||
|
|
||||||
serviceBootstrap.group(loopGroup);
|
serviceBootstrap.group(loopGroup);
|
||||||
httpBootstrap.group(loopGroup);
|
httpBootstrap.group(loopGroup);
|
||||||
@@ -131,7 +135,8 @@ public final class Server {
|
|||||||
|
|
||||||
World world = new World();
|
World world = new World();
|
||||||
ServiceManager serviceManager = new ServiceManager(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);
|
ApolloHandler handler = new ApolloHandler(context);
|
||||||
|
|
||||||
ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler);
|
ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler);
|
||||||
@@ -149,8 +154,6 @@ public final class Server {
|
|||||||
PluginManager manager = new PluginManager(world, new PluginContext(context));
|
PluginManager manager = new PluginManager(world, new PluginContext(context));
|
||||||
serviceManager.startAll();
|
serviceManager.startAll();
|
||||||
|
|
||||||
int releaseNo = release.getReleaseNumber();
|
|
||||||
IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs", Integer.toString(releaseNo)), true);
|
|
||||||
world.init(releaseNo, fs, manager);
|
world.init(releaseNo, fs, manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package org.apollo;
|
package org.apollo;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apollo.fs.IndexedFileSystem;
|
||||||
import org.apollo.net.release.Release;
|
import org.apollo.net.release.Release;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,16 +24,23 @@ public final class ServerContext {
|
|||||||
*/
|
*/
|
||||||
private final ServiceManager serviceManager;
|
private final ServiceManager serviceManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
private final IndexedFileSystem fileSystem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new server context.
|
* Creates a new server context.
|
||||||
*
|
*
|
||||||
* @param release The current release.
|
* @param release The current release.
|
||||||
* @param serviceManager The service manager.
|
* @param serviceManager The service manager.
|
||||||
|
* @param fileSystem The indexed file system.
|
||||||
*/
|
*/
|
||||||
ServerContext(Release release, ServiceManager serviceManager) {
|
protected ServerContext(Release release, ServiceManager serviceManager, IndexedFileSystem fileSystem) {
|
||||||
this.release = release;
|
this.release = Objects.requireNonNull(release);
|
||||||
this.serviceManager = serviceManager;
|
this.serviceManager = Objects.requireNonNull(serviceManager);
|
||||||
this.serviceManager.setContext(this);
|
this.serviceManager.setContext(this);
|
||||||
|
this.fileSystem = Objects.requireNonNull(fileSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +52,15 @@ public final class ServerContext {
|
|||||||
return release;
|
return release;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the IndexeFileSystem
|
||||||
|
*
|
||||||
|
* @return The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
public IndexedFileSystem getFileSystem() {
|
||||||
|
return fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a service. This method is shorthand for {@code getServiceManager().getService(...)}.
|
* Gets a service. This method is shorthand for {@code getServiceManager().getService(...)}.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public final class ServiceManager {
|
|||||||
/**
|
/**
|
||||||
* The service map.
|
* 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}.
|
* Creates and initializes the {@link ServiceManager}.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.io.RandomAccessFile;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
@@ -24,6 +25,11 @@ public final class IndexedFileSystem implements Closeable {
|
|||||||
*/
|
*/
|
||||||
private ByteBuffer crcTable;
|
private ByteBuffer crcTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #crcTable} represented as an {@code int} array.
|
||||||
|
*/
|
||||||
|
private int[] crcs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data file.
|
* The data file.
|
||||||
*/
|
*/
|
||||||
@@ -32,7 +38,7 @@ public final class IndexedFileSystem implements Closeable {
|
|||||||
/**
|
/**
|
||||||
* The index files.
|
* The index files.
|
||||||
*/
|
*/
|
||||||
private RandomAccessFile[] indices = new RandomAccessFile[256];
|
private final RandomAccessFile[] indices = new RandomAccessFile[256];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read only flag.
|
* 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.");
|
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.
|
* Gets a file.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ public final class GameObjectDecoder {
|
|||||||
if (block) {
|
if (block) {
|
||||||
for (int dx = 0; dx < definition.getWidth(); dx++) {
|
for (int dx = 0; dx < definition.getWidth(); dx++) {
|
||||||
for (int dy = 0; dy < definition.getLength(); dy++) {
|
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) {
|
if (localX > 7 || localY > 7) {
|
||||||
int nextLocalX = localX > 7 ? x + localX - 7 : x + localX;
|
int nextLocalX = localX > 7 ? x + localX - 7 : x + localX;
|
||||||
@@ -141,11 +141,13 @@ public final class GameObjectDecoder {
|
|||||||
Position nextPosition = new Position(nextLocalX, nextLocalY);
|
Position nextPosition = new Position(nextLocalX, nextLocalY);
|
||||||
Region next = regions.fromPosition(nextPosition);
|
Region next = regions.fromPosition(nextPosition);
|
||||||
|
|
||||||
int nextX = (nextPosition.getX() % Region.SIZE) + dx, nextY = (nextPosition.getY() % Region.SIZE) + dy;
|
int nextX = nextPosition.getX() % Region.SIZE + dx, nextY = nextPosition.getY() % Region.SIZE + dy;
|
||||||
if (nextX > 7)
|
if (nextX > 7) {
|
||||||
nextX -= 7;
|
nextX -= 7;
|
||||||
if (nextY > 7)
|
}
|
||||||
|
if (nextY > 7) {
|
||||||
nextY -= 7;
|
nextY -= 7;
|
||||||
|
}
|
||||||
|
|
||||||
next.getMatrix(height).block(nextX, nextY);
|
next.getMatrix(height).block(nextX, nextY);
|
||||||
continue;
|
continue;
|
||||||
@@ -181,7 +183,7 @@ public final class GameObjectDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
int localX = (x % Region.SIZE), localY = (y % Region.SIZE);
|
int localX = x % Region.SIZE, localY = y % Region.SIZE;
|
||||||
current.block(localX, localY);
|
current.block(localX, localY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,7 +211,7 @@ public final class GameObjectDecoder {
|
|||||||
|
|
||||||
int localY = packed & 0x3F;
|
int localY = packed & 0x3F;
|
||||||
int localX = packed >> 6 & 0x3F;
|
int localX = packed >> 6 & 0x3F;
|
||||||
int height = (packed >> 12) & 0x3;
|
int height = packed >> 12 & 0x3;
|
||||||
|
|
||||||
int attributes = buffer.get() & 0xFF;
|
int attributes = buffer.get() & 0xFF;
|
||||||
int type = attributes >> 2;
|
int type = attributes >> 2;
|
||||||
|
|||||||
@@ -121,17 +121,13 @@ public final class NpcDefinitionDecoder {
|
|||||||
} else if (opcode == 102 || opcode == 103) {
|
} else if (opcode == 102 || opcode == 103) {
|
||||||
buffer.getShort();
|
buffer.getShort();
|
||||||
} else if (opcode == 106) {
|
} else if (opcode == 106) {
|
||||||
@SuppressWarnings("unused")
|
wrap(buffer.getShort());
|
||||||
int morphVariableBitsIndex = wrap(buffer.getShort());
|
wrap(buffer.getShort());
|
||||||
@SuppressWarnings("unused")
|
|
||||||
int morphismCount = wrap(buffer.getShort());
|
|
||||||
|
|
||||||
int count = buffer.get() & 0xFF;
|
int count = buffer.get() & 0xFF;
|
||||||
int[] morphisms = new int[count + 1];
|
int[] morphisms = new int[count + 1];
|
||||||
Arrays.setAll(morphisms, index -> wrap(buffer.getShort()));
|
Arrays.setAll(morphisms, index -> wrap(buffer.getShort()));
|
||||||
} else if (opcode == 107) {
|
} 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.login.LoginService;
|
||||||
import org.apollo.net.session.GameSession;
|
import org.apollo.net.session.GameSession;
|
||||||
import org.apollo.util.MobRepository;
|
import org.apollo.util.MobRepository;
|
||||||
|
import org.apollo.util.ThreadUtil;
|
||||||
import org.apollo.util.xml.XmlNode;
|
import org.apollo.util.xml.XmlNode;
|
||||||
import org.apollo.util.xml.XmlParser;
|
import org.apollo.util.xml.XmlParser;
|
||||||
import org.xml.sax.SAXException;
|
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.
|
* 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.
|
* 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}.
|
* The {@link ClientSynchronizer}.
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public final class MessageHandlerChainSet {
|
|||||||
public <M extends Message> boolean notify(Player player, M message) {
|
public <M extends Message> boolean notify(Player player, M message) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
MessageHandlerChain<M> chain = (MessageHandlerChain<M>) chains.get(message.getClass());
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null
|
if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null && EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) {
|
||||||
&& EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) {
|
|
||||||
equipment.set(EquipmentConstants.SHIELD, inventory.reset(inventorySlot));
|
equipment.set(EquipmentConstants.SHIELD, inventory.reset(inventorySlot));
|
||||||
inventory.add(equipment.reset(EquipmentConstants.WEAPON));
|
inventory.add(equipment.reset(EquipmentConstants.WEAPON));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ public final class ItemOnObjectVerificationHandler extends MessageHandler<ItemOn
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(Player player, ItemOnObjectMessage message) {
|
public void handle(Player player, ItemOnObjectMessage message) {
|
||||||
if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID
|
if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID && message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) {
|
||||||
&& message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) {
|
|
||||||
message.terminate();
|
message.terminate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public final class ForwardPrivateChatMessage extends Message {
|
|||||||
*/
|
*/
|
||||||
public ForwardPrivateChatMessage(String username, PrivilegeLevel level, byte[] message) {
|
public ForwardPrivateChatMessage(String username, PrivilegeLevel level, byte[] message) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.privilege = level;
|
privilege = level;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import org.apollo.game.model.area.RegionCoordinates;
|
|||||||
public final class GroupedRegionUpdateMessage extends Message {
|
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.
|
* The Position of the Region being updated.
|
||||||
@@ -31,13 +31,13 @@ public final class GroupedRegionUpdateMessage extends Message {
|
|||||||
/**
|
/**
|
||||||
* Creates the GroupedRegionUpdateMessage.
|
* 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 coordinates The {@link RegionCoordinates} of the Region being updated.
|
||||||
* @param messages The {@link List} of {@link RegionUpdateMessage}s.
|
* @param messages The {@link List} of {@link RegionUpdateMessage}s.
|
||||||
*/
|
*/
|
||||||
public GroupedRegionUpdateMessage(Position player, RegionCoordinates coordinates, List<RegionUpdateMessage> messages) {
|
public GroupedRegionUpdateMessage(Position lastKnownRegion, RegionCoordinates coordinates, List<RegionUpdateMessage> messages) {
|
||||||
this.player = player;
|
this.lastKnownRegion = lastKnownRegion;
|
||||||
this.region = new Position(coordinates.getAbsoluteX(), coordinates.getAbsoluteY());
|
region = new Position(coordinates.getAbsoluteX(), coordinates.getAbsoluteY());
|
||||||
this.messages = messages;
|
this.messages = messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,8 +46,8 @@ public final class GroupedRegionUpdateMessage extends Message {
|
|||||||
*
|
*
|
||||||
* @return The Position.
|
* @return The Position.
|
||||||
*/
|
*/
|
||||||
public Position getPlayerPosition() {
|
public Position getLastKnownRegion() {
|
||||||
return player;
|
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) {
|
public ItemOnObjectMessage(int interfaceId, int itemId, int itemSlot, int objectId, int x, int y) {
|
||||||
super(0, interfaceId, itemId, itemSlot);
|
super(0, interfaceId, itemId, itemSlot);
|
||||||
this.objectId = objectId;
|
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) {
|
public RemoveObjectMessage(GameObject object, int positionOffset) {
|
||||||
this.positionOffset = positionOffset;
|
this.positionOffset = positionOffset;
|
||||||
this.type = object.getType();
|
type = object.getType();
|
||||||
this.orientation = object.getOrientation();
|
orientation = object.getOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.
|
* @param positionOffset The offset of the object's position from the region's central position.
|
||||||
*/
|
*/
|
||||||
public SendObjectMessage(GameObject object, int positionOffset) {
|
public SendObjectMessage(GameObject object, int positionOffset) {
|
||||||
this.id = object.getId();
|
id = object.getId();
|
||||||
this.positionOffset = positionOffset;
|
this.positionOffset = positionOffset;
|
||||||
this.type = object.getType();
|
type = object.getType();
|
||||||
this.orientation = object.getOrientation();
|
orientation = object.getOrientation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public final class SetPlayerActionMessage extends Message {
|
|||||||
public SetPlayerActionMessage(String text, int slot, boolean primaryInteraction) {
|
public SetPlayerActionMessage(String text, int slot, boolean primaryInteraction) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
this.primaryAction = primaryInteraction;
|
primaryAction = primaryInteraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public final class WalkMessage extends Message {
|
|||||||
/**
|
/**
|
||||||
* The running flag.
|
* The running flag.
|
||||||
*/
|
*/
|
||||||
private boolean run;
|
private final boolean run;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The steps.
|
* The steps.
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public final class Item {
|
|||||||
Preconditions.checkArgument(amount >= 0, "Amount cannot be negative.");
|
Preconditions.checkArgument(amount >= 0, "Amount cannot be negative.");
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
this.definition = ItemDefinition.lookup(id);
|
definition = ItemDefinition.lookup(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ public final class Position {
|
|||||||
* @return The y coordinate.
|
* @return The y coordinate.
|
||||||
*/
|
*/
|
||||||
public int getY() {
|
public int getY() {
|
||||||
return (packed >> 15) & 0x7FFF;
|
return packed >> 15 & 0x7FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public final class World {
|
|||||||
/**
|
/**
|
||||||
* The command dispatcher.
|
* The command dispatcher.
|
||||||
*/
|
*/
|
||||||
private CommandDispatcher commandDispatcher = new CommandDispatcher();
|
private final CommandDispatcher commandDispatcher = new CommandDispatcher();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The EventListenerChainSet for this World.
|
* 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.
|
* @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 {
|
public void init(int release, IndexedFileSystem fs, PluginManager manager) throws Exception {
|
||||||
this.releaseNumber = release;
|
releaseNumber = release;
|
||||||
|
|
||||||
ItemDefinitionDecoder itemDecoder = new ItemDefinitionDecoder(fs);
|
ItemDefinitionDecoder itemDecoder = new ItemDefinitionDecoder(fs);
|
||||||
ItemDefinition[] items = itemDecoder.decode();
|
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.
|
* @param entities The entities.
|
||||||
*/
|
*/
|
||||||
private void placeEntities(Entity... 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ public final class Region {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(Region region, Entity entity, EntityUpdateType update) {
|
public void execute(Region region, Entity entity, EntityUpdateType update) {
|
||||||
EntityType type = entity.getEntityType();
|
EntityType type = entity.getEntityType();
|
||||||
if (type != EntityType.PLAYER && type != EntityType.NPC && (type != EntityType.STATIC_OBJECT || update == EntityUpdateType.REMOVE)) {
|
if (type != EntityType.PLAYER && type != EntityType.NPC) {
|
||||||
region.record(entity, update);
|
region.record(entity, update);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ public final class Region {
|
|||||||
/**
|
/**
|
||||||
* The Set containing RegionUpdateMessages which can be sent to add every non-Mob Entity in this Region.
|
* 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);
|
private final List<Map<Entity, RegionUpdateMessage>> snapshots = new ArrayList<>(Position.HEIGHT_LEVELS);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Set containing UpdateOperations.
|
* The Set containing UpdateOperations.
|
||||||
@@ -110,19 +110,20 @@ public final class Region {
|
|||||||
listeners.add(new UpdateRegionListener());
|
listeners.add(new UpdateRegionListener());
|
||||||
|
|
||||||
for (int height = 0; height < Position.HEIGHT_LEVELS; height++) {
|
for (int height = 0; height < Position.HEIGHT_LEVELS; height++) {
|
||||||
snapshots.add(new ArrayList<>());
|
snapshots.add(new HashMap<>());
|
||||||
updates.add(new ArrayList<>(DEFAULT_SET_SIZE));
|
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
|
* 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.
|
* register it to this Region.
|
||||||
*
|
*
|
||||||
* @param entity The Entity.
|
* @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.
|
* @throws IllegalArgumentException If the Entity does not belong in this Region.
|
||||||
*/
|
*/
|
||||||
public void addEntity(Entity entity) {
|
public void addEntity(Entity entity, boolean notify) {
|
||||||
Position position = entity.getPosition();
|
Position position = entity.getPosition();
|
||||||
checkPosition(position);
|
checkPosition(position);
|
||||||
|
|
||||||
@@ -133,17 +134,33 @@ public final class Region {
|
|||||||
System.out.println("Adding entity " + entity + " to " + entity.getPosition());
|
System.out.println("Adding entity " + entity + " to " + entity.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notify) {
|
||||||
notifyListeners(entity, EntityUpdateType.ADD);
|
notifyListeners(entity, EntityUpdateType.ADD);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this Region contains the specified Entity.
|
* Checks if this Region contains the specified Entity.
|
||||||
* <p>
|
* <p/>
|
||||||
* This method operates in constant time.
|
* This method operates in constant time.
|
||||||
*
|
*
|
||||||
* @param entity The Entity.
|
* @param entity The Entity.
|
||||||
* @return {@code true} if this Region contains the Entity, otherwise {@code false}.
|
* @return {@code true} if this Region contains the Entity, otherwise {@code false}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public boolean contains(Entity entity) {
|
public boolean contains(Entity entity) {
|
||||||
Position position = entity.getPosition();
|
Position position = entity.getPosition();
|
||||||
Set<Entity> local = entities.get(position);
|
Set<Entity> local = entities.get(position);
|
||||||
@@ -211,7 +228,7 @@ public final class Region {
|
|||||||
* @return The Set of RegionUpdateMessages.
|
* @return The Set of RegionUpdateMessages.
|
||||||
*/
|
*/
|
||||||
public List<RegionUpdateMessage> getSnapshot(int height) {
|
public List<RegionUpdateMessage> getSnapshot(int height) {
|
||||||
List<RegionUpdateMessage> copy = new ArrayList<>(snapshots.get(height));
|
List<RegionUpdateMessage> copy = new ArrayList<>(snapshots.get(height).values());
|
||||||
Collections.sort(copy);
|
Collections.sort(copy);
|
||||||
return ImmutableList.copyOf(copy);
|
return ImmutableList.copyOf(copy);
|
||||||
}
|
}
|
||||||
@@ -304,7 +321,12 @@ public final class Region {
|
|||||||
int height = entity.getPosition().getHeight();
|
int height = entity.getPosition().getHeight();
|
||||||
|
|
||||||
updates.get(height).add(message);
|
updates.get(height).add(message);
|
||||||
snapshots.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.
|
* @return The array of CollisionFlags.
|
||||||
*/
|
*/
|
||||||
public static CollisionFlag[] forType(EntityType type) {
|
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(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 + ".");
|
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.
|
* 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.
|
* The slot this equipment goes into.
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public final class ItemDefinition {
|
|||||||
/**
|
/**
|
||||||
* The ground actions array.
|
* The ground actions array.
|
||||||
*/
|
*/
|
||||||
private String[] groundActions = new String[5];
|
private final String[] groundActions = new String[5];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item's id.
|
* The item's id.
|
||||||
@@ -124,7 +124,7 @@ public final class ItemDefinition {
|
|||||||
/**
|
/**
|
||||||
* The inventory actions array.
|
* 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.
|
* A flag indicating if this item is members only.
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public final class NpcDefinition {
|
|||||||
/**
|
/**
|
||||||
* An array of interaction options.
|
* An array of interaction options.
|
||||||
*/
|
*/
|
||||||
private String[] interactions = new String[5];
|
private final String[] interactions = new String[5];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the npc.
|
* The name of the npc.
|
||||||
|
|||||||
@@ -535,7 +535,7 @@ public abstract class Mob extends Entity {
|
|||||||
* @param position The position to face.
|
* @param position The position to face.
|
||||||
*/
|
*/
|
||||||
public final void turnTo(Position position) {
|
public final void turnTo(Position position) {
|
||||||
this.facingPosition = position;
|
facingPosition = position;
|
||||||
blockSet.add(SynchronizationBlock.createTurnToPositionBlock(position));
|
blockSet.add(SynchronizationBlock.createTurnToPositionBlock(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public final class Player extends Mob {
|
|||||||
/**
|
/**
|
||||||
* This player's credentials.
|
* This player's credentials.
|
||||||
*/
|
*/
|
||||||
private PlayerCredentials credentials;
|
private final PlayerCredentials credentials;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flag which indicates there are npcs that couldn't be added.
|
* 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.
|
* @param brightness The screen brightness.
|
||||||
*/
|
*/
|
||||||
public void setScreenBrightness(ScreenBrightness brightness) {
|
public void setScreenBrightness(ScreenBrightness brightness) {
|
||||||
this.screenBrightness = brightness;
|
screenBrightness = brightness;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ public final class SkillSet {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
current += (current < max ? 1 : -1);
|
current += current < max ? 1 : -1;
|
||||||
setSkill(id, new Skill(skills[id].getExperience(), current, max));
|
setSkill(id, new Skill(skills[id].getExperience(), current, max));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public final class AttributeMap {
|
|||||||
/**
|
/**
|
||||||
* The map of attribute names to attributes.
|
* 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.
|
* Gets the {@link Attribute} with the specified name.
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ public final class NumericalAttribute extends Attribute<Number> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encode() {
|
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);
|
return Longs.toByteArray(encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
Player player = get();
|
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) {
|
public GameObject(World world, int id, Position position, int type, int orientation) {
|
||||||
super(world, position);
|
super(world, position);
|
||||||
this.packed = id << 8 | (type & 0x3F) << 2 | orientation & 0x3;
|
packed = id << 8 | (type & 0x3F) << 2 | orientation & 0x3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,7 +81,7 @@ public abstract class GameObject extends Entity {
|
|||||||
* @return The type.
|
* @return The type.
|
||||||
*/
|
*/
|
||||||
public int getType() {
|
public int getType() {
|
||||||
return (packed >> 2) & 0x3F;
|
return packed >> 2 & 0x3F;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public final class SimplePathfindingAlgorithm extends PathfindingAlgorithm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Position last = new Position(x, y, height);
|
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);
|
return addVertical(last, target, positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ public final class SimplePathfindingAlgorithm extends PathfindingAlgorithm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Position last = new Position(x, y, height);
|
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);
|
return addHorizontal(last, target, positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public final class EventListenerChainSet {
|
|||||||
public <E extends Event> boolean notify(E event) {
|
public <E extends Event> boolean notify(E event) {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
EventListenerChain<E> chain = (EventListenerChain<E>) chains.get(event.getClass());
|
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.
|
* 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
|
* @author Major
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public final class InterfaceSet {
|
|||||||
/**
|
/**
|
||||||
* A map of open interfaces.
|
* A map of open interfaces.
|
||||||
*/
|
*/
|
||||||
private Map<InterfaceType, Integer> interfaces = new HashMap<>();
|
private final Map<InterfaceType, Integer> interfaces = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current listener.
|
* The current listener.
|
||||||
@@ -150,7 +150,7 @@ public final class InterfaceSet {
|
|||||||
public void openDialogue(DialogueListener listener, int dialogueId) {
|
public void openDialogue(DialogueListener listener, int dialogueId) {
|
||||||
closeAndNotify();
|
closeAndNotify();
|
||||||
|
|
||||||
this.dialogueListener = Optional.ofNullable(listener);
|
dialogueListener = Optional.ofNullable(listener);
|
||||||
this.listener = Optional.ofNullable(listener);
|
this.listener = Optional.ofNullable(listener);
|
||||||
|
|
||||||
interfaces.put(InterfaceType.DIALOGUE, dialogueId);
|
interfaces.put(InterfaceType.DIALOGUE, dialogueId);
|
||||||
@@ -175,7 +175,7 @@ public final class InterfaceSet {
|
|||||||
public void openDialogueOverlay(DialogueListener listener, int dialogueId) {
|
public void openDialogueOverlay(DialogueListener listener, int dialogueId) {
|
||||||
closeAndNotify();
|
closeAndNotify();
|
||||||
|
|
||||||
this.dialogueListener = Optional.ofNullable(listener);
|
dialogueListener = Optional.ofNullable(listener);
|
||||||
this.listener = Optional.ofNullable(listener);
|
this.listener = Optional.ofNullable(listener);
|
||||||
|
|
||||||
interfaces.put(InterfaceType.DIALOGUE, dialogueId);
|
interfaces.put(InterfaceType.DIALOGUE, dialogueId);
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ public interface DialogueListener extends InterfaceListener {
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param button The button interface id.
|
* @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);
|
public boolean buttonClicked(int button);
|
||||||
|
|
||||||
|
|||||||
@@ -540,7 +540,7 @@ public final class Inventory {
|
|||||||
int removed = Math.min(amount, itemAmount);
|
int removed = Math.min(amount, itemAmount);
|
||||||
int remainder = itemAmount - removed;
|
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;
|
return removed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,8 +82,8 @@ public final class NpcMovementTask extends ScheduledTask {
|
|||||||
int currentX = current.getX(), currentY = current.getY();
|
int currentX = current.getX(), currentY = current.getY();
|
||||||
|
|
||||||
boolean negativeX = RANDOM.nextBoolean(), negativeY = RANDOM.nextBoolean();
|
boolean negativeX = RANDOM.nextBoolean(), negativeY = RANDOM.nextBoolean();
|
||||||
int x = RANDOM.nextInt(negativeX ? (currentX - min.getX()) : (max.getX() - currentX));
|
int x = RANDOM.nextInt(negativeX ? currentX - min.getX() : max.getX() - currentX);
|
||||||
int y = RANDOM.nextInt(negativeY ? (currentY - min.getY()) : (max.getY() - currentY));
|
int y = RANDOM.nextInt(negativeY ? currentY - min.getY() : max.getY() - currentY);
|
||||||
|
|
||||||
int dx = negativeX ? -x : x;
|
int dx = negativeX ? -x : x;
|
||||||
int dy = negativeY ? -y : y;
|
int dy = negativeY ? -y : y;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import java.util.Map;
|
|||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Phaser;
|
import java.util.concurrent.Phaser;
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
|
|
||||||
import org.apollo.game.GameService;
|
import org.apollo.game.GameService;
|
||||||
import org.apollo.game.message.impl.RegionUpdateMessage;
|
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.PrePlayerSynchronizationTask;
|
||||||
import org.apollo.game.sync.task.SynchronizationTask;
|
import org.apollo.game.sync.task.SynchronizationTask;
|
||||||
import org.apollo.util.MobRepository;
|
import org.apollo.util.MobRepository;
|
||||||
|
import org.apollo.util.ThreadUtil;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of {@link ClientSynchronizer} which runs in a thread pool. A {@link Phaser} is used to ensure that
|
* 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
|
* 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() {
|
public ParallelClientSynchronizer() {
|
||||||
int processors = Runtime.getRuntime().availableProcessors();
|
executor = Executors.newFixedThreadPool(ThreadUtil.AVAILABLE_PROCESSORS, ThreadUtil.build("ClientSynchronizer"));
|
||||||
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("ClientSynchronizer").build();
|
|
||||||
executor = Executors.newFixedThreadPool(processors, factory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -49,8 +49,7 @@ public final class NpcSynchronizationTask extends SynchronizationTask {
|
|||||||
|
|
||||||
for (Iterator<Npc> it = localNpcs.iterator(); it.hasNext();) {
|
for (Iterator<Npc> it = localNpcs.iterator(); it.hasNext();) {
|
||||||
Npc npc = it.next();
|
Npc npc = it.next();
|
||||||
if (!npc.isActive() || npc.isTeleporting()
|
if (!npc.isActive() || npc.isTeleporting() || npc.getPosition().getLongestDelta(playerPosition) > player.getViewingDistance()) {
|
||||||
|| npc.getPosition().getLongestDelta(playerPosition) > player.getViewingDistance()) {
|
|
||||||
it.remove();
|
it.remove();
|
||||||
segments.add(new RemoveMobSegment());
|
segments.add(new RemoveMobSegment());
|
||||||
} else {
|
} else {
|
||||||
@@ -69,8 +68,7 @@ public final class NpcSynchronizationTask extends SynchronizationTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Position npcPosition = npc.getPosition();
|
Position npcPosition = npc.getPosition();
|
||||||
if (npcPosition.isWithinDistance(playerPosition, player.getViewingDistance()) && !localNpcs.contains(npc)
|
if (npcPosition.isWithinDistance(playerPosition, player.getViewingDistance()) && !localNpcs.contains(npc) && npcPosition.getHeight() == playerPosition.getHeight()) {
|
||||||
&& npcPosition.getHeight() == playerPosition.getHeight()) {
|
|
||||||
localNpcs.add(npc);
|
localNpcs.add(npc);
|
||||||
added++;
|
added++;
|
||||||
npc.turnTo(npc.getFacingPosition());
|
npc.turnTo(npc.getFacingPosition());
|
||||||
|
|||||||
@@ -80,8 +80,7 @@ public final class PlayerSynchronizationTask extends SynchronizationTask {
|
|||||||
int added = 0;
|
int added = 0;
|
||||||
|
|
||||||
MobRepository<Player> repository = player.getWorld().getPlayerRepository();
|
MobRepository<Player> repository = player.getWorld().getPlayerRepository();
|
||||||
for (Iterator<Player> it = repository.iterator(); it.hasNext();) {
|
for (Player other : repository) {
|
||||||
Player other = it.next();
|
|
||||||
if (localPlayers.size() >= 255) {
|
if (localPlayers.size() >= 255) {
|
||||||
player.flagExcessivePlayers();
|
player.flagExcessivePlayers();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
|||||||
player.send(new ClearRegionMessage(position, coordinates));
|
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()) {
|
if (message.isPresent()) {
|
||||||
messages.add(message.get());
|
messages.add(message.get());
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
|||||||
int deltaX = current.getLocalX(last);
|
int deltaX = current.getLocalX(last);
|
||||||
int deltaY = current.getLocalY(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.
|
* {@link Optional#empty()} if no update message is required.
|
||||||
*
|
*
|
||||||
* @param mode The RegionUpdateMode for the Message.
|
* @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 coordinates The {@link RegionCoordinates} of the {@link Region}.
|
||||||
* @param repository The {@link RegionRepository} containing the Regions.
|
* @param repository The {@link RegionRepository} containing the Regions.
|
||||||
* @return The Optional containing the GroupedRegionUpdateMessage.
|
* @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;
|
List<RegionUpdateMessage> messages;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -237,7 +237,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
|
|||||||
messages = updates.get(coordinates);
|
messages = updates.get(coordinates);
|
||||||
if (messages == null) {
|
if (messages == null) {
|
||||||
synchronized (updates) {
|
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);
|
messages = snapshots.get(coordinates);
|
||||||
if (messages == null) {
|
if (messages == null) {
|
||||||
synchronized (snapshots) {
|
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 + ".");
|
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 y = in.readUnsignedShort();
|
||||||
int height = in.readUnsignedByte();
|
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];
|
int[] style = new int[7];
|
||||||
for (int slot = 0; slot < style.length; slot++) {
|
for (int slot = 0; slot < style.length; slot++) {
|
||||||
style[slot] = in.readUnsignedByte();
|
style[slot] = in.readUnsignedByte();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.apollo.login;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
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.release.Release;
|
||||||
import org.apollo.net.session.GameSession;
|
import org.apollo.net.session.GameSession;
|
||||||
import org.apollo.net.session.LoginSession;
|
import org.apollo.net.session.LoginSession;
|
||||||
|
import org.apollo.util.ThreadUtil;
|
||||||
import org.apollo.util.xml.XmlNode;
|
import org.apollo.util.xml.XmlNode;
|
||||||
import org.apollo.util.xml.XmlParser;
|
import org.apollo.util.xml.XmlParser;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link LoginService} manages {@link LoginRequest}s.
|
* 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.
|
* 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}.
|
* The current {@link PlayerSerializer}.
|
||||||
@@ -79,9 +79,6 @@ public final class LoginService extends Service {
|
|||||||
this.serializer = (PlayerSerializer) clazz.getConstructor(World.class).newInstance(world);
|
this.serializer = (PlayerSerializer) clazz.getConstructor(World.class).newInstance(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the login service.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
|
|
||||||
@@ -92,15 +89,44 @@ public final class LoginService extends Service {
|
|||||||
*
|
*
|
||||||
* @param session The session submitting this request.
|
* @param session The session submitting this request.
|
||||||
* @param request The login request.
|
* @param request The login request.
|
||||||
|
* @throws IOException If some I/O exception occurs.
|
||||||
*/
|
*/
|
||||||
public void submitLoadRequest(LoginSession session, LoginRequest request) {
|
public void submitLoadRequest(LoginSession session, LoginRequest request) throws IOException {
|
||||||
Release release = session.getRelease();
|
int response = LoginConstants.STATUS_OK;
|
||||||
if (release.getReleaseNumber() != request.getReleaseNumber()) {
|
|
||||||
// TODO check archive 0 CRCs
|
if (requiresUpdate(session, request)) {
|
||||||
session.handlePlayerLoaderResponse(request, new PlayerLoaderResponse(LoginConstants.STATUS_GAME_UPDATED));
|
response = LoginConstants.STATUS_GAME_UPDATED;
|
||||||
} else {
|
|
||||||
executor.submit(new PlayerLoaderWorker(serializer, session, request));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
@Override
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object message) {
|
public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
|
||||||
try {
|
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();
|
Session session = attribute.get();
|
||||||
|
|
||||||
if (message instanceof HttpRequest || message instanceof JagGrabRequest) {
|
if (message instanceof HttpRequest || message instanceof JagGrabRequest) {
|
||||||
session = new UpdateSession(ctx.channel(), serverContext);
|
session = new UpdateSession(channel, serverContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
@@ -86,11 +87,11 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
switch (handshakeMessage.getServiceId()) {
|
switch (handshakeMessage.getServiceId()) {
|
||||||
case HandshakeConstants.SERVICE_GAME:
|
case HandshakeConstants.SERVICE_GAME:
|
||||||
attribute.set(new LoginSession(ctx, serverContext));
|
attribute.set(new LoginSession(channel, serverContext));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HandshakeConstants.SERVICE_UPDATE:
|
case HandshakeConstants.SERVICE_UPDATE:
|
||||||
attribute.set(new UpdateSession(ctx.channel(), serverContext));
|
attribute.set(new UpdateSession(channel, serverContext));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
|||||||
int read;
|
int read;
|
||||||
if (reader.getLength() == 2) {
|
if (reader.getLength() == 2) {
|
||||||
read = (int) reader.getUnsigned(DataType.SHORT);
|
read = (int) reader.getUnsigned(DataType.SHORT);
|
||||||
int clicks = (read >> 12);
|
int clicks = read >> 12;
|
||||||
int dX = (read >> 6) & 0x3f;
|
int dX = read >> 6 & 0x3f;
|
||||||
int dY = read & 0x3f;
|
int dY = read & 0x3f;
|
||||||
return new FlaggedMouseEventMessage(clicks, dX, dY, true);
|
return new FlaggedMouseEventMessage(clicks, dX, dY, true);
|
||||||
} else if (reader.getLength() == 3) {
|
} else if (reader.getLength() == 3) {
|
||||||
@@ -29,7 +29,7 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
|||||||
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
|
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int clicks = (read >> 19);
|
int clicks = read >> 19;
|
||||||
int x = (read & 0x7f) % 765;
|
int x = (read & 0x7f) % 765;
|
||||||
int y = (read & 0x7f) / 765;
|
int y = (read & 0x7f) / 765;
|
||||||
|
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ public final class GroupedRegionUpdateMessageEncoder extends MessageEncoder<Grou
|
|||||||
@Override
|
@Override
|
||||||
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
||||||
GamePacketBuilder builder = new GamePacketBuilder(60, PacketType.VARIABLE_SHORT);
|
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));
|
builder.put(DataType.BYTE, region.getLocalY(lastKnownRegion));
|
||||||
System.out.println("Grum: local x: " + player.getLocalX(region) + ", local y: " + player.getLocalY(region));
|
builder.put(DataType.BYTE, DataTransformation.NEGATE, region.getLocalX(lastKnownRegion));
|
||||||
builder.put(DataType.BYTE, DataTransformation.NEGATE, player.getLocalX(region));
|
System.out.println("Grum: local x: " + lastKnownRegion.getLocalX(region) + ", local y: " + lastKnownRegion.getLocalY(region));
|
||||||
|
|
||||||
for (RegionUpdateMessage update : message.getMessages()) {
|
for (RegionUpdateMessage update : message.getMessages()) {
|
||||||
System.out.println("==== Sending " + update + " as part of grum");
|
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);
|
int value = (int) reader.getUnsigned(DataType.INT);
|
||||||
|
|
||||||
long delay = (value >> 20) * 50;
|
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 x = cords % 765;
|
||||||
int y = cords / 765;
|
int y = cords / 765;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
|||||||
|
|
||||||
if (reader.getLength() == 2) {
|
if (reader.getLength() == 2) {
|
||||||
read = (int) reader.getUnsigned(DataType.SHORT);
|
read = (int) reader.getUnsigned(DataType.SHORT);
|
||||||
clicks = (read >> 12);
|
clicks = read >> 12;
|
||||||
x = (read >> 6) & 0x3f;
|
x = read >> 6 & 0x3f;
|
||||||
y = read & 0x3f;
|
y = read & 0x3f;
|
||||||
return new FlaggedMouseEventMessage(clicks, x, y, true);
|
return new FlaggedMouseEventMessage(clicks, x, y, true);
|
||||||
} else if (reader.getLength() == 3) {
|
} else if (reader.getLength() == 3) {
|
||||||
@@ -30,7 +30,7 @@ public final class FlaggedMouseEventMessageDecoder extends MessageDecoder<Flagge
|
|||||||
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
|
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
clicks = (read >> 19);
|
clicks = read >> 19;
|
||||||
x = (read & 0x7f) % 765;
|
x = (read & 0x7f) % 765;
|
||||||
y = (read & 0x7f) / 765;
|
y = (read & 0x7f) / 765;
|
||||||
return new FlaggedMouseEventMessage(clicks, x, y, false);
|
return new FlaggedMouseEventMessage(clicks, x, y, false);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public final class GroupedRegionUpdateMessageEncoder extends MessageEncoder<Grou
|
|||||||
@Override
|
@Override
|
||||||
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
public GamePacket encode(GroupedRegionUpdateMessage message) {
|
||||||
GamePacketBuilder builder = new GamePacketBuilder(183, PacketType.VARIABLE_SHORT);
|
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, region.getLocalX(base));
|
||||||
builder.put(DataType.BYTE, DataTransformation.ADD, region.getLocalY(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);
|
int value = (int) reader.getUnsigned(DataType.INT);
|
||||||
|
|
||||||
long delay = (value >> 20) * 50;
|
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 x = cords % 765;
|
||||||
int y = 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.MessageHandlerChainSet;
|
||||||
import org.apollo.game.message.impl.LogoutMessage;
|
import org.apollo.game.message.impl.LogoutMessage;
|
||||||
import org.apollo.game.model.entity.Player;
|
import org.apollo.game.model.entity.Player;
|
||||||
import org.apollo.util.CollectionUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A game session.
|
* A game session.
|
||||||
@@ -84,13 +83,14 @@ public final class GameSession extends Session {
|
|||||||
* @param chainSet The {@link MessageHandlerChainSet}
|
* @param chainSet The {@link MessageHandlerChainSet}
|
||||||
*/
|
*/
|
||||||
public void handlePendingMessages(MessageHandlerChainSet chainSet) {
|
public void handlePendingMessages(MessageHandlerChainSet chainSet) {
|
||||||
CollectionUtil.pollAll(messageQueue, message -> {
|
Message message;
|
||||||
|
while ((message = messageQueue.poll()) != null) {
|
||||||
try {
|
try {
|
||||||
chainSet.notify(player, message);
|
chainSet.notify(player, message);
|
||||||
} catch (Exception reason) {
|
} catch (Exception reason) {
|
||||||
logger.log(Level.SEVERE, "Uncaught exception thrown while handling message: " + message, 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.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.apollo.ServerContext;
|
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.game.model.entity.Player;
|
||||||
import org.apollo.io.player.PlayerLoaderResponse;
|
import org.apollo.io.player.PlayerLoaderResponse;
|
||||||
import org.apollo.login.LoginService;
|
import org.apollo.login.LoginService;
|
||||||
import org.apollo.net.ApolloHandler;
|
|
||||||
import org.apollo.net.NetworkConstants;
|
import org.apollo.net.NetworkConstants;
|
||||||
import org.apollo.net.codec.game.GameMessageDecoder;
|
import org.apollo.net.codec.game.GameMessageDecoder;
|
||||||
import org.apollo.net.codec.game.GameMessageEncoder;
|
import org.apollo.net.codec.game.GameMessageEncoder;
|
||||||
@@ -32,26 +31,20 @@ import org.apollo.security.IsaacRandomPair;
|
|||||||
*/
|
*/
|
||||||
public final class LoginSession extends Session {
|
public final class LoginSession extends Session {
|
||||||
|
|
||||||
/**
|
|
||||||
* The context of the {@link ApolloHandler}.
|
|
||||||
*/
|
|
||||||
private final ChannelHandlerContext channelContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The server context.
|
* The server context.
|
||||||
*/
|
*/
|
||||||
private final ServerContext serverContext;
|
private final ServerContext context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a login session for the specified channel.
|
* Creates a login session for the specified channel.
|
||||||
*
|
*
|
||||||
* @param ctx The context of the {@link ApolloHandler}.
|
* @param channel The channel.
|
||||||
* @param serverContext The server context.
|
* @param context The server context.
|
||||||
*/
|
*/
|
||||||
public LoginSession(ChannelHandlerContext ctx, ServerContext serverContext) {
|
public LoginSession(Channel channel, ServerContext context) {
|
||||||
super(ctx.channel());
|
super(channel);
|
||||||
this.channelContext = ctx;
|
this.context = context;
|
||||||
this.serverContext = serverContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.
|
* Handles a login request.
|
||||||
*
|
*
|
||||||
* @param request The login request.
|
* @param request The login request.
|
||||||
|
* @throws IOException If some I/O exception occurs.
|
||||||
*/
|
*/
|
||||||
private void handleLoginRequest(LoginRequest request) {
|
private void handleLoginRequest(LoginRequest request) throws IOException {
|
||||||
LoginService loginService = serverContext.getService(LoginService.class);
|
LoginService loginService = context.getService(LoginService.class);
|
||||||
loginService.submitLoadRequest(this, request);
|
loginService.submitLoadRequest(this, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +70,7 @@ public final class LoginSession extends Session {
|
|||||||
* @param response The response.
|
* @param response The response.
|
||||||
*/
|
*/
|
||||||
public void handlePlayerLoaderResponse(LoginRequest request, PlayerLoaderResponse response) {
|
public void handlePlayerLoaderResponse(LoginRequest request, PlayerLoaderResponse response) {
|
||||||
GameService service = serverContext.getService(GameService.class);
|
GameService service = context.getService(GameService.class);
|
||||||
Channel channel = getChannel();
|
Channel channel = getChannel();
|
||||||
|
|
||||||
Optional<Player> optional = response.getPlayer();
|
Optional<Player> optional = response.getPlayer();
|
||||||
@@ -96,14 +81,14 @@ public final class LoginSession extends Session {
|
|||||||
Player player = optional.get();
|
Player player = optional.get();
|
||||||
rights = player.getPrivilegeLevel().toInteger();
|
rights = player.getPrivilegeLevel().toInteger();
|
||||||
|
|
||||||
GameSession session = new GameSession(channel, serverContext, player);
|
GameSession session = new GameSession(channel, context, player);
|
||||||
RegistrationStatus registration = service.registerPlayer(player, session);
|
RegistrationStatus registration = service.registerPlayer(player, session);
|
||||||
|
|
||||||
if (registration != RegistrationStatus.OK) {
|
if (registration != RegistrationStatus.OK) {
|
||||||
optional = Optional.empty();
|
optional = Optional.empty();
|
||||||
rights = 0;
|
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()) {
|
if (optional.isPresent()) {
|
||||||
IsaacRandomPair randomPair = request.getRandomPair();
|
IsaacRandomPair randomPair = request.getRandomPair();
|
||||||
Release release = serverContext.getRelease();
|
Release release = context.getRelease();
|
||||||
|
|
||||||
channel.pipeline().addFirst("messageEncoder", new GameMessageEncoder(release));
|
channel.pipeline().addFirst("messageEncoder", new GameMessageEncoder(release));
|
||||||
channel.pipeline().addBefore("messageEncoder", "gameEncoder", new GamePacketEncoder(randomPair.getEncodingRandom()));
|
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().addAfter("gameDecoder", "messageDecoder", new GameMessageDecoder(release));
|
||||||
|
|
||||||
channel.pipeline().remove("loginDecoder");
|
channel.pipeline().remove("loginDecoder");
|
||||||
channel.pipeline().remove("loginEncoder");
|
channel.pipeline().remove("loginEncoder");
|
||||||
|
|
||||||
channelContext.attr(NetworkConstants.SESSION_KEY).set(optional.get().getSession());
|
channel.attr(NetworkConstants.SESSION_KEY).set(optional.get().getSession());
|
||||||
} else {
|
} else {
|
||||||
future.addListener(ChannelFutureListener.CLOSE);
|
future.addListener(ChannelFutureListener.CLOSE);
|
||||||
}
|
}
|
||||||
@@ -135,7 +120,7 @@ public final class LoginSession extends Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(Object message) {
|
public void messageReceived(Object message) throws Exception {
|
||||||
if (message.getClass() == LoginRequest.class) {
|
if (message.getClass() == LoginRequest.class) {
|
||||||
handleLoginRequest((LoginRequest) message);
|
handleLoginRequest((LoginRequest) message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ public abstract class Session {
|
|||||||
* Processes a message received from the channel.
|
* Processes a message received from the channel.
|
||||||
*
|
*
|
||||||
* @param message The message.
|
* @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 {
|
do {
|
||||||
p = BigInteger.probablePrime(BIT_COUNT / 2, random);
|
p = BigInteger.probablePrime(BIT_COUNT / 2, random);
|
||||||
q = 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);
|
modulus = p.multiply(q);
|
||||||
privateKey = publicKey.modInverse(phi);
|
privateKey = publicKey.modInverse(phi);
|
||||||
} while (modulus.bitLength() != BIT_COUNT || privateKey.bitLength() != BIT_COUNT
|
} while (modulus.bitLength() != BIT_COUNT || privateKey.bitLength() != BIT_COUNT || !phi.gcd(publicKey).equals(BigInteger.ONE));
|
||||||
|| !phi.gcd(publicKey).equals(BigInteger.ONE));
|
|
||||||
|
|
||||||
System.out.println("modulus: " + modulus);
|
System.out.println("modulus: " + modulus);
|
||||||
System.out.println("public key: " + publicKey);
|
System.out.println("public key: " + publicKey);
|
||||||
|
|||||||
@@ -23,27 +23,18 @@ public final class TextUtil {
|
|||||||
* @return The string with correct capitalization.
|
* @return The string with correct capitalization.
|
||||||
*/
|
*/
|
||||||
public static String capitalize(String str) {
|
public static String capitalize(String str) {
|
||||||
char[] chars = str.toCharArray();
|
boolean capitalize = true;
|
||||||
boolean sentenceStart = true;
|
StringBuilder bldr = new StringBuilder(str);
|
||||||
for (int i = 0; i < chars.length; i++) {
|
for (int index = 0, length = str.length(); index < length; index++) {
|
||||||
char c = chars[i];
|
char character = bldr.charAt(index);
|
||||||
if (sentenceStart) {
|
if (character == '.' || character == '!' || character == '?') {
|
||||||
if (c >= 'a' && c <= 'z') {
|
capitalize = true;
|
||||||
chars[i] -= 0x20;
|
} else if (capitalize && !Character.isWhitespace(character)) {
|
||||||
sentenceStart = false;
|
bldr.setCharAt(index, Character.toUpperCase(character));
|
||||||
} else if (c >= 'A' && c <= 'Z') {
|
capitalize = false;
|
||||||
sentenceStart = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (c >= 'A' && c <= 'Z') {
|
|
||||||
chars[i] += 0x20;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c == '.' || c == '!' || c == '?') {
|
return bldr.toString();
|
||||||
sentenceStart = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new String(chars, 0, chars.length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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.
|
* A set of all author names.
|
||||||
*/
|
*/
|
||||||
private SortedSet<String> authors = new TreeSet<>();
|
private final SortedSet<String> authors = new TreeSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The plugin context.
|
* The plugin context.
|
||||||
@@ -164,8 +164,7 @@ public final class PluginManager {
|
|||||||
* @throws DependencyException If a dependency error occurs.
|
* @throws DependencyException If a dependency error occurs.
|
||||||
* @throws IOException If an I/O error occurs.
|
* @throws IOException If an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
private void start(PluginEnvironment env, PluginMetaData plugin, Map<String, PluginMetaData> plugins,
|
private void start(PluginEnvironment env, PluginMetaData plugin, Map<String, PluginMetaData> plugins, Set<PluginMetaData> started) throws DependencyException, IOException {
|
||||||
Set<PluginMetaData> started) throws DependencyException, IOException {
|
|
||||||
// TODO check for cyclic dependencies! this way just won't cut it, we need an exception
|
// TODO check for cyclic dependencies! this way just won't cut it, we need an exception
|
||||||
if (started.contains(plugin)) {
|
if (started.contains(plugin)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public final class XmlParser {
|
|||||||
/**
|
/**
|
||||||
* The stack of nodes, used when traversing the document and going through child nodes.
|
* 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.
|
* The current root node.
|
||||||
|
|||||||
Reference in New Issue
Block a user