Various changes.

This commit is contained in:
Major-
2013-11-19 20:17:58 +00:00
parent fb422bcfe1
commit f40f885008
92 changed files with 965 additions and 419 deletions
+10
View File
@@ -0,0 +1,10 @@
require 'java'
java_import 'org.apollo.game.model.Player'
java_import 'org.apollo.game.event.impl.PositionEvent'
java_import 'org.apollo.game.event.impl.SetTileItemEvent'
on :command, :drop, RIGHTS_ADMIN do |player, command|
player.send(PositionEvent.new(player.position, player.position))
player.send(SetTileItemEvent.new(70, 1))
end
+6
View File
@@ -0,0 +1,6 @@
require 'java'
java_import 'org.apollo.game.model.Player'
java_import 'org.apollo.game.event.impl.PositionEvent'
java_import 'org.apollo.game.event.impl.SetTileItemEvent'
+8 -1
View File
@@ -1,7 +1,14 @@
require 'java' require 'java'
java_import 'org.apollo.game.model.Animation' java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.World'
SERVER_RELEASE = World.world.release_number
on :command, :hello do |player, command| on :command, :hello do |player, command|
player.play_animation Animation::WAVE player.play_animation Animation::WAVE
player.send_message "Hello, World!" player.send_message("Hello, World!")
end end
on :command, :release do |player, command|
player.send_message("This server is currently running the #{SERVER_RELEASE} release.")
end
@@ -101,9 +101,9 @@ public final class IsaacRandom {
/** /**
* Initialises this random number generator. * Initialises this random number generator.
* *
* @param flag Set to {@code true} if a seed was passed to the constructor. * @param hasSeed Set to {@code true} if a seed was passed to the constructor.
*/ */
private void init(boolean flag) { private void init(boolean hasSeed) {
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,7 +136,7 @@ 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 (flag) { if (hasSeed) {
a += rsl[i]; a += rsl[i];
b += rsl[i + 1]; b += rsl[i + 1];
c += rsl[i + 2]; c += rsl[i + 2];
@@ -180,7 +180,7 @@ public final class IsaacRandom {
mem[i + 7] = h; mem[i + 7] = h;
} }
if (flag) { /* second pass makes all of seed affect all of mem */ 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 += mem[i];
b += mem[i + 1]; b += mem[i + 1];
@@ -302,4 +302,4 @@ public final class IsaacRandom {
return rsl[count]; return rsl[count];
} }
} }
@@ -1,5 +1,4 @@
/** /**
* Contains a Java implementation of Bob Jenkins' ISAAC algorithm. * Contains a Java implementation of Bob Jenkins' ISAAC algorithm.
*/ */
package net.burtleburtle.bob.rand; package net.burtleburtle.bob.rand;
+1 -2
View File
@@ -44,9 +44,8 @@ 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) {
Server server = null;
try { try {
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());
SocketAddress service = new InetSocketAddress(NetworkConstants.SERVICE_PORT); SocketAddress service = new InetSocketAddress(NetworkConstants.SERVICE_PORT);
+1 -1
View File
@@ -35,4 +35,4 @@ public abstract class Service {
*/ */
public abstract void start(); public abstract void start();
} }
+12 -5
View File
@@ -1,6 +1,7 @@
package org.apollo; package org.apollo;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -8,6 +9,7 @@ import java.util.logging.Logger;
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;
/** /**
* A class which manages {@link Service}s. * A class which manages {@link Service}s.
@@ -50,10 +52,15 @@ public final class ServiceManager {
/** /**
* Initializes this service manager. * Initializes this service manager.
* *
* @throws Exception If an error occurs. * @throws SAXException If the service XML file could not be parsed.
* @throws IOException If the file could not be accessed.
* @throws IllegalAccessException If the service could not be accessed.
* @throws InstantiationException If the service could not be instantiated.
* @throws ClassNotFoundException If the service could not be found.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void init() throws Exception { private void init() throws SAXException, IOException, InstantiationException, IllegalAccessException,
ClassNotFoundException {
logger.info("Registering services..."); logger.info("Registering services...");
XmlParser parser = new XmlParser(); XmlParser parser = new XmlParser();
@@ -67,16 +74,16 @@ public final class ServiceManager {
} }
if (!rootNode.getName().equals("services")) { if (!rootNode.getName().equals("services")) {
throw new Exception("unexpected name of root node"); throw new IOException("unexpected name of root node");
} }
for (XmlNode childNode : rootNode) { for (XmlNode childNode : rootNode) {
if (!childNode.getName().equals("service")) { if (!childNode.getName().equals("service")) {
throw new Exception("unexpected name of child node"); throw new IOException("unexpected name of child node");
} }
if (!childNode.hasValue()) { if (!childNode.hasValue()) {
throw new Exception("child node must have a value!"); throw new IOException("child node must have a value!");
} }
Class<? extends Service> clazz = (Class<? extends Service>) Class.forName(childNode.getValue()); Class<? extends Service> clazz = (Class<? extends Service>) Class.forName(childNode.getValue());
+13 -14
View File
@@ -40,10 +40,10 @@ public final class IndexedFileSystem implements Closeable {
* Creates the file system with the specified base directory. * Creates the file system with the specified base directory.
* *
* @param base The base directory. * @param base The base directory.
* @param readOnly A flag indicating if the file system will be read only. * @param readOnly Indicates whether the file system will be read only or not.
* @throws Exception If the file system is invalid. * @throws FileNotFoundException If the data files could not be found.
*/ */
public IndexedFileSystem(File base, boolean readOnly) throws Exception { public IndexedFileSystem(File base, boolean readOnly) throws FileNotFoundException {
this.readOnly = readOnly; this.readOnly = readOnly;
detectLayout(base); detectLayout(base);
} }
@@ -69,9 +69,9 @@ public final class IndexedFileSystem implements Closeable {
* Automatically detect the layout of the specified directory. * Automatically detect the layout of the specified directory.
* *
* @param base The base directory. * @param base The base directory.
* @throws Exception If the file system is invalid. * @throws FileNotFoundException If the data files could not be found.
*/ */
private void detectLayout(File base) throws Exception { private void detectLayout(File base) throws FileNotFoundException {
int indexCount = 0; int indexCount = 0;
for (int index = 0; index < indices.length; index++) { for (int index = 0; index < indices.length; index++) {
File f = new File(base.getAbsolutePath() + "/main_file_cache.idx" + index); File f = new File(base.getAbsolutePath() + "/main_file_cache.idx" + index);
@@ -81,7 +81,7 @@ public final class IndexedFileSystem implements Closeable {
} }
} }
if (indexCount <= 0) { if (indexCount <= 0) {
throw new Exception("No index file(s) present"); throw new FileNotFoundException("No index file(s) present");
} }
File oldEngineData = new File(base.getAbsolutePath() + "/main_file_cache.dat"); File oldEngineData = new File(base.getAbsolutePath() + "/main_file_cache.dat");
@@ -91,7 +91,7 @@ public final class IndexedFileSystem implements Closeable {
} else if (newEngineData.exists() && !oldEngineData.isDirectory()) { } else if (newEngineData.exists() && !oldEngineData.isDirectory()) {
data = new RandomAccessFile(newEngineData, readOnly ? "r" : "rw"); data = new RandomAccessFile(newEngineData, readOnly ? "r" : "rw");
} else { } else {
throw new Exception("No data file present"); throw new FileNotFoundException("No data file present");
} }
} }
@@ -99,7 +99,7 @@ public final class IndexedFileSystem implements Closeable {
* Gets the CRC table. * Gets the CRC table.
* *
* @return The CRC table. * @return The CRC table.
* @throws IOException If an I/O erorr occurs. * @throws IOException If an I/O error occurs.
*/ */
public ByteBuffer getCrcTable() throws IOException { public ByteBuffer getCrcTable() throws IOException {
if (readOnly) { if (readOnly) {
@@ -146,9 +146,8 @@ public final class IndexedFileSystem implements Closeable {
crcTable = buf.asReadOnlyBuffer(); crcTable = buf.asReadOnlyBuffer();
return crcTable.duplicate(); return crcTable.duplicate();
} }
} else {
throw new IOException("cannot get CRC table from a writable file system");
} }
throw new IOException("cannot get CRC table from a writable file system");
} }
/** /**
@@ -250,7 +249,7 @@ public final class IndexedFileSystem implements Closeable {
*/ */
private int getFileCount(int type) throws IOException { private int getFileCount(int type) throws IOException {
if (type < 0 || type >= indices.length) { if (type < 0 || type >= indices.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("file type out of bounds");
} }
RandomAccessFile indexFile = indices[type]; RandomAccessFile indexFile = indices[type];
@@ -269,7 +268,7 @@ public final class IndexedFileSystem implements Closeable {
private Index getIndex(FileDescriptor fd) throws IOException { private Index getIndex(FileDescriptor fd) throws IOException {
int index = fd.getType(); int index = fd.getType();
if (index < 0 || index >= indices.length) { if (index < 0 || index >= indices.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("file descriptor type out of bounds");
} }
byte[] buffer = new byte[FileSystemConstants.INDEX_SIZE]; byte[] buffer = new byte[FileSystemConstants.INDEX_SIZE];
@@ -280,7 +279,7 @@ public final class IndexedFileSystem implements Closeable {
indexFile.seek(ptr); indexFile.seek(ptr);
indexFile.readFully(buffer); indexFile.readFully(buffer);
} else { } else {
throw new FileNotFoundException(); throw new FileNotFoundException("could not find find index");
} }
} }
@@ -296,4 +295,4 @@ public final class IndexedFileSystem implements Closeable {
return readOnly; return readOnly;
} }
} }
+2 -2
View File
@@ -93,7 +93,7 @@ public final class Archive {
return entry; return entry;
} }
} }
throw new FileNotFoundException(); throw new FileNotFoundException("could not find entry: " + name);
} }
} }
+13 -5
View File
@@ -1,6 +1,7 @@
package org.apollo.game; package org.apollo.game;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
@@ -21,6 +22,7 @@ import org.apollo.net.session.GameSession;
import org.apollo.util.NamedThreadFactory; import org.apollo.util.NamedThreadFactory;
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;
/** /**
* 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.
@@ -88,9 +90,15 @@ public final class GameService extends Service {
/** /**
* Initializes the game service. * Initializes the game service.
* *
* @throws Exception If an error occurs. * @throws IOException If there is an error with the file (e.g. does not exist, cannot be read, does not contain
* valid nodes).
* @throws SAXException If there is an error parsing the file.
* @throws ClassNotFoundException If an event handler could not be found.
* @throws InstantiationException If an event handler could not be instantiated.
* @throws IllegalAccessException If an event handler could not be accessed.
*/ */
private void init() throws Exception { private void init() throws IOException, SAXException, ClassNotFoundException, InstantiationException,
IllegalAccessException {
InputStream is = new FileInputStream("data/events.xml"); InputStream is = new FileInputStream("data/events.xml");
try { try {
EventHandlerChainParser chainGroupParser = new EventHandlerChainParser(is); EventHandlerChainParser chainGroupParser = new EventHandlerChainParser(is);
@@ -105,12 +113,12 @@ public final class GameService extends Service {
XmlNode rootNode = parser.parse(is); XmlNode rootNode = parser.parse(is);
if (!rootNode.getName().equals("synchronizer")) { if (!rootNode.getName().equals("synchronizer")) {
throw new Exception("Invalid root node name."); throw new IOException("Invalid root node name.");
} }
XmlNode activeNode = rootNode.getChild("active"); XmlNode activeNode = rootNode.getChild("active");
if (activeNode == null || !activeNode.hasValue()) { if (activeNode == null || !activeNode.hasValue()) {
throw new Exception("No active node/value."); throw new IOException("No active node/value.");
} }
Class<?> clazz = Class.forName(activeNode.getValue()); Class<?> clazz = Class.forName(activeNode.getValue());
@@ -186,4 +194,4 @@ public final class GameService extends Service {
oldPlayers.add(player); oldPlayers.add(player);
} }
} }
@@ -36,7 +36,7 @@ public final class BankEventHandler extends EventHandler<ItemActionEvent> {
case 5: case 5:
return -1; return -1;
} }
throw new IllegalArgumentException(); throw new IllegalArgumentException("option out of bounds");
} }
/** /**
@@ -90,4 +90,4 @@ public final class BankEventHandler extends EventHandler<ItemActionEvent> {
} }
} }
} }
@@ -3,10 +3,83 @@ package org.apollo.game.event.impl;
import org.apollo.game.event.Event; import org.apollo.game.event.Event;
/** /**
* An{@link Event} sent when the player has clicked on something. TODO * An {@link Event} sent when the player clicks with their mouse (or mousekeys etc).
* *
* @author Major * @author Major
*/ */
public class MouseClickEvent extends Event { public class MouseClickEvent extends Event {
/**
* The number of clicks on this point (i.e. the point ({@link #x}, {@link #y})).
*/
private final int clickCount;
/**
* The x coordinate of the mouse click.
*/
private final int x;
/**
* The y coordinate of the mouse click.
*/
private final int y;
/**
* Indicates whether the {@link #x} and {@link #y} values represent the deviation from the last click or an actual
* point.
*/
private final boolean delta;
/**
* Creates a new mouse click event.
*
* @param clickCount The number of clicks on this point.
* @param x The x coordinate of the mouse click.
* @param y The y coordinate of the mouse click.
* @param delta If the coordinates represent a change in x/y, rather than the values themselves.
*/
public MouseClickEvent(int clickCount, int x, int y, boolean delta) {
this.clickCount = clickCount;
this.x = x;
this.y = y;
this.delta = delta;
}
/**
* Gets the number of clicks on this point - maximum value of 2047.
*
* @return The number of clicks.
*/
public int getClickCount() {
return clickCount;
}
/**
* The x coordinate of the click.
*
* @return The x coordinate.
*/
public int getX() {
return x;
}
/**
* The y coordinate of the click.
*
* @return The y coordinate.
*/
public int getY() {
return y;
}
/**
* Gets the value indicating whether the {@link #x} and {@link #y} values represent the deviation from the last
* click or an actual point.
*
* @return The value.
*/
public boolean getDelta() {
return delta;
}
} }
@@ -22,7 +22,7 @@ public final class PositionEvent extends Event {
private final Position position; private final Position position;
/** /**
* Creates a new focus position event. * Creates a new position event.
* *
* @param base The base from which the position is being focused on. * @param base The base from which the position is being focused on.
* @param position The position to focus on. * @param position The position to focus on.
@@ -0,0 +1,35 @@
package org.apollo.game.event.impl;
import org.apollo.game.event.Event;
/**
* An {@link Event} sent to the client to update the remaining run energy value.
*
* @author Major
*/
public class UpdateRunEnergyEvent extends Event {
/**
* The run energy.
*/
private final int energy;
/**
* Creates a new update run energy event.
*
* @param energy The energy.
*/
public UpdateRunEnergyEvent(int energy) {
this.energy = energy;
}
/**
* Gets the amount of run energy.
*
* @return The energy.
*/
public int getEnergy() {
return energy;
}
}
+4 -8
View File
@@ -14,7 +14,7 @@ public final class Appearance {
42 }, new int[5]); 42 }, new int[5]);
/** /**
* The array of clothing/skin colours. * The array of clothing/skin colors.
*/ */
private final int[] colors; private final int[] colors;
@@ -37,7 +37,7 @@ public final class Appearance {
*/ */
public Appearance(Gender gender, int[] style, int[] colors) { public Appearance(Gender gender, int[] style, int[] colors) {
if (gender == null || style == null || colors == null) { if (gender == null || style == null || colors == null) {
throw new NullPointerException(); throw new NullPointerException("no arguments can be null");
} }
if (style.length != 7) { if (style.length != 7) {
throw new IllegalArgumentException("the style array must have 7 elements"); throw new IllegalArgumentException("the style array must have 7 elements");
@@ -74,11 +74,7 @@ public final class Appearance {
* @return The player's styles. * @return The player's styles.
*/ */
public int[] getStyle() { public int[] getStyle() {
/* // 0 = head 1 = chin/beard 2 = chest 3 = arms 4 = hands 5 = legs 6 = feet
* Info on the elements of the array itself:
*
* 0 = head 1 = chin/beard 2 = chest 3 = arms 4 = hands 5 = legs 6 = feet
*/
return style; return style;
} }
@@ -100,4 +96,4 @@ public final class Appearance {
return gender == Gender.MALE; return gender == Gender.MALE;
} }
} }
+7 -16
View File
@@ -17,12 +17,12 @@ import org.apollo.util.CharacterRepository;
* *
* @author Graham * @author Graham
*/ */
public abstract class Character { public abstract class Character implements Entity {
/** /**
* The character's current action. * The character's current action.
*/ */
private Action<?> action; // TODO private Action<?> action;
/** /**
* The character's bank. * The character's bank.
@@ -130,14 +130,10 @@ public abstract class Character {
*/ */
public Direction[] getDirections() { public Direction[] getDirections() {
if (firstDirection != Direction.NONE) { if (firstDirection != Direction.NONE) {
if (secondDirection != Direction.NONE) { return secondDirection == Direction.NONE ? new Direction[] { firstDirection } : new Direction[] {
return new Direction[] { firstDirection, secondDirection }; firstDirection, secondDirection };
} else {
return new Direction[] { firstDirection };
}
} else {
return Direction.EMPTY_DIRECTION_ARRAY;
} }
return Direction.EMPTY_DIRECTION_ARRAY;
} }
/** /**
@@ -205,11 +201,7 @@ public abstract class Character {
return definition; return definition;
} }
/** @Override
* Gets the position of this character.
*
* @return The position of this character.
*/
public Position getPosition() { public Position getPosition() {
return position; return position;
} }
@@ -365,8 +357,7 @@ public abstract class Character {
stopAction(); stopAction();
} }
this.action = action; this.action = action;
World.getWorld().schedule(action); return World.getWorld().schedule(action);
return true; // TODO maybe this should be incorporated into the action class itself?
} }
/** /**
+25
View File
@@ -0,0 +1,25 @@
package org.apollo.game.model;
/**
* Represents an in-game entity, such as a character, object, projectile etc.
*
* @author Major
*/
public interface Entity {
/**
* Gets the {@link EntityType} of this entity.
*
* @return The type.
*/
public EntityType getEntityType();
/**
* Gets the position of this entity.
*
* @return The position.
*/
public Position getPosition();
}
+40
View File
@@ -0,0 +1,40 @@
package org.apollo.game.model;
/**
* Represents a type of {@link Entity}.
*
* @author Major
*/
public enum EntityType {
/**
* An item that has been dropped on the ground.
*/
DROPPED_ITEM,
/**
* A temporary object.
*/
GAME_OBJECT,
/**
* An npc.
*/
NPC,
/**
* A player.
*/
PLAYER,
/**
* A projectile (e.g. an arrow).
*/
PROJECTILE,
/**
* A permanent object appearing on the map.
*/
STATIC_OBJECT;
}
@@ -69,4 +69,4 @@ public final class EquipmentConstants {
} }
} }
+1 -1
View File
@@ -40,4 +40,4 @@ public enum Gender {
return intValue; return intValue;
} }
} }
+1 -1
View File
@@ -86,4 +86,4 @@ public final class Graphic {
return id; return id;
} }
} }
@@ -1,41 +0,0 @@
package org.apollo.game.model;
/**
* Represents the different types of interfaces.
*
* @author Graham
*/
public enum InterfaceType {
/**
* A dialogue is an interface which appears in the chat box.
*/
DIALOGUE,
/**
* An interface which is shown behind a fullscreen window.
*/
FULLSCREEN_BACKGROUND,
/**
* An interface which is shown in full screen mode.
*/
FULLSCREEN_WINDOW,
/**
* An overlay is an interface which occupies the game screen like a window, however, you can walk around and perform
* actions still.
*/
OVERLAY,
/**
* An interface which displays over the inventory area.
*/
SIDEBAR,
/**
* A window is an interface which occupies the game screen.
*/
WINDOW;
}
@@ -29,4 +29,4 @@ public final class InventoryConstants {
} }
} }
+5
View File
@@ -36,6 +36,11 @@ public class Npc extends Character {
this.definition = definition; this.definition = definition;
} }
@Override
public EntityType getEntityType() {
return EntityType.NPC;
}
/** /**
* Gets this npc's {@link NpcDefinition} * Gets this npc's {@link NpcDefinition}
* *
+48 -8
View File
@@ -1,8 +1,8 @@
package org.apollo.game.model; package org.apollo.game.model;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List; import java.util.List;
import java.util.Queue;
import org.apollo.game.event.Event; import org.apollo.game.event.Event;
import org.apollo.game.event.impl.ConfigEvent; import org.apollo.game.event.impl.ConfigEvent;
@@ -11,6 +11,9 @@ import org.apollo.game.event.impl.LogoutEvent;
import org.apollo.game.event.impl.ServerMessageEvent; import org.apollo.game.event.impl.ServerMessageEvent;
import org.apollo.game.event.impl.SetWidgetTextEvent; import org.apollo.game.event.impl.SetWidgetTextEvent;
import org.apollo.game.event.impl.SwitchTabInterfaceEvent; import org.apollo.game.event.impl.SwitchTabInterfaceEvent;
import org.apollo.game.event.impl.UpdateRunEnergyEvent;
import org.apollo.game.model.inter.InterfaceConstants;
import org.apollo.game.model.inter.InterfaceSet;
import org.apollo.game.model.inter.bank.BankConstants; import org.apollo.game.model.inter.bank.BankConstants;
import org.apollo.game.model.inv.AppearanceInventoryListener; import org.apollo.game.model.inv.AppearanceInventoryListener;
import org.apollo.game.model.inv.FullInventoryListener; import org.apollo.game.model.inv.FullInventoryListener;
@@ -22,6 +25,7 @@ import org.apollo.game.model.skill.SynchronizationSkillListener;
import org.apollo.game.sync.block.SynchronizationBlock; import org.apollo.game.sync.block.SynchronizationBlock;
import org.apollo.net.session.GameSession; import org.apollo.net.session.GameSession;
import org.apollo.security.PlayerCredentials; import org.apollo.security.PlayerCredentials;
import org.apollo.util.Point;
/** /**
* A {@link Player} is a {@link Character} that a user is controlling. * A {@link Player} is a {@link Character} that a user is controlling.
@@ -98,6 +102,11 @@ public final class Player extends Character {
*/ */
private Appearance appearance = Appearance.DEFAULT_APPEARANCE; private Appearance appearance = Appearance.DEFAULT_APPEARANCE;
/**
* A {@link List} of this player's mouse clicks.
*/
private Deque<Point> clicks = new ArrayDeque<Point>();
/** /**
* The player's credentials. * The player's credentials.
*/ */
@@ -151,7 +160,7 @@ public final class Player extends Character {
/** /**
* A temporary queue of events sent during the login process. * A temporary queue of events sent during the login process.
*/ */
private final Queue<Event> queuedEvents = new ArrayDeque<Event>(); private final Deque<Event> queuedEvents = new ArrayDeque<Event>();
/** /**
* A flag indicating if the region changed in the last cycle. * A flag indicating if the region changed in the last cycle.
@@ -195,6 +204,16 @@ public final class Player extends Character {
this.credentials = credentials; this.credentials = credentials;
} }
/**
* Adds a click, represented by a {@link Point}, to the {@link List} of clicks.
*
* @param point The point.
* @return {@code true} if the point was added successfully.
*/
public boolean addClick(Point point) {
return clicks.add(point);
}
/** /**
* Decrements this player's viewing distance if it is greater than 1. * Decrements this player's viewing distance if it is greater than 1.
*/ */
@@ -227,6 +246,15 @@ public final class Player extends Character {
return appearance; return appearance;
} }
/**
* Gets the {@link Deque} of clicks.
*
* @return The deque.
*/
public Deque<Point> getClicks() {
return clicks;
}
/** /**
* Gets the player's credentials. * Gets the player's credentials.
* *
@@ -245,6 +273,11 @@ public final class Player extends Character {
return credentials.getEncodedUsername(); return credentials.getEncodedUsername();
} }
@Override
public EntityType getEntityType() {
return EntityType.PLAYER;
}
/** /**
* Gets the player's head icon. * Gets the player's head icon.
* *
@@ -263,6 +296,15 @@ public final class Player extends Character {
return interfaceSet; return interfaceSet;
} }
/**
* Gets this player's last click, represented by a {@link Point}.
*
* @return The click.
*/
public Point getLastClick() {
return clicks.pollLast();
}
/** /**
* Gets the last known region. * Gets the last known region.
* *
@@ -378,8 +420,6 @@ public final class Player extends Character {
Inventory bank = getBank(); Inventory bank = getBank();
Inventory equipment = getEquipment(); Inventory equipment = getEquipment();
// TODO only add bank listener when it is open? (like Hyperion)
// inventory full listeners // inventory full listeners
InventoryListener fullInventoryListener = new FullInventoryListener(this, InventoryListener fullInventoryListener = new FullInventoryListener(this,
FullInventoryListener.FULL_INVENTORY_MESSAGE); FullInventoryListener.FULL_INVENTORY_MESSAGE);
@@ -509,7 +549,6 @@ public final class Player extends Character {
* Sends the initial events. * Sends the initial events.
*/ */
private void sendInitialEvents() { private void sendInitialEvents() {
// vital initial stuff
send(new IdAssignmentEvent(getIndex(), members)); // TODO should this be sent when we reconnect? send(new IdAssignmentEvent(getIndex(), members)); // TODO should this be sent when we reconnect?
sendMessage("Welcome to RuneScape."); sendMessage("Welcome to RuneScape.");
@@ -546,7 +585,7 @@ public final class Player extends Character {
public void sendQuestInterface(List<String> text) { public void sendQuestInterface(List<String> text) {
int size = text.size(), lines = InterfaceConstants.QUEST_TEXT.length; int size = text.size(), lines = InterfaceConstants.QUEST_TEXT.length;
if (size > lines) { if (size > lines) {
throw new IllegalArgumentException("List contains too much text for the interface."); throw new IllegalArgumentException("list contains too much text for this interface.");
} }
for (int pos = 0; pos < lines; pos++) { for (int pos = 0; pos < lines; pos++) {
@@ -635,6 +674,7 @@ public final class Player extends Character {
*/ */
public void setRunEnergy(int runEnergy) { public void setRunEnergy(int runEnergy) {
this.runEnergy = runEnergy; this.runEnergy = runEnergy;
send(new UpdateRunEnergyEvent(runEnergy));
} }
/** /**
@@ -652,9 +692,9 @@ public final class Player extends Character {
} }
/** /**
* Sets the withdrawing notes flag. * Sets whether the player is withdrawing notes from the bank.
* *
* @param withdrawingNotes The flag. * @param withdrawingNotes Whether the player is withdrawing noted items or not.
*/ */
public void setWithdrawingNotes(boolean withdrawingNotes) { public void setWithdrawingNotes(boolean withdrawingNotes) {
this.withdrawingNotes = withdrawingNotes; this.withdrawingNotes = withdrawingNotes;
+3 -3
View File
@@ -166,7 +166,7 @@ public final class Position {
} }
/** /**
* Gets the x coordinate of the sector. * Gets the x coordinate of the sector this position is in.
* *
* @return The sector x coordinate. * @return The sector x coordinate.
*/ */
@@ -175,7 +175,7 @@ public final class Position {
} }
/** /**
* Gets the y coordinate of the sector. * Gets the y coordinate of the sector this position is in.
* *
* @return The sector y coordinate. * @return The sector y coordinate.
*/ */
@@ -221,7 +221,7 @@ public final class Position {
@Override @Override
public String toString() { public String toString() {
return Position.class.getName() + " [x= " + x + ", y= " + y + ", height= " + height + "]"; return Position.class.getName() + " [x=" + x + ", y=" + y + ", height=" + height + "]";
} }
} }
+11 -1
View File
@@ -129,6 +129,16 @@ public final class Skill {
return SKILL_NAMES[id]; return SKILL_NAMES[id];
} }
/**
* Whether the skill affects the combat level or not.
*
* @param skill The id of the skill.
* @return {@code true} if the skill is a combat skill, otherwise {@code false}.
*/
public static boolean isCombatSkill(int skill) {
return skill >= ATTACK && skill <= MAGIC;
}
/** /**
* The current level. * The current level.
*/ */
@@ -184,4 +194,4 @@ public final class Skill {
return maximumLevel; return maximumLevel;
} }
} }
+50 -56
View File
@@ -15,7 +15,7 @@ public final class SkillSet {
/** /**
* The maximum allowed experience. * The maximum allowed experience.
*/ */
public static final double MAXIMUM_EXP = 200000000; public static final double MAXIMUM_EXP = 200_000_000;
/** /**
* The number of skills. * The number of skills.
@@ -60,6 +60,11 @@ public final class SkillSet {
return 99; return 99;
} }
/**
* The combat level for this skill set.
*/
private int combatLevel = 3;
/** /**
* A flag indicating if events are being fired. * A flag indicating if events are being fired.
*/ */
@@ -94,23 +99,18 @@ public final class SkillSet {
Skill old = skills[id]; Skill old = skills[id];
double newExperience = old.getExperience() + experience; double newExperience = old.getExperience() + experience;
newExperience = newExperience > MAXIMUM_EXP ? MAXIMUM_EXP : newExperience;
if (newExperience > MAXIMUM_EXP) {
newExperience = MAXIMUM_EXP;
}
int newCurrentLevel = old.getCurrentLevel(); int newCurrentLevel = old.getCurrentLevel();
int newMaximumLevel = getLevelForExperience(newExperience); int newMaximumLevel = getLevelForExperience(newExperience);
int delta = newMaximumLevel - old.getMaximumLevel(); int delta = newMaximumLevel - old.getMaximumLevel();
if (delta > 0) { newCurrentLevel += delta > 0 ? delta : 0;
newCurrentLevel += delta;
}
setSkill(id, new Skill(newExperience, newCurrentLevel, newMaximumLevel)); setSkill(id, new Skill(newExperience, newCurrentLevel, newMaximumLevel));
if (delta > 0) { if (delta > 0) {
// here so it gets updated skill // here so it notifies using the updated skill
notifyLevelledUp(id); notifyLevelledUp(id);
} }
} }
@@ -120,27 +120,8 @@ public final class SkillSet {
* *
* @param listener The listener to add. * @param listener The listener to add.
*/ */
public void addListener(SkillListener listener) { public boolean addListener(SkillListener listener) {
listeners.add(listener); return listeners.add(listener);
}
/**
* Checks the bounds of the id.
*
* @param id The id.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/
private void checkBounds(int id) {
if (id < 0 || id >= skills.length) {
throw new IndexOutOfBoundsException();
}
}
/**
* Forces this skill set to refresh.
*/
public void forceRefresh() {
notifySkillsUpdated();
} }
/** /**
@@ -148,12 +129,7 @@ public final class SkillSet {
* *
* @return The combat level. * @return The combat level.
*/ */
/** public void calculateCombatLevel() {
* Gets the combat level for this skill set.
*
* @return The combat level.
*/
public int getCombatLevel() {
int attack = skills[Skill.ATTACK].getMaximumLevel(); int attack = skills[Skill.ATTACK].getMaximumLevel();
int defence = skills[Skill.DEFENCE].getMaximumLevel(); int defence = skills[Skill.DEFENCE].getMaximumLevel();
int strength = skills[Skill.STRENGTH].getMaximumLevel(); int strength = skills[Skill.STRENGTH].getMaximumLevel();
@@ -170,7 +146,35 @@ public final class SkillSet {
double mage = magic * 0.4875; double mage = magic * 0.4875;
return (int) (combatLevel + Math.max(melee, Math.max(range, mage))); this.combatLevel = (int) (combatLevel + Math.max(melee, Math.max(range, mage)));
}
/**
* Checks the bounds of the id.
*
* @param id The id.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/
private void checkBounds(int id) {
if (id < 0 || id >= skills.length) {
throw new IndexOutOfBoundsException("skill id is out of bounds");
}
}
/**
* Forces this skill set to refresh.
*/
public void forceRefresh() {
notifySkillsUpdated();
}
/**
* Gets the combat level for this skill set.
*
* @return The combat level.
*/
public int getCombatLevel() {
return combatLevel;
} }
/** /**
@@ -178,7 +182,6 @@ public final class SkillSet {
* *
* @param id The id. * @param id The id.
* @return The skill. * @return The skill.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/ */
public Skill getSkill(int id) { public Skill getSkill(int id) {
checkBounds(id); checkBounds(id);
@@ -202,13 +205,8 @@ public final class SkillSet {
* Initialises the skill set. * Initialises the skill set.
*/ */
private void init() { private void init() {
for (int i = 0; i < skills.length; i++) { for (int id = 0; id < skills.length; id++) {
if (i == Skill.HITPOINTS) { skills[id] = id == Skill.HITPOINTS ? new Skill(1154, 10, 10) : new Skill(0, 1, 1);
skills[i] = new Skill(1154, 10, 10);
} else {
skills[i] = new Skill(0, 1, 1);
}
// DO NOT CALL notifyXXX here!!
} }
} }
@@ -216,10 +214,9 @@ public final class SkillSet {
* Normalizes the skills in this set. * Normalizes the skills in this set.
*/ */
public void normalize() { public void normalize() {
for (int i = 0; i < skills.length; i++) { for (int id = 0; id < skills.length; id++) {
// TODO I think prayer works differently(?) int cur = skills[id].getCurrentLevel();
int cur = skills[i].getCurrentLevel(); int max = skills[id].getMaximumLevel();
int max = skills[i].getMaximumLevel();
if (cur > max) { if (cur > max) {
cur--; cur--;
@@ -229,7 +226,7 @@ public final class SkillSet {
continue; continue;
} }
setSkill(i, new Skill(skills[i].getExperience(), cur, max)); setSkill(id, new Skill(skills[id].getExperience(), cur, max));
} }
} }
@@ -237,7 +234,6 @@ public final class SkillSet {
* Notifies listeners that a skill has been levelled up. * Notifies listeners that a skill has been levelled up.
* *
* @param id The skill's id. * @param id The skill's id.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/ */
private void notifyLevelledUp(int id) { private void notifyLevelledUp(int id) {
checkBounds(id); checkBounds(id);
@@ -263,7 +259,6 @@ public final class SkillSet {
* Notifies listeners that a skill has been updated. * Notifies listeners that a skill has been updated.
* *
* @param id The skill's id. * @param id The skill's id.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/ */
private void notifySkillUpdated(int id) { private void notifySkillUpdated(int id) {
checkBounds(id); checkBounds(id);
@@ -286,8 +281,8 @@ public final class SkillSet {
* *
* @param listener The listener to remove. * @param listener The listener to remove.
*/ */
public void removeListener(SkillListener listener) { public boolean removeListener(SkillListener listener) {
listeners.remove(listener); return listeners.remove(listener);
} }
/** /**
@@ -295,7 +290,6 @@ public final class SkillSet {
* *
* @param id The id. * @param id The id.
* @param skill The skill. * @param skill The skill.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/ */
public void setSkill(int id, Skill skill) { public void setSkill(int id, Skill skill) {
checkBounds(id); checkBounds(id);
@@ -326,4 +320,4 @@ public final class SkillSet {
firingEvents = false; firingEvents = false;
} }
} }
+1 -1
View File
@@ -46,4 +46,4 @@ public final class SlottedItem {
return slot; return slot;
} }
} }
+77 -32
View File
@@ -4,6 +4,8 @@ import java.io.BufferedInputStream;
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.HashMap;
import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.apollo.Service; import org.apollo.Service;
@@ -18,6 +20,9 @@ import org.apollo.game.model.def.ItemDefinition;
import org.apollo.game.model.def.NpcDefinition; import org.apollo.game.model.def.NpcDefinition;
import org.apollo.game.model.def.ObjectDefinition; import org.apollo.game.model.def.ObjectDefinition;
import org.apollo.game.model.obj.StaticObject; import org.apollo.game.model.obj.StaticObject;
import org.apollo.game.model.sector.Sector;
import org.apollo.game.model.sector.SectorCoordinates;
import org.apollo.game.model.sector.SectorRepository;
import org.apollo.game.scheduling.ScheduledTask; import org.apollo.game.scheduling.ScheduledTask;
import org.apollo.game.scheduling.Scheduler; import org.apollo.game.scheduling.Scheduler;
import org.apollo.io.EquipmentDefinitionParser; import org.apollo.io.EquipmentDefinitionParser;
@@ -92,11 +97,25 @@ public final class World {
WorldConstants.MAXIMUM_PLAYERS); WorldConstants.MAXIMUM_PLAYERS);
/** /**
* The {@link PluginManager}. * The release number (i.e. version) of this world.
*/
private int releaseNumber;
/**
* A {@link Map} of player usernames and the player objects.
*/
private final Map<String, Player> players = new HashMap<String, Player>();
/**
* The {@link PluginManager}. TODO: better place than here!!
*/ */
// TODO: better place than here!!
private PluginManager pluginManager; private PluginManager pluginManager;
/**
* This world's {@link SectorRepository}.
*/
private final SectorRepository repository = new SectorRepository(false);
/** /**
* The scheduler. * The scheduler.
*/ */
@@ -127,12 +146,20 @@ public final class World {
} }
/** /**
* Gets the character repository. NOTE: {@link CharacterRepository#add(Character)} and * Gets the {@link Player} with the specified username.
* {@link CharacterRepository#remove(Character)} should not be called directly! These mutation methods are not *
* guaranteed to work in future releases! * @param username The username.
* @return The player.
*/
public Player getPlayer(String username) {
return players.get(username);
}
/**
* Gets the character repository.
* <p> * <p>
* Instead, use the {@link World#register(Player)} and {@link World#unregister(Player)} methods which do the same * Note: players should be registered and unregistered using {@link World#register(Player)} and
* thing and will continue to work as normal in future releases. * {@link World#unregister(Player)} respectively, not by adding to or removing from this repository directly.
* *
* @return The character repository. * @return The character repository.
*/ */
@@ -158,9 +185,9 @@ public final class World {
* @throws IOException If an I/O error occurs. * @throws IOException If an I/O error occurs.
*/ */
public void init(int release, IndexedFileSystem fs, PluginManager manager) throws IOException { public void init(int release, IndexedFileSystem fs, PluginManager manager) throws IOException {
this.releaseNumber = release;
ItemDefinitionDecoder itemParser = new ItemDefinitionDecoder(fs); ItemDefinitionDecoder itemDefParser = new ItemDefinitionDecoder(fs);
ItemDefinition[] itemDefs = itemParser.decode(); ItemDefinition[] itemDefs = itemDefParser.decode();
ItemDefinition.init(itemDefs); ItemDefinition.init(itemDefs);
logger.info("Loaded " + itemDefs.length + " item definitions."); logger.info("Loaded " + itemDefs.length + " item definitions.");
@@ -174,42 +201,51 @@ public final class World {
is.close(); is.close();
} }
NpcDefinitionDecoder parser = new NpcDefinitionDecoder(fs); NpcDefinitionDecoder npcDefParser = new NpcDefinitionDecoder(fs);
NpcDefinition[] npcDefs = parser.decode(); NpcDefinition[] npcDefs = npcDefParser.decode();
NpcDefinition.init(npcDefs); NpcDefinition.init(npcDefs);
logger.info("Loaded " + npcDefs.length + " npc definitions."); logger.info("Loaded " + npcDefs.length + " npc definitions.");
ObjectDefinitionDecoder objParser = new ObjectDefinitionDecoder(fs); ObjectDefinitionDecoder objDefParser = new ObjectDefinitionDecoder(fs);
ObjectDefinition[] objDefs = objParser.decode(); ObjectDefinition[] objDefs = objDefParser.decode();
ObjectDefinition.init(objDefs); ObjectDefinition.init(objDefs);
logger.info("Loaded " + objDefs.length + " object definitions."); logger.info("Loaded " + objDefs.length + " object definitions.");
StaticObjectDecoder objectParser = new StaticObjectDecoder(fs); StaticObjectDecoder objectParser = new StaticObjectDecoder(fs);
StaticObject[] objects = objectParser.decode(); StaticObject[] objects = objectParser.decode();
StaticObject.init(objects); placeEntities(objects);
logger.info("Loaded " + objects.length + " static objects."); logger.info("Loaded " + objects.length + " static objects.");
pluginManager = manager; // TODO move!! pluginManager = manager; // TODO move!!
} }
/** /**
* Checks if the specified player is online. * Checks if the {@link Player} with the specified name is online.
* *
* @param name The player's name. * @param name The name.
* @return {@code true} if so, {@code false} if not. * @return {@code true} if the player is online, otherwise {@code false}.
*/ */
public boolean isPlayerOnline(String name) { public boolean isPlayerOnline(String name) {
// TODO: use a hash set or map in the future? return getPlayer(name) != null;
for (Player player : playerRepository) {
if (player.getName().equalsIgnoreCase(name)) {
return true;
}
}
return false;
} }
/** /**
* Calls the {@link Scheduler#pulse()} method. * Adds entities to sectors in the {@link SectorRepository}.
*
* @param entities The entities.
* @return {@code true} if all entities were added successfully, otherwise {@code false}.
*/
private boolean placeEntities(Entity[] entities) {
boolean success = true;
for (Entity entity : entities) {
Sector sector = repository.get(SectorCoordinates.fromPosition(entity.getPosition()));
success &= sector.addEntity(entity);
}
return success;
}
/**
* Pulses the world.
*/ */
public void pulse() { public void pulse() {
scheduler.pulse(); scheduler.pulse();
@@ -242,7 +278,7 @@ public final class World {
return RegistrationStatus.ALREADY_ONLINE; return RegistrationStatus.ALREADY_ONLINE;
} }
boolean success = playerRepository.add(player); boolean success = playerRepository.add(player) & players.put(player.getName(), player) == null;
if (success) { if (success) {
logger.info("Registered player: " + player + " [online=" + playerRepository.size() + "]"); logger.info("Registered player: " + player + " [online=" + playerRepository.size() + "]");
return RegistrationStatus.OK; return RegistrationStatus.OK;
@@ -252,13 +288,22 @@ public final class World {
return RegistrationStatus.WORLD_FULL; return RegistrationStatus.WORLD_FULL;
} }
/**
* Gets the release number of this world.
*
* @return The release number.
*/
public int getReleaseNumber() {
return releaseNumber;
}
/** /**
* Schedules a new task. * Schedules a new task.
* *
* @param task The {@link ScheduledTask}. * @param task The {@link ScheduledTask}.
*/ */
public void schedule(ScheduledTask task) { public boolean schedule(ScheduledTask task) {
scheduler.schedule(task); return scheduler.schedule(task);
} }
/** /**
@@ -268,7 +313,7 @@ public final class World {
*/ */
public void unregister(Npc npc) { public void unregister(Npc npc) {
if (npcRepository.remove(npc)) { if (npcRepository.remove(npc)) {
logger.info("Unregistered npc: " + npc + " [online=" + npcRepository.size() + "]"); logger.info("Unregistered npc: " + npc + " [count=" + npcRepository.size() + "]");
} else { } else {
logger.warning("Could not find npc " + npc + " to unregister!"); logger.warning("Could not find npc " + npc + " to unregister!");
} }
@@ -280,10 +325,10 @@ public final class World {
* @param player The player. * @param player The player.
*/ */
public void unregister(Player player) { public void unregister(Player player) {
if (playerRepository.remove(player)) { if (playerRepository.remove(player) & players.remove(player.getName()) == player) {
logger.info("Unregistered player: " + player + " [online=" + playerRepository.size() + "]"); logger.info("Unregistered player: " + player + " [online=" + playerRepository.size() + "]");
} else { } else {
logger.warning("Could not find player to unregister: " + player + "!"); logger.warning("Could not find player " + player + " to unregister!");
} }
} }
@@ -88,7 +88,7 @@ public final class ItemDefinition {
*/ */
public static ItemDefinition lookup(int id) { public static ItemDefinition lookup(int id) {
if (id < 0 || id >= definitions.length) { if (id < 0 || id >= definitions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("item id is out of bounds");
} }
return definitions[id]; return definitions[id];
} }
@@ -189,7 +189,7 @@ public final class ItemDefinition {
*/ */
public String getGroundAction(int id) { public String getGroundAction(int id) {
if (id < 0 || id >= groundActions.length) { if (id < 0 || id >= groundActions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("ground action id is out of bounds");
} }
return groundActions[id]; return groundActions[id];
} }
@@ -212,7 +212,7 @@ public final class ItemDefinition {
*/ */
public String getInventoryAction(int id) { public String getInventoryAction(int id) {
if (id < 0 || id >= inventoryActions.length) { if (id < 0 || id >= inventoryActions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("inventory action id is out of bounds");
} }
return inventoryActions[id]; return inventoryActions[id];
} }
@@ -307,7 +307,7 @@ public final class ItemDefinition {
*/ */
public void setGroundAction(int id, String action) { public void setGroundAction(int id, String action) {
if (id < 0 || id >= groundActions.length) { if (id < 0 || id >= groundActions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("ground action id is out of bounds");
} }
groundActions[id] = action; groundActions[id] = action;
} }
@@ -321,7 +321,7 @@ public final class ItemDefinition {
*/ */
public void setInventoryAction(int id, String action) { public void setInventoryAction(int id, String action) {
if (id < 0 || id >= inventoryActions.length) { if (id < 0 || id >= inventoryActions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("inventory action id is out of bounds");
} }
inventoryActions[id] = action; inventoryActions[id] = action;
} }
@@ -57,7 +57,7 @@ public final class NpcDefinition {
*/ */
public static NpcDefinition lookup(int id) { public static NpcDefinition lookup(int id) {
if (id < 0 || id >= definitions.length) { if (id < 0 || id >= definitions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("npc id is out of bounds");
} }
return definitions[id]; return definitions[id];
} }
@@ -142,7 +142,7 @@ public final class NpcDefinition {
*/ */
public String getInteraction(int slot) { public String getInteraction(int slot) {
if (slot < 0 || slot >= interactions.length) { if (slot < 0 || slot >= interactions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("npc interaction id is out of bounds");
} }
return interactions[slot]; return interactions[slot];
} }
@@ -237,7 +237,7 @@ public final class NpcDefinition {
*/ */
public boolean hasInteraction(int slot) { public boolean hasInteraction(int slot) {
if (slot < 0 || slot >= interactions.length) { if (slot < 0 || slot >= interactions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("npc interaction id is out of bounds");
} }
return interactions[slot] != null; return interactions[slot] != null;
} }
@@ -314,7 +314,7 @@ public final class NpcDefinition {
*/ */
public void setInteraction(int slot, String interaction) { public void setInteraction(int slot, String interaction) {
if (slot < 0 || slot >= interactions.length) { if (slot < 0 || slot >= interactions.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("npc interaction id is out of bounds");
} }
interactions[slot] = interaction; interactions[slot] = interaction;
} }
@@ -1,4 +1,4 @@
package org.apollo.game.model; package org.apollo.game.model.inter;
/** /**
* Contains interface-related constants. * Contains interface-related constants.
@@ -21,6 +21,12 @@ public class InterfaceConstants {
// 4445 = settings tab, music disabled // 4445 = settings tab, music disabled
// 12855 = ancients magic // 12855 = ancients magic
/**
* The level-up dialogue interface ids.
*/
public static final int[] LEVEL_UP_INTERFACES = { 6247, 6253, 6206, 6216, 4443, 6242, 6211, 6226, 4272, 6231, 6258,
4282, 6263, 6221, 4416, 6237, 4277, 4261, 12122, 4887, 4267 };
/** /**
* The quest interface id. * The quest interface id.
*/ */
@@ -1,4 +1,4 @@
package org.apollo.game.model; package org.apollo.game.model.inter;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -7,8 +7,7 @@ import org.apollo.game.event.impl.CloseInterfaceEvent;
import org.apollo.game.event.impl.EnterAmountEvent; import org.apollo.game.event.impl.EnterAmountEvent;
import org.apollo.game.event.impl.OpenInterfaceEvent; import org.apollo.game.event.impl.OpenInterfaceEvent;
import org.apollo.game.event.impl.OpenInterfaceSidebarEvent; import org.apollo.game.event.impl.OpenInterfaceSidebarEvent;
import org.apollo.game.model.inter.EnterAmountListener; import org.apollo.game.model.Player;
import org.apollo.game.model.inter.InterfaceListener;
/** /**
* Represents the set of interfaces the player has open. * Represents the set of interfaces the player has open.
@@ -16,14 +15,13 @@ import org.apollo.game.model.inter.InterfaceListener;
* This class manages all six distinct types of interface (the last two are not present on 317 servers). * This class manages all six distinct types of interface (the last two are not present on 317 servers).
* <p> * <p>
* <ul> * <ul>
* <li><strong>Windows:</strong> the ones people mostly associate with the word interfaces. Things like your bank, the * <li><strong>Windows:</strong> Interfaces such as the bank, the wilderness warning screen, the trade screen, etc.</li>
* wildy warning screen, the trade screen, etc.</li> * <li><strong>Overlays:</strong> Displayed in the same place as windows, but don't prevent a player from moving e.g.
* <li><strong>Overlays:</strong> display in the same place as windows, but don't prevent you from moving. For example,
* the wilderness level indicator.</li> * the wilderness level indicator.</li>
* <li><strong>Dialogues:</strong> interfaces which are displayed over the chat box.</li> * <li><strong>Dialogues:</strong> Interfaces displayed over the chat box.</li>
* <li><strong>Sidebars:</strong> an interface which displays over the inventory area.</li> * <li><strong>Sidebars:</strong> Interfaces displayed over the inventory area.</li>
* <li><strong>Fullscreen windows:</strong> a window which displays over the whole screen e.g. the 377 welcome screen.</li> * <li><strong>Fullscreen windows:</strong> A window displayed over the whole screen e.g. the 377 welcome screen.</li>
* <li><strong>Fullscreen background:</strong> an interface displayed behind the fullscreen window, typically a blank, * <li><strong>Fullscreen background:</strong> Interfaces displayed behind the fullscreen window, typically a blank,
* black screen.</li> * black screen.</li>
* </ul> * </ul>
* *
@@ -0,0 +1,41 @@
package org.apollo.game.model.inter;
/**
* Represents the different types of interfaces.
*
* @author Graham
*/
public enum InterfaceType {
/**
* An interface that appears in the chat box.
*/
DIALOGUE,
/**
* An interface shown behind a fullscreen window.
*/
FULLSCREEN_BACKGROUND,
/**
* An interface shown in full screen mode.
*/
FULLSCREEN_WINDOW,
/**
* An interface that occupies the game screen like a window, but the player can still perform actions without the
* interface closing.
*/
OVERLAY,
/**
* An interface displayed over the inventory area.
*/
SIDEBAR,
/**
* An interface that occupies the game screen.
*/
WINDOW;
}
@@ -1,5 +1,5 @@
/** /**
* Contains interface listeners. * Contains interface-related classes.
*/ */
package org.apollo.game.model.inter; package org.apollo.game.model.inter;
+21 -2
View File
@@ -1,5 +1,8 @@
package org.apollo.game.model.obj; package org.apollo.game.model.obj;
import org.apollo.game.model.Entity;
import org.apollo.game.model.EntityType;
import org.apollo.game.model.Position;
import org.apollo.game.model.def.ObjectDefinition; import org.apollo.game.model.def.ObjectDefinition;
/** /**
@@ -7,20 +10,26 @@ import org.apollo.game.model.def.ObjectDefinition;
* *
* @author Major * @author Major
*/ */
public final class GameObject { public final class GameObject implements Entity {
/** /**
* The object definition. * The object definition.
*/ */
private final ObjectDefinition definition; private final ObjectDefinition definition;
/**
* The position of the game object.
*/
private final Position position;
/** /**
* Creates the game object. * Creates the game object.
* *
* @param definition The object's definition. * @param definition The object's definition.
*/ */
public GameObject(ObjectDefinition definition) { public GameObject(ObjectDefinition definition, Position position) {
this.definition = definition; this.definition = definition;
this.position = position;
} }
/** /**
@@ -32,4 +41,14 @@ public final class GameObject {
return definition; return definition;
} }
@Override
public EntityType getEntityType() {
return EntityType.GAME_OBJECT;
}
@Override
public Position getPosition() {
return position;
}
} }
+15 -15
View File
@@ -1,22 +1,17 @@
package org.apollo.game.model.obj; package org.apollo.game.model.obj;
import org.apollo.game.model.Entity;
import org.apollo.game.model.EntityType;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.def.ObjectDefinition; import org.apollo.game.model.def.ObjectDefinition;
/** /**
* Represents a static object in the game world. * Represents a static object in the game world.
* *
* @author Graham
* @author Chris Fletcher * @author Chris Fletcher
* @author Major * @author Major
*/ */
public final class StaticObject { public final class StaticObject implements Entity {
/**
* Initialises the static objects.
*/
public static void init(StaticObject[] objects) {
}
/** /**
* The object's definition. * The object's definition.
@@ -26,7 +21,7 @@ public final class StaticObject {
/** /**
* The object's id. * The object's id.
*/ */
private final short id; private final int id;
/** /**
* The object's position. * The object's position.
@@ -36,12 +31,12 @@ public final class StaticObject {
/** /**
* The object's rotation. * The object's rotation.
*/ */
private final byte rotation; private final int rotation;
/** /**
* The object type. * The object type.
*/ */
private final byte type; private final int type;
/** /**
* Creates a new static object. * Creates a new static object.
@@ -52,10 +47,10 @@ public final class StaticObject {
* @param rotation The rotation of the object. * @param rotation The rotation of the object.
*/ */
public StaticObject(int id, Position position, int type, int rotation) { public StaticObject(int id, Position position, int type, int rotation) {
this.id = (short) id; this.id = id;
this.position = position; this.position = position;
this.type = (byte) type; this.type = type;
this.rotation = (byte) rotation; this.rotation = rotation;
definition = ObjectDefinition.lookup(id); definition = ObjectDefinition.lookup(id);
} }
@@ -68,6 +63,11 @@ public final class StaticObject {
return definition; return definition;
} }
@Override
public EntityType getEntityType() {
return EntityType.STATIC_OBJECT;
}
/** /**
* Gets the id of the object. * Gets the id of the object.
* *
@@ -106,7 +106,7 @@ public final class StaticObject {
@Override @Override
public String toString() { public String toString() {
return StaticObject.class.getName() + " [id= " + id + ", type= " + type + ", rotation= " + rotation + "]"; return StaticObject.class.getName() + " [id=" + id + ", type=" + type + ", rotation=" + rotation + "]";
} }
} }
+31 -9
View File
@@ -1,9 +1,14 @@
package org.apollo.game.model.sector; package org.apollo.game.model.sector;
import java.util.ArrayList;
import java.util.List;
import org.apollo.game.model.Entity;
/** /**
* Represents an 8x8 area of the map. * Represents an 8x8 area of the map.
* *
* @author Graham * @author Major
*/ */
public final class Sector { public final class Sector {
@@ -17,6 +22,11 @@ public final class Sector {
*/ */
private final SectorCoordinates coordinates; private final SectorCoordinates coordinates;
/**
* A {@link List} of every {@link Entity} in this sector.
*/
private final List<Entity> entities = new ArrayList<Entity>();
/** /**
* Creates a new sector. * Creates a new sector.
* *
@@ -37,21 +47,33 @@ public final class Sector {
} }
/** /**
* Gets the x coordinate of this sector. * Adds a {@link Entity} from to sector. Note that this does not spawn the entity, or do any other action
* other than register it to this sector.
* *
* @return The x coordinate. * @param entity The entity.
* @return {@code true} if the entity was added, otherwise {@code false}.
*/ */
public int getX() { public boolean addEntity(Entity entity) {
return coordinates.getX(); return entities.add(entity);
} }
/** /**
* Gets the y coordinate of this sector. * Gets this sector's {@link SectorCoordinates}.
* *
* @return The y coordinate. * @return The sector coordinates.
*/ */
public int getY() { public SectorCoordinates getCoordinates() {
return coordinates.getY(); return coordinates;
}
/**
* Removes a {@link Entity} from this sector.
*
* @param entity The entity.
* @return {@code true} if the entity was removed, otherwise {@code false}.
*/
public boolean removeEntity(Entity entity) {
return entities.remove(entity);
} }
} }
@@ -1,19 +1,32 @@
package org.apollo.game.model.sector; package org.apollo.game.model.sector;
import org.apollo.game.model.Position;
/** /**
* An immutable class representing the coordinates of a sector. * An immutable class representing the coordinates of a sector, where the coordinates ({@code x, y}) are the top-left of
* the sector.
* *
* @author Graham * @author Graham
*/ */
public final class SectorCoordinates { public final class SectorCoordinates {
/** /**
* The x coordinate. * Gets a pair of sector coordinates from a {@link Position}.
*
* @param position The position.
* @return The sector coordinates.
*/
public static SectorCoordinates fromPosition(Position position) {
return new SectorCoordinates(position.getTopLeftSectorX(), position.getTopLeftSectorY());
}
/**
* The x coordinate of this sector.
*/ */
private final int x; private final int x;
/** /**
* The y coordinate. * The y coordinate of this sector.
*/ */
private final int y; private final int y;
@@ -44,7 +57,7 @@ public final class SectorCoordinates {
} }
/** /**
* Gets the x coordinate. * Gets the x coordinate (equivalent to the {@link Position#getTopLeftSectorX()} of a position within this sector).
* *
* @return The x coordinate. * @return The x coordinate.
*/ */
@@ -53,7 +66,7 @@ public final class SectorCoordinates {
} }
/** /**
* Gets the y coordinate. * Gets the y coordinate (equivalent to the {@link Position#getTopLeftSectorY()} of a position within this sector).
* *
* @return The y coordinate. * @return The y coordinate.
*/ */
@@ -63,10 +76,7 @@ public final class SectorCoordinates {
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; return 61 * (427 + x) + y;
hash = 61 * hash + x;
hash = 61 * hash + y;
return hash;
} }
} }
@@ -1,10 +1,103 @@
package org.apollo.game.model.sector; package org.apollo.game.model.sector;
import java.util.HashMap;
import java.util.Map;
/** /**
* A repository of sectors. * A repository of sectors, backed by a {@link HashMap} of {@link SectorCoordinates} that correspond to their
* appropriate {@link Sector}s.
* *
* @author Graham * @author Major
*/ */
public class SectorRepository { public final class SectorRepository {
/**
* Indicates whether sectors can be removed from this repository.
*/
private final boolean permitRemoval;
/**
* A {@link Map} of {@link SectorCoordinates} that correspond to the appropriate {@link Sector}s..
*/
private final Map<SectorCoordinates, Sector> sectors = new HashMap<>();
/**
* Creates a new sector repository.
*
* @param permitRemoval If removal (of {@link Sector}s) from this repository should be permitted.
*/
public SectorRepository(boolean permitRemoval) {
this.permitRemoval = permitRemoval;
}
/**
* Adds a {@link Sector} to the repository.
*
* @param sector The sector.
* @return {@code false} if another sector was replaced, otherwise {@code true}.
* @throws IllegalArgumentException If the provided sector is null.
* @throws UnsupportedOperationException If the coordinates of the provided sector are already mapped (and hence the
* existing sector would be replaced), and removal of sectors is not permitted.
*/
public void add(Sector sector) {
if (sector == null) {
throw new IllegalArgumentException("sector cannot be null");
} else if (sectors.containsKey(sector.getCoordinates()) && !permitRemoval) {
throw new UnsupportedOperationException(
"cannot add a sector with the same coordinates as an existing sector");
}
sectors.put(sector.getCoordinates(), sector);
}
/**
* Indicates whether the supplied value (i.e. the {@link Sector}) has a mapping.
*
* @param sector The sector.
* @return {@code true} if the value is mapped by a key (i.e. {@link SectorCoordinates}), otherwise {@code false}.
*/
public boolean contains(Sector sector) {
return sectors.containsValue(sector);
}
/**
* Indicates whether the supplied key (i.e. the {@link SectorCoordinates}) has a mapping.
*
* @param coordinates The coordinates.
* @return {@code true} if the key is already mapped to a value (i.e. a {@link Sector}), otherwise {@code false}.
*/
public boolean contains(SectorCoordinates coordinates) {
return sectors.containsKey(coordinates);
}
/**
* Gets a {@link Sector} with the specified {@link SectorCoordinates}. If the sector does not exist (i.e.
* {@link #sectors}{@code .get()} returns {@code null}) then a new sector is created, submitted to the repository,
* and returned.
*
* @param coordinates The coordinates.
* @return The sector.
*/
public Sector get(SectorCoordinates coordinates) {
Sector sector = sectors.get(coordinates);
if (sector == null) {
add(sector = new Sector(coordinates));
}
return sector;
}
/**
* Removes a {@link Sector} from the repository, if permitted.
*
* @param sector The sector to remove.
* @return {@code true} unless the coordinates of the provided sector were the key to another sector, or the sector
* did not exist in the first place.
* @throws UnsupportedOperationException If this method is called on a repository that does not permit removal.
*/
public void remove(Sector sector) {
if (!permitRemoval) {
throw new UnsupportedOperationException("cannot remove sectors from this repository");
}
sectors.remove(sector.getCoordinates());
}
} }
@@ -33,6 +33,10 @@ public final class LevelUpSkillListener extends SkillAdapter {
String article = LanguageUtil.getIndefiniteArticle(name); String article = LanguageUtil.getIndefiniteArticle(name);
player.sendMessage("You've just advanced " + article + " " + name + " level! You have reached level " player.sendMessage("You've just advanced " + article + " " + name + " level! You have reached level "
+ skill.getMaximumLevel() + "."); + skill.getMaximumLevel() + ".");
if (Skill.isCombatSkill(id)) {
player.getSkillSet().calculateCombatLevel();
}
} }
} }
@@ -67,7 +67,7 @@ public abstract class ScheduledTask {
*/ */
public void setDelay(int delay) { public void setDelay(int delay) {
if (delay < 0) { if (delay < 0) {
throw new IllegalArgumentException(); throw new IllegalArgumentException("delay cannot be less than 0");
} }
this.delay = delay; this.delay = delay;
} }
@@ -46,8 +46,8 @@ public final class Scheduler {
* *
* @param task The task to schedule. * @param task The task to schedule.
*/ */
public void schedule(ScheduledTask task) { public boolean schedule(ScheduledTask task) {
newTasks.add(task); return newTasks.add(task);
} }
} }
@@ -30,12 +30,12 @@ public class ForceMovementBlock extends SynchronizationBlock {
private final Position initialPosition; private final Position initialPosition;
/** /**
* The length of time (in game ticks) the player's movement along the X axis will last. * The length of time (in game pulses) the player's movement along the X axis will last.
*/ */
private final int travelDurationX; private final int travelDurationX;
/** /**
* The length of time (in game ticks) the player's movement along the Y axis will last. * The length of time (in game pulses) the player's movement along the Y axis will last.
*/ */
private final int travelDurationY; private final int travelDurationY;
@@ -44,8 +44,8 @@ public class ForceMovementBlock extends SynchronizationBlock {
* *
* @param initialPosition The initial {@link Position} of the player. * @param initialPosition The initial {@link Position} of the player.
* @param finalPosition The final {@link Position} of the player * @param finalPosition The final {@link Position} of the player
* @param travelDurationX The length of time (in game ticks) the player's movement along the X axis will last. * @param travelDurationX The length of time (in game pulses) the player's movement along the X axis will last.
* @param travelDurationY The length of time (in game ticks) the player's movement along the Y axis will last. * @param travelDurationY The length of time (in game pulses) the player's movement along the Y axis will last.
* @param direction The direction the player should move. * @param direction The direction the player should move.
*/ */
public ForceMovementBlock(Position initialPosition, Position finalPosition, int travelDurationX, public ForceMovementBlock(Position initialPosition, Position finalPosition, int travelDurationX,
@@ -123,7 +123,7 @@ public class ForceMovementBlock extends SynchronizationBlock {
} }
/** /**
* Gets the length of time (in game ticks) the player's movement along the Y axis will last. * Gets the length of time (in game pulses) the player's movement along the Y axis will last.
* *
* @return The time period. * @return The time period.
*/ */
@@ -132,7 +132,7 @@ public class ForceMovementBlock extends SynchronizationBlock {
} }
/** /**
* Gets the length of time (in game ticks) the player's movement along the Y axis will last. * Gets the length of time (in game pulses) the player's movement along the Y axis will last.
* *
* @return The time period. * @return The time period.
*/ */
@@ -49,8 +49,8 @@ public final class MovementSegment extends SynchronizationSegment {
case 2: case 2:
return SegmentType.RUN; return SegmentType.RUN;
default: default:
throw new IllegalStateException(); throw new IllegalStateException("direction type unsupported");
} }
} }
} }
@@ -45,10 +45,6 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
player.getWalkingQueue().pulse(); player.getWalkingQueue().pulse();
if (player.isTeleporting()) { if (player.isTeleporting()) {
// TODO check if this should be done anywhere else if the conditions should be different
// e.g. if the player teleports one tile away should the viewing distance be reset?
// if this isn't the case, what should the max teleport distance be before it is reset?
// or is this correct anyway?!
player.resetViewingDistance(); player.resetViewingDistance();
} }
@@ -62,4 +58,4 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
} }
} }
} }
+1 -1
View File
@@ -19,4 +19,4 @@ public interface PlayerLoader {
*/ */
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception; public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception;
} }
@@ -33,7 +33,7 @@ public final class BinaryPlayerLoader implements PlayerLoader {
private static final Position SPAWN_POSITION = new Position(3222, 3222); private static final Position SPAWN_POSITION = new Position(3222, 3222);
@Override @Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception { public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws IOException {
File f = BinaryPlayerUtil.getFile(credentials.getUsername()); File f = BinaryPlayerUtil.getFile(credentials.getUsername());
if (!f.exists()) { if (!f.exists()) {
return new PlayerLoaderResponse(LoginConstants.STATUS_OK, new Player(credentials, SPAWN_POSITION)); return new PlayerLoaderResponse(LoginConstants.STATUS_OK, new Player(credentials, SPAWN_POSITION));
@@ -42,7 +42,7 @@ public final class BinaryPlayerLoader implements PlayerLoader {
DataInputStream in = new DataInputStream(new FileInputStream(f)); DataInputStream in = new DataInputStream(new FileInputStream(f));
try { try {
// read credentials nad privileges // read credentials and privileges
String name = StreamUtil.readString(in); String name = StreamUtil.readString(in);
String pass = StreamUtil.readString(in); String pass = StreamUtil.readString(in);
@@ -129,4 +129,4 @@ public final class BinaryPlayerLoader implements PlayerLoader {
} }
} }
} }
@@ -23,7 +23,7 @@ import org.apollo.util.StreamUtil;
public final class BinaryPlayerSaver implements PlayerSaver { public final class BinaryPlayerSaver implements PlayerSaver {
@Override @Override
public void savePlayer(Player player) throws Exception { public void savePlayer(Player player) throws IOException {
File f = BinaryPlayerUtil.getFile(player.getName()); File f = BinaryPlayerUtil.getFile(player.getName());
DataOutputStream out = new DataOutputStream(new FileOutputStream(f)); DataOutputStream out = new DataOutputStream(new FileOutputStream(f));
try { try {
@@ -11,8 +11,8 @@ import org.apollo.io.player.PlayerSaver;
public final class DiscardPlayerSaver implements PlayerSaver { public final class DiscardPlayerSaver implements PlayerSaver {
@Override @Override
public void savePlayer(Player player) throws Exception { public void savePlayer(Player player) {
/* discard player */ /* discard player */
} }
} }
@@ -21,7 +21,7 @@ public final class DummyPlayerLoader implements PlayerLoader {
private static final Position DEFAULT_POSITION = new Position(3222, 3222); private static final Position DEFAULT_POSITION = new Position(3222, 3222);
@Override @Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception { public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) {
int status = LoginConstants.STATUS_OK; int status = LoginConstants.STATUS_OK;
Player player = new Player(credentials, DEFAULT_POSITION); Player player = new Player(credentials, DEFAULT_POSITION);
@@ -31,4 +31,4 @@ public final class DummyPlayerLoader implements PlayerLoader {
return new PlayerLoaderResponse(status, player); return new PlayerLoaderResponse(status, player);
} }
} }
@@ -8,8 +8,7 @@ public final class JdbcPlayerLoader implements PlayerLoader {
@Override @Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception { public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception {
return null; return null;
} }
} }
+12 -5
View File
@@ -1,6 +1,7 @@
package org.apollo.login; package org.apollo.login;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@@ -18,6 +19,7 @@ import org.apollo.net.session.LoginSession;
import org.apollo.util.NamedThreadFactory; import org.apollo.util.NamedThreadFactory;
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;
/** /**
* The {@link LoginService} manages {@link LoginRequest}s. * The {@link LoginService} manages {@link LoginRequest}s.
@@ -53,9 +55,14 @@ public final class LoginService extends Service {
/** /**
* Initialises the login service. * Initialises the login service.
* *
* @throws Exception If an error occurs. * @throws SAXException If there is an error parsing the XML file.
* @throws IOException If there is an error accessing the file.
* @throws ClassNotFoundException If the player loader/saver implementation could not be found.
* @throws IllegalAccessException If the player loader/saver implementation could not be accessed.
* @throws InstantiationException If the player loader/saver implementation could not be instantiated.
*/ */
private void init() throws Exception { private void init() throws SAXException, IOException, ClassNotFoundException, InstantiationException,
IllegalAccessException {
XmlParser parser = new XmlParser(); XmlParser parser = new XmlParser();
XmlNode rootNode; XmlNode rootNode;
@@ -67,17 +74,17 @@ public final class LoginService extends Service {
} }
if (!rootNode.getName().equals("login")) { if (!rootNode.getName().equals("login")) {
throw new Exception("unexpected root node name"); throw new IOException("unexpected root node name");
} }
XmlNode loaderNode = rootNode.getChild("loader"); XmlNode loaderNode = rootNode.getChild("loader");
if (loaderNode == null || !loaderNode.hasValue()) { if (loaderNode == null || !loaderNode.hasValue()) {
throw new Exception("no loader child node or value"); throw new IOException("no loader child node or value");
} }
XmlNode saverNode = rootNode.getChild("saver"); XmlNode saverNode = rootNode.getChild("saver");
if (saverNode == null || !saverNode.hasValue()) { if (saverNode == null || !saverNode.hasValue()) {
throw new Exception("no saver child node or value"); throw new IOException("no saver child node or value");
} }
Class<?> loaderClazz = Class.forName(loaderNode.getValue()); Class<?> loaderClazz = Class.forName(loaderNode.getValue());
+6 -6
View File
@@ -47,14 +47,14 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
} }
@Override @Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel channel = ctx.getChannel(); Channel channel = ctx.getChannel();
logger.info("Channel connected: " + channel); logger.info("Channel connected: " + channel);
serverContext.getChannelGroup().add(channel); serverContext.getChannelGroup().add(channel);
} }
@Override @Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel channel = ctx.getChannel(); Channel channel = ctx.getChannel();
logger.info("Channel disconnected: " + channel); logger.info("Channel disconnected: " + channel);
serverContext.getChannelGroup().remove(channel); serverContext.getChannelGroup().remove(channel);
@@ -65,18 +65,18 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
} }
@Override @Override
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception { public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) {
e.getChannel().close(); e.getChannel().close();
} }
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(Level.WARNING, "Exception occured for channel: " + e.getChannel() + ", closing...", e.getCause()); logger.log(Level.WARNING, "Exception occured for channel: " + e.getChannel() + ", closing...", e.getCause());
ctx.getChannel().close(); ctx.getChannel().close();
} }
@Override @Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if (ctx.getAttachment() == null) { if (ctx.getAttachment() == null) {
Object msg = e.getMessage(); Object msg = e.getMessage();
if (msg instanceof HttpRequest || msg instanceof JagGrabRequest) { if (msg instanceof HttpRequest || msg instanceof JagGrabRequest) {
@@ -94,7 +94,7 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
ctx.setAttachment(new UpdateSession(ctx.getChannel(), serverContext)); ctx.setAttachment(new UpdateSession(ctx.getChannel(), serverContext));
break; break;
default: default:
throw new Exception("Invalid service id"); throw new IllegalStateException("Invalid service id");
} }
} }
} else { } else {
+2 -2
View File
@@ -43,7 +43,7 @@ public final class HttpPipelineFactory implements ChannelPipelineFactory {
} }
@Override @Override
public ChannelPipeline getPipeline() throws Exception { public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline(); ChannelPipeline pipeline = Channels.pipeline();
// decoders // decoders
@@ -60,4 +60,4 @@ public final class HttpPipelineFactory implements ChannelPipelineFactory {
return pipeline; return pipeline;
} }
} }
@@ -66,7 +66,7 @@ public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
} }
@Override @Override
public ChannelPipeline getPipeline() throws Exception { public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline(); ChannelPipeline pipeline = Channels.pipeline();
// decoders // decoders
@@ -84,4 +84,4 @@ public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
return pipeline; return pipeline;
} }
} }
@@ -36,7 +36,7 @@ public final class ServicePipelineFactory implements ChannelPipelineFactory {
} }
@Override @Override
public ChannelPipeline getPipeline() throws Exception { public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline(); ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("handshakeDecoder", new HandshakeDecoder()); pipeline.addLast("handshakeDecoder", new HandshakeDecoder());
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0)); pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0));
@@ -44,4 +44,4 @@ public final class ServicePipelineFactory implements ChannelPipelineFactory {
return pipeline; return pipeline;
} }
} }
@@ -29,7 +29,7 @@ public final class GameEventDecoder extends OneToOneDecoder {
} }
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception { protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) {
if (msg instanceof GamePacket) { if (msg instanceof GamePacket) {
GamePacket packet = (GamePacket) msg; GamePacket packet = (GamePacket) msg;
EventDecoder<?> decoder = release.getEventDecoder(packet.getOpcode()); EventDecoder<?> decoder = release.getEventDecoder(packet.getOpcode());
@@ -30,7 +30,7 @@ public final class GameEventEncoder extends OneToOneEncoder {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception { protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) {
if (msg instanceof Event) { if (msg instanceof Event) {
Event event = (Event) msg; Event event = (Event) msg;
EventEncoder<Event> encoder = (EventEncoder<Event>) release.getEventEncoder(event.getClass()); EventEncoder<Event> encoder = (EventEncoder<Event>) release.getEventEncoder(event.getClass());
@@ -91,7 +91,6 @@ public final class GamePacketBuilder {
* Gets the current length of the builder's buffer. * Gets the current length of the builder's buffer.
* *
* @return The length of the buffer. * @return The length of the buffer.
* @throws IllegalStateException If the builder is not in byte access mode.
*/ */
public int getLength() { public int getLength() {
checkByteAccess(); checkByteAccess();
@@ -105,8 +104,7 @@ public final class GamePacketBuilder {
* @param order The byte order. * @param order The byte order.
* @param transformation The transformation. * @param transformation The transformation.
* @param value The value. * @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode. * @throws IllegalArgumentException If the type, order, or transformation is unknown.
* @throws IllegalArgumentException If the combination is invalid.
*/ */
public void put(DataType type, DataOrder order, DataTransformation transformation, Number value) { public void put(DataType type, DataOrder order, DataTransformation transformation, Number value) {
checkByteAccess(); checkByteAccess();
@@ -177,8 +175,6 @@ public final class GamePacketBuilder {
* @param type The data type. * @param type The data type.
* @param order The byte order. * @param order The byte order.
* @param value The value. * @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode.
* @throws IllegalArgumentException If the combination is invalid.
*/ */
public void put(DataType type, DataOrder order, Number value) { public void put(DataType type, DataOrder order, Number value) {
put(type, order, DataTransformation.NONE, value); put(type, order, DataTransformation.NONE, value);
@@ -190,8 +186,6 @@ public final class GamePacketBuilder {
* @param type The type. * @param type The type.
* @param transformation The transformation. * @param transformation The transformation.
* @param value The value. * @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode.
* @throws IllegalArgumentException If the combination is invalid.
*/ */
public void put(DataType type, DataTransformation transformation, Number value) { public void put(DataType type, DataTransformation transformation, Number value) {
put(type, DataOrder.BIG, transformation, value); put(type, DataOrder.BIG, transformation, value);
@@ -202,7 +196,6 @@ public final class GamePacketBuilder {
* *
* @param type The data type. * @param type The data type.
* @param value The value. * @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode.
*/ */
public void put(DataType type, Number value) { public void put(DataType type, Number value) {
put(type, DataOrder.BIG, DataTransformation.NONE, value); put(type, DataOrder.BIG, DataTransformation.NONE, value);
@@ -213,7 +206,6 @@ public final class GamePacketBuilder {
* {@code flag} is {@code false}, the value of the bit is {@code 0}. * {@code flag} is {@code false}, the value of the bit is {@code 0}.
* *
* @param flag The flag. * @param flag The flag.
* @throws IllegalStateException If the builder is not in bit access mode.
*/ */
public void putBit(boolean flag) { public void putBit(boolean flag) {
putBit(flag ? 1 : 0); putBit(flag ? 1 : 0);
@@ -223,7 +215,6 @@ public final class GamePacketBuilder {
* Puts a single bit into the buffer with the value {@code value}. * Puts a single bit into the buffer with the value {@code value}.
* *
* @param value The value. * @param value The value.
* @throws IllegalStateException If the builder is not in bit access mode.
*/ */
public void putBit(int value) { public void putBit(int value) {
putBits(1, value); putBits(1, value);
@@ -234,7 +225,6 @@ public final class GamePacketBuilder {
* *
* @param numBits The number of bits to put into the buffer. * @param numBits The number of bits to put into the buffer.
* @param value The value. * @param value The value.
* @throws IllegalStateException If the builder is not in bit access mode.
* @throws IllegalArgumentException If the number of bits is not between 1 and 31 inclusive. * @throws IllegalArgumentException If the number of bits is not between 1 and 31 inclusive.
*/ */
public void putBits(int numBits, int value) { public void putBits(int numBits, int value) {
@@ -276,7 +266,6 @@ public final class GamePacketBuilder {
* Puts the specified byte array into the buffer. * Puts the specified byte array into the buffer.
* *
* @param bytes The byte array. * @param bytes The byte array.
* @throws IllegalStateException If the builder is not in bit access mode.
*/ */
public void putBytes(byte[] bytes) { public void putBytes(byte[] bytes) {
buffer.writeBytes(bytes); buffer.writeBytes(bytes);
@@ -286,7 +275,6 @@ public final class GamePacketBuilder {
* Puts the bytes from the specified buffer into this packet's buffer. * Puts the bytes from the specified buffer into this packet's buffer.
* *
* @param buffer The source {@link ChannelBuffer}. * @param buffer The source {@link ChannelBuffer}.
* @throws IllegalStateException If the builder is not in byte access mode.
*/ */
public void putBytes(ChannelBuffer buffer) { public void putBytes(ChannelBuffer buffer) {
byte[] bytes = new byte[buffer.readableBytes()]; byte[] bytes = new byte[buffer.readableBytes()];
@@ -304,7 +292,6 @@ public final class GamePacketBuilder {
* *
* @param transformation The transformation. * @param transformation The transformation.
* @param bytes The byte array. * @param bytes The byte array.
* @throws IllegalStateException If the builder is not in byte access mode.
*/ */
public void putBytes(DataTransformation transformation, byte[] bytes) { public void putBytes(DataTransformation transformation, byte[] bytes) {
if (transformation == DataTransformation.NONE) { if (transformation == DataTransformation.NONE) {
@@ -320,7 +307,6 @@ public final class GamePacketBuilder {
* Puts the specified byte array into the buffer in reverse. * Puts the specified byte array into the buffer in reverse.
* *
* @param bytes The byte array. * @param bytes The byte array.
* @throws IllegalStateException If the builder is not in byte access mode.
*/ */
public void putBytesReverse(byte[] bytes) { public void putBytesReverse(byte[] bytes) {
checkByteAccess(); checkByteAccess();
@@ -333,7 +319,6 @@ public final class GamePacketBuilder {
* Puts the bytes from the specified buffer into this packet's buffer, in reverse. * Puts the bytes from the specified buffer into this packet's buffer, in reverse.
* *
* @param buffer The source {@link ChannelBuffer}. * @param buffer The source {@link ChannelBuffer}.
* @throws IllegalStateException If the builder is not in byte access mode.
*/ */
public void putBytesReverse(ChannelBuffer buffer) { public void putBytesReverse(ChannelBuffer buffer) {
byte[] bytes = new byte[buffer.readableBytes()]; byte[] bytes = new byte[buffer.readableBytes()];
@@ -351,7 +336,6 @@ public final class GamePacketBuilder {
* *
* @param transformation The transformation. * @param transformation The transformation.
* @param bytes The byte array. * @param bytes The byte array.
* @throws IllegalStateException If the builder is not in byte access mode.
*/ */
public void putBytesReverse(DataTransformation transformation, byte[] bytes) { public void putBytesReverse(DataTransformation transformation, byte[] bytes) {
if (transformation == DataTransformation.NONE) { if (transformation == DataTransformation.NONE) {
@@ -367,6 +351,7 @@ public final class GamePacketBuilder {
* Puts a raw builder. Both builders (this and parameter) must be in byte access mode. * Puts a raw builder. Both builders (this and parameter) must be in byte access mode.
* *
* @param builder The builder. * @param builder The builder.
* @throws IllegalArgumentException If the builder is not raw.
*/ */
public void putRawBuilder(GamePacketBuilder builder) { public void putRawBuilder(GamePacketBuilder builder) {
checkByteAccess(); checkByteAccess();
@@ -381,6 +366,7 @@ public final class GamePacketBuilder {
* Puts a raw builder in reverse. Both builders (this and parameter) must be in byte access mode. * Puts a raw builder in reverse. Both builders (this and parameter) must be in byte access mode.
* *
* @param builder The builder. * @param builder The builder.
* @throws IllegalArgumentException If the builder is not raw.
*/ */
public void putRawBuilderReverse(GamePacketBuilder builder) { public void putRawBuilderReverse(GamePacketBuilder builder) {
checkByteAccess(); checkByteAccess();
@@ -461,4 +447,4 @@ public final class GamePacketBuilder {
return new GamePacket(opcode, type, buffer); return new GamePacket(opcode, type, buffer);
} }
} }
@@ -1,5 +1,7 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import java.io.IOException;
import net.burtleburtle.bob.rand.IsaacRandom; import net.burtleburtle.bob.rand.IsaacRandom;
import org.apollo.net.meta.PacketMetaData; import org.apollo.net.meta.PacketMetaData;
@@ -57,7 +59,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, GameDecoderState state) protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, GameDecoderState state)
throws Exception { throws IOException {
switch (state) { switch (state) {
case GAME_OPCODE: case GAME_OPCODE:
return decodeOpcode(ctx, channel, buffer); return decodeOpcode(ctx, channel, buffer);
@@ -66,7 +68,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
case GAME_PAYLOAD: case GAME_PAYLOAD:
return decodePayload(ctx, channel, buffer); return decodePayload(ctx, channel, buffer);
default: default:
throw new Exception("Invalid game decoder state"); throw new IllegalStateException("Invalid game decoder state");
} }
} }
@@ -79,7 +81,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
private Object decodeLength(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { private Object decodeLength(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
if (buffer.readable()) { if (buffer.readable()) {
length = buffer.readUnsignedByte(); length = buffer.readUnsignedByte();
if (length == 0) { if (length == 0) {
@@ -98,16 +100,16 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @param channel The channel. * @param channel The channel.
* @param buffer The buffer. * @param buffer The buffer.
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws Exception If an error occurs. * @throws IOException If a received opcode or packet type is illegal.
*/ */
private Object decodeOpcode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { private Object decodeOpcode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws IOException {
if (buffer.readable()) { if (buffer.readable()) {
int encryptedOpcode = buffer.readUnsignedByte(); int encryptedOpcode = buffer.readUnsignedByte();
opcode = encryptedOpcode - random.nextInt() & 0xFF; opcode = encryptedOpcode - random.nextInt() & 0xFF;
PacketMetaData metaData = release.getIncomingPacketMetaData(opcode); PacketMetaData metaData = release.getIncomingPacketMetaData(opcode);
if (metaData == null) { if (metaData == null) {
throw new Exception("Illegal opcode: " + opcode); throw new IOException("Illegal opcode: " + opcode);
} }
type = metaData.getType(); type = metaData.getType();
@@ -124,7 +126,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
setState(GameDecoderState.GAME_LENGTH); setState(GameDecoderState.GAME_LENGTH);
break; break;
default: default:
throw new Exception("Illegal packet type: " + type); throw new IOException("Illegal packet type: " + type);
} }
} }
return null; return null;
@@ -139,7 +141,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
private Object decodePayload(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { private Object decodePayload(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
if (buffer.readableBytes() >= length) { if (buffer.readableBytes() >= length) {
ChannelBuffer payload = buffer.readBytes(length); ChannelBuffer payload = buffer.readBytes(length);
setState(GameDecoderState.GAME_OPCODE); setState(GameDecoderState.GAME_OPCODE);
@@ -158,11 +160,10 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
private Object decodeZeroLengthPacket(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) private Object decodeZeroLengthPacket(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
throws Exception {
ChannelBuffer payload = ChannelBuffers.buffer(0); ChannelBuffer payload = ChannelBuffers.buffer(0);
setState(GameDecoderState.GAME_OPCODE); setState(GameDecoderState.GAME_OPCODE);
return new GamePacket(opcode, type, payload); return new GamePacket(opcode, type, payload);
} }
} }
@@ -26,7 +26,7 @@ public final class HandshakeDecoder extends FrameDecoder {
} }
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
if (buffer.readable()) { if (buffer.readable()) {
int id = buffer.readUnsignedByte(); int id = buffer.readUnsignedByte();
@@ -43,7 +43,7 @@ public final class HandshakeDecoder extends FrameDecoder {
channel.write(buf); // TODO should it be here? channel.write(buf); // TODO should it be here?
break; break;
default: default:
throw new Exception("Invalid service id"); throw new IllegalArgumentException("Invalid service id");
} }
ctx.getPipeline().remove(this); ctx.getPipeline().remove(this);
@@ -52,10 +52,8 @@ public final class HandshakeDecoder extends FrameDecoder {
if (buffer.readable()) { if (buffer.readable()) {
return new Object[] { message, buffer.readBytes(buffer.readableBytes()) }; return new Object[] { message, buffer.readBytes(buffer.readableBytes()) };
} else {
return message;
} }
return message;
} }
return null; return null;
} }
@@ -12,17 +12,16 @@ import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;
public final class JagGrabRequestDecoder extends OneToOneDecoder { public final class JagGrabRequestDecoder extends OneToOneDecoder {
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception { protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) {
if (msg instanceof String) { if (msg instanceof String) {
String str = (String) msg; String str = (String) msg;
if (str.startsWith("JAGGRAB /")) { if (str.startsWith("JAGGRAB /")) {
String filePath = str.substring(8).trim(); String filePath = str.substring(8).trim();
return new JagGrabRequest(filePath); return new JagGrabRequest(filePath);
} else {
throw new Exception("corrupted request line");
} }
throw new IllegalArgumentException("corrupted request line");
} }
return msg; return msg;
} }
} }
@@ -12,7 +12,7 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
public final class JagGrabResponseEncoder extends OneToOneEncoder { public final class JagGrabResponseEncoder extends OneToOneEncoder {
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception { protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) {
if (msg instanceof JagGrabResponse) { if (msg instanceof JagGrabResponse) {
JagGrabResponse resp = (JagGrabResponse) msg; JagGrabResponse resp = (JagGrabResponse) msg;
return resp.getFileData(); return resp.getFileData();
@@ -20,4 +20,4 @@ public final class JagGrabResponseEncoder extends OneToOneEncoder {
return msg; return msg;
} }
} }
@@ -1,5 +1,6 @@
package org.apollo.net.codec.login; package org.apollo.net.codec.login;
import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.SecureRandom; import java.security.SecureRandom;
@@ -66,7 +67,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
case LOGIN_PAYLOAD: case LOGIN_PAYLOAD:
return decodePayload(ctx, channel, buffer); return decodePayload(ctx, channel, buffer);
default: default:
throw new IllegalArgumentException("Invalid login decoder state"); throw new IllegalStateException("Invalid login decoder state");
} }
} }
@@ -79,7 +80,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
private Object decodeHandshake(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { private Object decodeHandshake(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
if (buffer.readable()) { if (buffer.readable()) {
usernameHash = buffer.readUnsignedByte(); usernameHash = buffer.readUnsignedByte();
serverSeed = random.nextLong(); serverSeed = random.nextLong();
@@ -102,14 +103,14 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
* @param channel The channel. * @param channel The channel.
* @param buffer The buffer. * @param buffer The buffer.
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws Exception If an error occurs. * @throws IOException If the login type sent by the client is invalid.
*/ */
private Object decodeHeader(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { private Object decodeHeader(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws IOException {
if (buffer.readableBytes() >= 2) { if (buffer.readableBytes() >= 2) {
int loginType = buffer.readUnsignedByte(); int loginType = buffer.readUnsignedByte();
if (loginType != LoginConstants.TYPE_STANDARD && loginType != LoginConstants.TYPE_RECONNECTION) { if (loginType != LoginConstants.TYPE_STANDARD && loginType != LoginConstants.TYPE_RECONNECTION) {
throw new Exception("Invalid login type"); throw new IOException("Invalid login type");
} }
reconnecting = loginType == LoginConstants.TYPE_RECONNECTION; reconnecting = loginType == LoginConstants.TYPE_RECONNECTION;
@@ -7,14 +7,14 @@ import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
/** /**
* A class which encodes login response messsages. * A class which encodes login response messages.
* *
* @author Graham * @author Graham
*/ */
public final class LoginEncoder extends OneToOneEncoder { public final class LoginEncoder extends OneToOneEncoder {
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object message) throws Exception { protected Object encode(ChannelHandlerContext ctx, Channel channel, Object message) {
if (!(message instanceof LoginResponse)) { if (!(message instanceof LoginResponse)) {
return message; return message;
} }
@@ -31,4 +31,4 @@ public final class LoginEncoder extends OneToOneEncoder {
return buffer; return buffer;
} }
} }
@@ -15,7 +15,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder;
public final class UpdateDecoder extends FrameDecoder { public final class UpdateDecoder extends FrameDecoder {
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel c, ChannelBuffer buf) throws Exception { protected Object decode(ChannelHandlerContext ctx, Channel c, ChannelBuffer buf) {
if (buf.readableBytes() >= 4) { if (buf.readableBytes() >= 4) {
int type = buf.readUnsignedByte() + 1; int type = buf.readUnsignedByte() + 1;
int file = buf.readUnsignedShort(); int file = buf.readUnsignedShort();
@@ -29,4 +29,4 @@ public final class UpdateDecoder extends FrameDecoder {
return null; return null;
} }
} }
@@ -15,7 +15,7 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
public final class UpdateEncoder extends OneToOneEncoder { public final class UpdateEncoder extends OneToOneEncoder {
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception { protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) {
if (msg instanceof OnDemandResponse) { if (msg instanceof OnDemandResponse) {
OnDemandResponse resp = (OnDemandResponse) msg; OnDemandResponse resp = (OnDemandResponse) msg;
@@ -36,4 +36,4 @@ public final class UpdateEncoder extends OneToOneEncoder {
return msg; return msg;
} }
} }
+2 -2
View File
@@ -16,7 +16,7 @@ public final class PacketMetaData {
*/ */
public static PacketMetaData createFixed(int length) { public static PacketMetaData createFixed(int length) {
if (length < 0) { if (length < 0) {
throw new IllegalArgumentException(); throw new IllegalArgumentException("packet length cannot be less than 0");
} }
return new PacketMetaData(PacketType.FIXED, length); return new PacketMetaData(PacketType.FIXED, length);
} }
@@ -69,7 +69,7 @@ public final class PacketMetaData {
*/ */
public int getLength() { public int getLength() {
if (type != PacketType.FIXED) { if (type != PacketType.FIXED) {
throw new IllegalStateException(); throw new IllegalStateException("can only get the length of a fixed length packet");
} }
return length; return length;
} }
@@ -17,14 +17,14 @@ public final class PacketMetaDataGroup {
*/ */
public static PacketMetaDataGroup createFromArray(int[] lengthArray) { public static PacketMetaDataGroup createFromArray(int[] lengthArray) {
if (lengthArray.length != 256) { if (lengthArray.length != 256) {
throw new IllegalArgumentException(); throw new IllegalArgumentException("length array must be 256");
} }
PacketMetaDataGroup grp = new PacketMetaDataGroup(); PacketMetaDataGroup grp = new PacketMetaDataGroup();
for (int i = 0; i < lengthArray.length; i++) { for (int i = 0; i < lengthArray.length; i++) {
int length = lengthArray[i]; int length = lengthArray[i];
PacketMetaData metaData = null; PacketMetaData metaData = null;
if (length < -3) { if (length < -3) {
throw new IllegalArgumentException(); throw new IllegalArgumentException("no packet length can have a value less than -3");
} else if (length == -2) { } else if (length == -2) {
metaData = PacketMetaData.createVariableShort(); metaData = PacketMetaData.createVariableShort();
} else if (length == -1) { } else if (length == -1) {
@@ -54,13 +54,13 @@ public final class PacketMetaDataGroup {
* *
* @param opcode The opcode of the packet. * @param opcode The opcode of the packet.
* @return The {@link PacketMetaData}, or {@code null} if the packet does not exist. * @return The {@link PacketMetaData}, or {@code null} if the packet does not exist.
* @throws IllegalArgumentException If the opcoe is not in the range 0 to 255. * @throws IllegalArgumentException If the opcode is not in the range 0 to 255.
*/ */
public PacketMetaData getMetaData(int opcode) { public PacketMetaData getMetaData(int opcode) {
if (opcode < 0 || opcode >= packets.length) { if (opcode < 0 || opcode >= packets.length) {
throw new IllegalArgumentException(); throw new IllegalArgumentException("opcode is out of bounds");
} }
return packets[opcode]; return packets[opcode];
} }
} }
+1 -1
View File
@@ -27,4 +27,4 @@ public enum PacketType {
*/ */
VARIABLE_SHORT; VARIABLE_SHORT;
} }
+2 -2
View File
@@ -53,7 +53,7 @@ public abstract class Release {
*/ */
public final EventDecoder<?> getEventDecoder(int opcode) { public final EventDecoder<?> getEventDecoder(int opcode) {
if (opcode < 0 || opcode >= decoders.length) { if (opcode < 0 || opcode >= decoders.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("opcode is out of bounds");
} }
return decoders[opcode]; return decoders[opcode];
} }
@@ -106,7 +106,7 @@ public abstract class Release {
*/ */
public final <E extends Event> void register(int opcode, EventDecoder<E> decoder) { public final <E extends Event> void register(int opcode, EventDecoder<E> decoder) {
if (opcode < 0 || opcode >= decoders.length) { if (opcode < 0 || opcode >= decoders.length) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException("opcode is out of bounds");
} }
decoders[opcode] = decoder; decoders[opcode] = decoder;
} }
@@ -16,8 +16,22 @@ public class MouseClickEventDecoder extends EventDecoder<MouseClickEvent> {
@Override @Override
public MouseClickEvent decode(GamePacket packet) { public MouseClickEvent decode(GamePacket packet) {
GamePacketReader reader = new GamePacketReader(packet); GamePacketReader reader = new GamePacketReader(packet);
reader.getUnsigned(DataType.INT); int read;
return new MouseClickEvent(); if (reader.getLength() == 2) {
read = (int) reader.getUnsigned(DataType.SHORT);
int clickCount = (read >> 12);
int dX = (read >> 6) & 0x3f;
int dY = read & 0x3f;
return new MouseClickEvent(clickCount, dX, dY, true);
} else if (reader.getLength() == 3) {
read = (int) reader.getUnsigned(DataType.TRI_BYTE) & ~0x800000;
} else {
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
}
int clickCount = (read >> 19);
int x = (read & 0x7f) % 765;
int y = (read & 0x7f) / 765;
return new MouseClickEvent(clickCount, x, y, false);
} }
} }
@@ -16,7 +16,6 @@ public final class RegionChangeEventEncoder extends EventEncoder<RegionChangeEve
@Override @Override
public GamePacket encode(RegionChangeEvent event) { public GamePacket encode(RegionChangeEvent event) {
System.out.println("Sending region change event.");
GamePacketBuilder builder = new GamePacketBuilder(73); GamePacketBuilder builder = new GamePacketBuilder(73);
builder.put(DataType.SHORT, DataTransformation.ADD, event.getPosition().getCentralSectorX()); builder.put(DataType.SHORT, DataTransformation.ADD, event.getPosition().getCentralSectorX());
builder.put(DataType.SHORT, event.getPosition().getCentralSectorY()); builder.put(DataType.SHORT, event.getPosition().getCentralSectorY());
@@ -22,6 +22,7 @@ import org.apollo.game.event.impl.SetWidgetTextEvent;
import org.apollo.game.event.impl.SetWidgetVisibilityEvent; import org.apollo.game.event.impl.SetWidgetVisibilityEvent;
import org.apollo.game.event.impl.SwitchTabInterfaceEvent; import org.apollo.game.event.impl.SwitchTabInterfaceEvent;
import org.apollo.game.event.impl.UpdateItemsEvent; import org.apollo.game.event.impl.UpdateItemsEvent;
import org.apollo.game.event.impl.UpdateRunEnergyEvent;
import org.apollo.game.event.impl.UpdateSkillEvent; import org.apollo.game.event.impl.UpdateSkillEvent;
import org.apollo.game.event.impl.UpdateSlottedItemsEvent; import org.apollo.game.event.impl.UpdateSlottedItemsEvent;
import org.apollo.net.meta.PacketMetaDataGroup; import org.apollo.net.meta.PacketMetaDataGroup;
@@ -117,6 +118,7 @@ public final class Release317 extends Release {
SpamPacketEventDecoder spamEventDecoder = new SpamPacketEventDecoder(); SpamPacketEventDecoder spamEventDecoder = new SpamPacketEventDecoder();
register(77, spamEventDecoder); register(77, spamEventDecoder);
register(78, spamEventDecoder);
register(165, spamEventDecoder); register(165, spamEventDecoder);
register(189, spamEventDecoder); register(189, spamEventDecoder);
register(226, spamEventDecoder); register(226, spamEventDecoder);
@@ -151,6 +153,7 @@ public final class Release317 extends Release {
register(DisplayTabInterfaceEvent.class, new DisplayTabInterfaceEventEncoder()); register(DisplayTabInterfaceEvent.class, new DisplayTabInterfaceEventEncoder());
register(SetTileItemEvent.class, new SetTileItemEventEncoder()); register(SetTileItemEvent.class, new SetTileItemEventEncoder());
register(PositionEvent.class, new PositionEventEncoder()); register(PositionEvent.class, new PositionEventEncoder());
register(UpdateRunEnergyEvent.class, new UpdateRunEnergyEventEncoder());
} }
} }
@@ -0,0 +1,23 @@
package org.apollo.net.release.r317;
import org.apollo.game.event.impl.UpdateRunEnergyEvent;
import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketBuilder;
import org.apollo.net.release.EventEncoder;
/**
* An {@link EventEncoder} for the {@link UpdateRunEnergyEvent}
*
* @author Major
*/
public class UpdateRunEnergyEventEncoder extends EventEncoder<UpdateRunEnergyEvent> {
@Override
public GamePacket encode(UpdateRunEnergyEvent event) {
GamePacketBuilder builder = new GamePacketBuilder(110);
builder.put(DataType.BYTE, event.getEnergy());
return builder.toGamePacket();
}
}
@@ -16,8 +16,22 @@ public class MouseClickEventDecoder extends EventDecoder<MouseClickEvent> {
@Override @Override
public MouseClickEvent decode(GamePacket packet) { public MouseClickEvent decode(GamePacket packet) {
GamePacketReader reader = new GamePacketReader(packet); GamePacketReader reader = new GamePacketReader(packet);
reader.getUnsigned(DataType.INT); int read;
return new MouseClickEvent(); if (reader.getLength() == 2) {
read = (int) reader.getUnsigned(DataType.SHORT);
int clickCount = (read >> 12);
int dX = (read >> 6) & 0x3f;
int dY = read & 0x3f;
return new MouseClickEvent(clickCount, dX, dY, true);
} else if (reader.getLength() == 3) {
read = (int) reader.getUnsigned(DataType.TRI_BYTE) & ~0x800000;
} else {
read = (int) reader.getUnsigned(DataType.INT) & ~0xc0000000;
}
int clickCount = (read >> 19);
int x = (read & 0x7f) % 765;
int y = (read & 0x7f) / 765;
return new MouseClickEvent(clickCount, x, y, false);
} }
} }
@@ -21,10 +21,8 @@ final class PositionEventEncoder extends EventEncoder<PositionEvent> {
GamePacketBuilder builder = new GamePacketBuilder(75); GamePacketBuilder builder = new GamePacketBuilder(75);
Position base = event.getBase(), pos = event.getPosition(); Position base = event.getBase(), pos = event.getPosition();
int x = pos.getLocalX(base); builder.put(DataType.BYTE, DataTransformation.NEGATE, pos.getLocalX(base));
builder.put(DataType.BYTE, DataTransformation.NEGATE, x); builder.put(DataType.BYTE, DataTransformation.ADD, pos.getLocalY(base));
int y = pos.getLocalY(base);
builder.put(DataType.BYTE, DataTransformation.ADD, y);
return builder.toGamePacket(); return builder.toGamePacket();
} }
@@ -22,6 +22,7 @@ import org.apollo.game.event.impl.SetWidgetTextEvent;
import org.apollo.game.event.impl.SetWidgetVisibilityEvent; import org.apollo.game.event.impl.SetWidgetVisibilityEvent;
import org.apollo.game.event.impl.SwitchTabInterfaceEvent; import org.apollo.game.event.impl.SwitchTabInterfaceEvent;
import org.apollo.game.event.impl.UpdateItemsEvent; import org.apollo.game.event.impl.UpdateItemsEvent;
import org.apollo.game.event.impl.UpdateRunEnergyEvent;
import org.apollo.game.event.impl.UpdateSkillEvent; import org.apollo.game.event.impl.UpdateSkillEvent;
import org.apollo.game.event.impl.UpdateSlottedItemsEvent; import org.apollo.game.event.impl.UpdateSlottedItemsEvent;
import org.apollo.net.meta.PacketMetaDataGroup; import org.apollo.net.meta.PacketMetaDataGroup;
@@ -149,6 +150,7 @@ public final class Release377 extends Release {
register(DisplayTabInterfaceEvent.class, new DisplayTabInterfaceEventEncoder()); register(DisplayTabInterfaceEvent.class, new DisplayTabInterfaceEventEncoder());
register(SetTileItemEvent.class, new SetTileItemEventEncoder()); register(SetTileItemEvent.class, new SetTileItemEventEncoder());
register(PositionEvent.class, new PositionEventEncoder()); register(PositionEvent.class, new PositionEventEncoder());
register(UpdateRunEnergyEvent.class, new UpdateRunEnergyEventEncoder());
} }
} }
@@ -0,0 +1,23 @@
package org.apollo.net.release.r377;
import org.apollo.game.event.impl.UpdateRunEnergyEvent;
import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketBuilder;
import org.apollo.net.release.EventEncoder;
/**
* An {@link EventEncoder} for the {@link UpdateRunEnergyEvent}
*
* @author Major
*/
public class UpdateRunEnergyEventEncoder extends EventEncoder<UpdateRunEnergyEvent> {
@Override
public GamePacket encode(UpdateRunEnergyEvent event) {
GamePacketBuilder builder = new GamePacketBuilder(125);
builder.put(DataType.BYTE, event.getEnergy());
return builder.toGamePacket();
}
}
+3 -3
View File
@@ -58,7 +58,7 @@ public final class GameSession extends Session {
} }
@Override @Override
public void destroy() throws Exception { public void destroy() {
context.getService(GameService.class).unregisterPlayer(player); context.getService(GameService.class).unregisterPlayer(player);
} }
@@ -122,7 +122,7 @@ public final class GameSession extends Session {
} }
@Override @Override
public void messageReceived(Object message) throws Exception { public void messageReceived(Object message) {
Event event = (Event) message; Event event = (Event) message;
if (eventQueue.size() >= GameConstants.EVENTS_PER_PULSE) { if (eventQueue.size() >= GameConstants.EVENTS_PER_PULSE) {
logger.warning("Too many events in queue for game session, dropping..."); logger.warning("Too many events in queue for game session, dropping...");
@@ -131,4 +131,4 @@ public final class GameSession extends Session {
} }
} }
} }
+2 -2
View File
@@ -133,10 +133,10 @@ public final class LoginSession extends Session {
} }
@Override @Override
public void messageReceived(Object message) throws Exception { public void messageReceived(Object message) {
if (message.getClass() == LoginRequest.class) { if (message.getClass() == LoginRequest.class) {
handleLoginRequest((LoginRequest) message); handleLoginRequest((LoginRequest) message);
} }
} }
} }
+3 -5
View File
@@ -26,10 +26,8 @@ public abstract class Session {
/** /**
* Destroys this session. * Destroys this session.
*
* @throws Exception If an error occurs.
*/ */
public abstract void destroy() throws Exception; public abstract void destroy();
/** /**
* Gets the channel. * Gets the channel.
@@ -46,6 +44,6 @@ public abstract class Session {
* @param message The message. * @param message The message.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
public abstract void messageReceived(Object message) throws Exception; public abstract void messageReceived(Object message);
} }
@@ -32,12 +32,12 @@ public final class UpdateSession extends Session {
} }
@Override @Override
public void destroy() throws Exception { public void destroy() {
// TODO implement // TODO implement
} }
@Override @Override
public void messageReceived(Object message) throws Exception { public void messageReceived(Object message) {
UpdateDispatcher dispatcher = context.getService(UpdateService.class).getDispatcher(); UpdateDispatcher dispatcher = context.getService(UpdateService.class).getDispatcher();
if (message instanceof OnDemandRequest) { if (message instanceof OnDemandRequest) {
dispatcher.dispatch(getChannel(), (OnDemandRequest) message); dispatcher.dispatch(getChannel(), (OnDemandRequest) message);
@@ -46,8 +46,8 @@ public final class UpdateSession extends Session {
} else if (message instanceof HttpRequest) { } else if (message instanceof HttpRequest) {
dispatcher.dispatch(getChannel(), (HttpRequest) message); dispatcher.dispatch(getChannel(), (HttpRequest) message);
} else { } else {
throw new Exception("unknown message type"); throw new IllegalArgumentException("unknown message type");
} }
} }
} }
+4 -5
View File
@@ -53,7 +53,7 @@ public final class CharacterRepository<T extends Character> implements Iterable<
} }
} }
if (character == null) { if (character == null) {
throw new NoSuchElementException(); throw new NoSuchElementException("character does not exist");
} }
previousIndex = index; previousIndex = index;
index++; index++;
@@ -64,7 +64,7 @@ public final class CharacterRepository<T extends Character> implements Iterable<
@Override @Override
public void remove() { public void remove() {
if (previousIndex == -1) { if (previousIndex == -1) {
throw new IllegalStateException(); throw new IllegalStateException("cannot remove as the repository is empty");
} }
CharacterRepository.this.remove((T) characters[previousIndex]); CharacterRepository.this.remove((T) characters[previousIndex]);
previousIndex = -1; previousIndex = -1;
@@ -167,9 +167,8 @@ public final class CharacterRepository<T extends Character> implements Iterable<
character.setIndex(-1); character.setIndex(-1);
size--; size--;
return true; return true;
} else {
return false;
} }
return false;
} }
/** /**
@@ -181,4 +180,4 @@ public final class CharacterRepository<T extends Character> implements Iterable<
return size; return size;
} }
} }
+2 -2
View File
@@ -33,7 +33,7 @@ public final class EnumerationUtil {
@Override @Override
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException("cannot remove an element using this wrapper");
} }
}; };
@@ -46,4 +46,4 @@ public final class EnumerationUtil {
} }
} }
+49
View File
@@ -0,0 +1,49 @@
package org.apollo.util;
/**
* Represents a point on a 2-dimensional Cartesian plane.
*
* @author Major
*/
public final class Point {
/**
* The x coordinate.
*/
private final int x;
/**
* The y coordinate.
*/
private final int y;
/**
* Creates a new point with the specified coordinates.
*
* @param x The x coordinate.
* @param y The y coordinate.
*/
public Point(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Gets the x coordinate of this point.
*
* @return The x coordinate.
*/
public int getX() {
return x;
}
/**
* Gets the y coordinate of this point.
*
* @return The y coordinate.
*/
public int getY() {
return y;
}
}
@@ -67,14 +67,12 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecod
* @param buffer The cumulative buffer, which may contain zero or more bytes. * @param buffer The cumulative buffer, which may contain zero or more bytes.
* @param state The current state. The state may be changed by calling {@link #setState(Enum)}. * @param state The current state. The state may be changed by calling {@link #setState(Enum)}.
* @return The decoded frame, or {@code null} if not enough data was received. * @return The decoded frame, or {@code null} if not enough data was received.
* @throws Exception If an error occurs during decoding.
*/ */
protected abstract Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state) protected abstract Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state)
throws Exception; throws Exception;
@Override @Override
protected final Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) protected final Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
throws Exception {
return decodeLast(ctx, channel, buffer, state); return decodeLast(ctx, channel, buffer, state);
} }
@@ -87,10 +85,8 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecod
* @param buffer The cumulative buffer, which may contain zero or more bytes. * @param buffer The cumulative buffer, which may contain zero or more bytes.
* @param state The current state. The state may be changed by calling {@link #setState(Enum)}. * @param state The current state. The state may be changed by calling {@link #setState(Enum)}.
* @return The decoded frame, or {@code null} if not enough data was received. * @return The decoded frame, or {@code null} if not enough data was received.
* @throws Exception If an error occurs during decoding.
*/ */
protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state) protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state) {
throws Exception {
return null; return null;
} }
@@ -107,4 +103,4 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecod
this.state = state; this.state = state;
} }
} }
@@ -24,4 +24,4 @@ public interface PluginEnvironment {
*/ */
public void setContext(PluginContext context); public void setContext(PluginContext context);
} }
@@ -53,4 +53,4 @@ public final class RubyPluginEnvironment implements PluginEnvironment {
container.put("$ctx", context); container.put("$ctx", context);
} }
} }