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'
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|
player.play_animation Animation::WAVE
player.send_message "Hello, World!"
player.send_message("Hello, World!")
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.
*
* @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 a, b, c, d, e, f, g, h;
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 */
if (flag) {
if (hasSeed) {
a += rsl[i];
b += rsl[i + 1];
c += rsl[i + 2];
@@ -180,7 +180,7 @@ public final class IsaacRandom {
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) {
a += mem[i];
b += mem[i + 1];
@@ -302,4 +302,4 @@ public final class IsaacRandom {
return rsl[count];
}
}
}
@@ -1,5 +1,4 @@
/**
* 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.
*/
public static void main(String[] args) {
Server server = null;
try {
server = new Server();
Server server = new Server();
server.init(args.length == 1 ? args[0] : Release317.class.getName());
SocketAddress service = new InetSocketAddress(NetworkConstants.SERVICE_PORT);
+1 -1
View File
@@ -35,4 +35,4 @@ public abstract class Service {
*/
public abstract void start();
}
}
+12 -5
View File
@@ -1,6 +1,7 @@
package org.apollo;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
@@ -8,6 +9,7 @@ import java.util.logging.Logger;
import org.apollo.util.xml.XmlNode;
import org.apollo.util.xml.XmlParser;
import org.xml.sax.SAXException;
/**
* A class which manages {@link Service}s.
@@ -50,10 +52,15 @@ public final class ServiceManager {
/**
* 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")
private void init() throws Exception {
private void init() throws SAXException, IOException, InstantiationException, IllegalAccessException,
ClassNotFoundException {
logger.info("Registering services...");
XmlParser parser = new XmlParser();
@@ -67,16 +74,16 @@ public final class ServiceManager {
}
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) {
if (!childNode.getName().equals("service")) {
throw new Exception("unexpected name of child node");
throw new IOException("unexpected name of child node");
}
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());
+13 -14
View File
@@ -40,10 +40,10 @@ public final class IndexedFileSystem implements Closeable {
* Creates the file system with the specified base directory.
*
* @param base The base directory.
* @param readOnly A flag indicating if the file system will be read only.
* @throws Exception If the file system is invalid.
* @param readOnly Indicates whether the file system will be read only or not.
* @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;
detectLayout(base);
}
@@ -69,9 +69,9 @@ public final class IndexedFileSystem implements Closeable {
* Automatically detect the layout of the specified 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;
for (int index = 0; index < indices.length; 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) {
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");
@@ -91,7 +91,7 @@ public final class IndexedFileSystem implements Closeable {
} else if (newEngineData.exists() && !oldEngineData.isDirectory()) {
data = new RandomAccessFile(newEngineData, readOnly ? "r" : "rw");
} 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.
*
* @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 {
if (readOnly) {
@@ -146,9 +146,8 @@ public final class IndexedFileSystem implements Closeable {
crcTable = buf.asReadOnlyBuffer();
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 {
if (type < 0 || type >= indices.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("file type out of bounds");
}
RandomAccessFile indexFile = indices[type];
@@ -269,7 +268,7 @@ public final class IndexedFileSystem implements Closeable {
private Index getIndex(FileDescriptor fd) throws IOException {
int index = fd.getType();
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];
@@ -280,7 +279,7 @@ public final class IndexedFileSystem implements Closeable {
indexFile.seek(ptr);
indexFile.readFully(buffer);
} else {
throw new FileNotFoundException();
throw new FileNotFoundException("could not find find index");
}
}
@@ -296,4 +295,4 @@ public final class IndexedFileSystem implements Closeable {
return readOnly;
}
}
}
+2 -2
View File
@@ -93,7 +93,7 @@ public final class Archive {
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;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -21,6 +22,7 @@ import org.apollo.net.session.GameSession;
import org.apollo.util.NamedThreadFactory;
import org.apollo.util.xml.XmlNode;
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.
@@ -88,9 +90,15 @@ public final class GameService extends 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");
try {
EventHandlerChainParser chainGroupParser = new EventHandlerChainParser(is);
@@ -105,12 +113,12 @@ public final class GameService extends Service {
XmlNode rootNode = parser.parse(is);
if (!rootNode.getName().equals("synchronizer")) {
throw new Exception("Invalid root node name.");
throw new IOException("Invalid root node name.");
}
XmlNode activeNode = rootNode.getChild("active");
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());
@@ -186,4 +194,4 @@ public final class GameService extends Service {
oldPlayers.add(player);
}
}
}
@@ -36,7 +36,7 @@ public final class BankEventHandler extends EventHandler<ItemActionEvent> {
case 5:
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;
/**
* 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
*/
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;
/**
* Creates a new focus position event.
* Creates a new position event.
*
* @param base The base from which the position is being focused 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]);
/**
* The array of clothing/skin colours.
* The array of clothing/skin colors.
*/
private final int[] colors;
@@ -37,7 +37,7 @@ public final class Appearance {
*/
public Appearance(Gender gender, int[] style, int[] colors) {
if (gender == null || style == null || colors == null) {
throw new NullPointerException();
throw new NullPointerException("no arguments can be null");
}
if (style.length != 7) {
throw new IllegalArgumentException("the style array must have 7 elements");
@@ -74,11 +74,7 @@ public final class Appearance {
* @return The player's styles.
*/
public int[] getStyle() {
/*
* Info on the elements of the array itself:
*
* 0 = head 1 = chin/beard 2 = chest 3 = arms 4 = hands 5 = legs 6 = feet
*/
// 0 = head 1 = chin/beard 2 = chest 3 = arms 4 = hands 5 = legs 6 = feet
return style;
}
@@ -100,4 +96,4 @@ public final class Appearance {
return gender == Gender.MALE;
}
}
}
+7 -16
View File
@@ -17,12 +17,12 @@ import org.apollo.util.CharacterRepository;
*
* @author Graham
*/
public abstract class Character {
public abstract class Character implements Entity {
/**
* The character's current action.
*/
private Action<?> action; // TODO
private Action<?> action;
/**
* The character's bank.
@@ -130,14 +130,10 @@ public abstract class Character {
*/
public Direction[] getDirections() {
if (firstDirection != Direction.NONE) {
if (secondDirection != Direction.NONE) {
return new Direction[] { firstDirection, secondDirection };
} else {
return new Direction[] { firstDirection };
}
} else {
return Direction.EMPTY_DIRECTION_ARRAY;
return secondDirection == Direction.NONE ? new Direction[] { firstDirection } : new Direction[] {
firstDirection, secondDirection };
}
return Direction.EMPTY_DIRECTION_ARRAY;
}
/**
@@ -205,11 +201,7 @@ public abstract class Character {
return definition;
}
/**
* Gets the position of this character.
*
* @return The position of this character.
*/
@Override
public Position getPosition() {
return position;
}
@@ -365,8 +357,7 @@ public abstract class Character {
stopAction();
}
this.action = action;
World.getWorld().schedule(action);
return true; // TODO maybe this should be incorporated into the action class itself?
return World.getWorld().schedule(action);
}
/**
+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;
}
}
}
+1 -1
View File
@@ -86,4 +86,4 @@ public final class Graphic {
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;
}
@Override
public EntityType getEntityType() {
return EntityType.NPC;
}
/**
* Gets this npc's {@link NpcDefinition}
*
+48 -8
View File
@@ -1,8 +1,8 @@
package org.apollo.game.model;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Queue;
import org.apollo.game.event.Event;
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.SetWidgetTextEvent;
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.inv.AppearanceInventoryListener;
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.net.session.GameSession;
import org.apollo.security.PlayerCredentials;
import org.apollo.util.Point;
/**
* 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;
/**
* A {@link List} of this player's mouse clicks.
*/
private Deque<Point> clicks = new ArrayDeque<Point>();
/**
* The player's credentials.
*/
@@ -151,7 +160,7 @@ public final class Player extends Character {
/**
* 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.
@@ -195,6 +204,16 @@ public final class Player extends Character {
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.
*/
@@ -227,6 +246,15 @@ public final class Player extends Character {
return appearance;
}
/**
* Gets the {@link Deque} of clicks.
*
* @return The deque.
*/
public Deque<Point> getClicks() {
return clicks;
}
/**
* Gets the player's credentials.
*
@@ -245,6 +273,11 @@ public final class Player extends Character {
return credentials.getEncodedUsername();
}
@Override
public EntityType getEntityType() {
return EntityType.PLAYER;
}
/**
* Gets the player's head icon.
*
@@ -263,6 +296,15 @@ public final class Player extends Character {
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.
*
@@ -378,8 +420,6 @@ public final class Player extends Character {
Inventory bank = getBank();
Inventory equipment = getEquipment();
// TODO only add bank listener when it is open? (like Hyperion)
// inventory full listeners
InventoryListener fullInventoryListener = new FullInventoryListener(this,
FullInventoryListener.FULL_INVENTORY_MESSAGE);
@@ -509,7 +549,6 @@ public final class Player extends Character {
* Sends the initial events.
*/
private void sendInitialEvents() {
// vital initial stuff
send(new IdAssignmentEvent(getIndex(), members)); // TODO should this be sent when we reconnect?
sendMessage("Welcome to RuneScape.");
@@ -546,7 +585,7 @@ public final class Player extends Character {
public void sendQuestInterface(List<String> text) {
int size = text.size(), lines = InterfaceConstants.QUEST_TEXT.length;
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++) {
@@ -635,6 +674,7 @@ public final class Player extends Character {
*/
public void setRunEnergy(int 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) {
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.
*/
@@ -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.
*/
@@ -221,7 +221,7 @@ public final class Position {
@Override
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];
}
/**
* 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.
*/
@@ -184,4 +194,4 @@ public final class Skill {
return maximumLevel;
}
}
}
+50 -56
View File
@@ -15,7 +15,7 @@ public final class SkillSet {
/**
* The maximum allowed experience.
*/
public static final double MAXIMUM_EXP = 200000000;
public static final double MAXIMUM_EXP = 200_000_000;
/**
* The number of skills.
@@ -60,6 +60,11 @@ public final class SkillSet {
return 99;
}
/**
* The combat level for this skill set.
*/
private int combatLevel = 3;
/**
* A flag indicating if events are being fired.
*/
@@ -94,23 +99,18 @@ public final class SkillSet {
Skill old = skills[id];
double newExperience = old.getExperience() + experience;
if (newExperience > MAXIMUM_EXP) {
newExperience = MAXIMUM_EXP;
}
newExperience = newExperience > MAXIMUM_EXP ? MAXIMUM_EXP : newExperience;
int newCurrentLevel = old.getCurrentLevel();
int newMaximumLevel = getLevelForExperience(newExperience);
int delta = newMaximumLevel - old.getMaximumLevel();
if (delta > 0) {
newCurrentLevel += delta;
}
newCurrentLevel += delta > 0 ? delta : 0;
setSkill(id, new Skill(newExperience, newCurrentLevel, newMaximumLevel));
if (delta > 0) {
// here so it gets updated skill
// here so it notifies using the updated skill
notifyLevelledUp(id);
}
}
@@ -120,27 +120,8 @@ public final class SkillSet {
*
* @param listener The listener to add.
*/
public void addListener(SkillListener listener) {
listeners.add(listener);
}
/**
* Checks the bounds of the id.
*
* @param id The id.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/
private void checkBounds(int id) {
if (id < 0 || id >= skills.length) {
throw new IndexOutOfBoundsException();
}
}
/**
* Forces this skill set to refresh.
*/
public void forceRefresh() {
notifySkillsUpdated();
public boolean addListener(SkillListener listener) {
return listeners.add(listener);
}
/**
@@ -148,12 +129,7 @@ public final class SkillSet {
*
* @return The combat level.
*/
/**
* Gets the combat level for this skill set.
*
* @return The combat level.
*/
public int getCombatLevel() {
public void calculateCombatLevel() {
int attack = skills[Skill.ATTACK].getMaximumLevel();
int defence = skills[Skill.DEFENCE].getMaximumLevel();
int strength = skills[Skill.STRENGTH].getMaximumLevel();
@@ -170,7 +146,35 @@ public final class SkillSet {
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.
* @return The skill.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/
public Skill getSkill(int id) {
checkBounds(id);
@@ -202,13 +205,8 @@ public final class SkillSet {
* Initialises the skill set.
*/
private void init() {
for (int i = 0; i < skills.length; i++) {
if (i == Skill.HITPOINTS) {
skills[i] = new Skill(1154, 10, 10);
} else {
skills[i] = new Skill(0, 1, 1);
}
// DO NOT CALL notifyXXX here!!
for (int id = 0; id < skills.length; id++) {
skills[id] = id == Skill.HITPOINTS ? new Skill(1154, 10, 10) : new Skill(0, 1, 1);
}
}
@@ -216,10 +214,9 @@ public final class SkillSet {
* Normalizes the skills in this set.
*/
public void normalize() {
for (int i = 0; i < skills.length; i++) {
// TODO I think prayer works differently(?)
int cur = skills[i].getCurrentLevel();
int max = skills[i].getMaximumLevel();
for (int id = 0; id < skills.length; id++) {
int cur = skills[id].getCurrentLevel();
int max = skills[id].getMaximumLevel();
if (cur > max) {
cur--;
@@ -229,7 +226,7 @@ public final class SkillSet {
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.
*
* @param id The skill's id.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/
private void notifyLevelledUp(int id) {
checkBounds(id);
@@ -263,7 +259,6 @@ public final class SkillSet {
* Notifies listeners that a skill has been updated.
*
* @param id The skill's id.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/
private void notifySkillUpdated(int id) {
checkBounds(id);
@@ -286,8 +281,8 @@ public final class SkillSet {
*
* @param listener The listener to remove.
*/
public void removeListener(SkillListener listener) {
listeners.remove(listener);
public boolean removeListener(SkillListener listener) {
return listeners.remove(listener);
}
/**
@@ -295,7 +290,6 @@ public final class SkillSet {
*
* @param id The id.
* @param skill The skill.
* @throws IndexOutOfBoundsException If the id is out of bounds.
*/
public void setSkill(int id, Skill skill) {
checkBounds(id);
@@ -326,4 +320,4 @@ public final class SkillSet {
firingEvents = false;
}
}
}
+1 -1
View File
@@ -46,4 +46,4 @@ public final class SlottedItem {
return slot;
}
}
}
+77 -32
View File
@@ -4,6 +4,8 @@ import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
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.ObjectDefinition;
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.Scheduler;
import org.apollo.io.EquipmentDefinitionParser;
@@ -92,11 +97,25 @@ public final class World {
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;
/**
* This world's {@link SectorRepository}.
*/
private final SectorRepository repository = new SectorRepository(false);
/**
* The scheduler.
*/
@@ -127,12 +146,20 @@ public final class World {
}
/**
* Gets the character repository. NOTE: {@link CharacterRepository#add(Character)} and
* {@link CharacterRepository#remove(Character)} should not be called directly! These mutation methods are not
* guaranteed to work in future releases!
* Gets the {@link Player} with the specified username.
*
* @param username The username.
* @return The player.
*/
public Player getPlayer(String username) {
return players.get(username);
}
/**
* Gets the character repository.
* <p>
* Instead, use the {@link World#register(Player)} and {@link World#unregister(Player)} methods which do the same
* thing and will continue to work as normal in future releases.
* Note: players should be registered and unregistered using {@link World#register(Player)} and
* {@link World#unregister(Player)} respectively, not by adding to or removing from this repository directly.
*
* @return The character repository.
*/
@@ -158,9 +185,9 @@ public final class World {
* @throws IOException If an I/O error occurs.
*/
public void init(int release, IndexedFileSystem fs, PluginManager manager) throws IOException {
ItemDefinitionDecoder itemParser = new ItemDefinitionDecoder(fs);
ItemDefinition[] itemDefs = itemParser.decode();
this.releaseNumber = release;
ItemDefinitionDecoder itemDefParser = new ItemDefinitionDecoder(fs);
ItemDefinition[] itemDefs = itemDefParser.decode();
ItemDefinition.init(itemDefs);
logger.info("Loaded " + itemDefs.length + " item definitions.");
@@ -174,42 +201,51 @@ public final class World {
is.close();
}
NpcDefinitionDecoder parser = new NpcDefinitionDecoder(fs);
NpcDefinition[] npcDefs = parser.decode();
NpcDefinitionDecoder npcDefParser = new NpcDefinitionDecoder(fs);
NpcDefinition[] npcDefs = npcDefParser.decode();
NpcDefinition.init(npcDefs);
logger.info("Loaded " + npcDefs.length + " npc definitions.");
ObjectDefinitionDecoder objParser = new ObjectDefinitionDecoder(fs);
ObjectDefinition[] objDefs = objParser.decode();
ObjectDefinitionDecoder objDefParser = new ObjectDefinitionDecoder(fs);
ObjectDefinition[] objDefs = objDefParser.decode();
ObjectDefinition.init(objDefs);
logger.info("Loaded " + objDefs.length + " object definitions.");
StaticObjectDecoder objectParser = new StaticObjectDecoder(fs);
StaticObject[] objects = objectParser.decode();
StaticObject.init(objects);
placeEntities(objects);
logger.info("Loaded " + objects.length + " static objects.");
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.
* @return {@code true} if so, {@code false} if not.
* @param name The name.
* @return {@code true} if the player is online, otherwise {@code false}.
*/
public boolean isPlayerOnline(String name) {
// TODO: use a hash set or map in the future?
for (Player player : playerRepository) {
if (player.getName().equalsIgnoreCase(name)) {
return true;
}
}
return false;
return getPlayer(name) != null;
}
/**
* 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() {
scheduler.pulse();
@@ -242,7 +278,7 @@ public final class World {
return RegistrationStatus.ALREADY_ONLINE;
}
boolean success = playerRepository.add(player);
boolean success = playerRepository.add(player) & players.put(player.getName(), player) == null;
if (success) {
logger.info("Registered player: " + player + " [online=" + playerRepository.size() + "]");
return RegistrationStatus.OK;
@@ -252,13 +288,22 @@ public final class World {
return RegistrationStatus.WORLD_FULL;
}
/**
* Gets the release number of this world.
*
* @return The release number.
*/
public int getReleaseNumber() {
return releaseNumber;
}
/**
* Schedules a new task.
*
* @param task The {@link ScheduledTask}.
*/
public void schedule(ScheduledTask task) {
scheduler.schedule(task);
public boolean schedule(ScheduledTask task) {
return scheduler.schedule(task);
}
/**
@@ -268,7 +313,7 @@ public final class World {
*/
public void unregister(Npc npc) {
if (npcRepository.remove(npc)) {
logger.info("Unregistered npc: " + npc + " [online=" + npcRepository.size() + "]");
logger.info("Unregistered npc: " + npc + " [count=" + npcRepository.size() + "]");
} else {
logger.warning("Could not find npc " + npc + " to unregister!");
}
@@ -280,10 +325,10 @@ public final class World {
* @param player The 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() + "]");
} 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) {
if (id < 0 || id >= definitions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("item id is out of bounds");
}
return definitions[id];
}
@@ -189,7 +189,7 @@ public final class ItemDefinition {
*/
public String getGroundAction(int id) {
if (id < 0 || id >= groundActions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("ground action id is out of bounds");
}
return groundActions[id];
}
@@ -212,7 +212,7 @@ public final class ItemDefinition {
*/
public String getInventoryAction(int id) {
if (id < 0 || id >= inventoryActions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("inventory action id is out of bounds");
}
return inventoryActions[id];
}
@@ -307,7 +307,7 @@ public final class ItemDefinition {
*/
public void setGroundAction(int id, String action) {
if (id < 0 || id >= groundActions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("ground action id is out of bounds");
}
groundActions[id] = action;
}
@@ -321,7 +321,7 @@ public final class ItemDefinition {
*/
public void setInventoryAction(int id, String action) {
if (id < 0 || id >= inventoryActions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("inventory action id is out of bounds");
}
inventoryActions[id] = action;
}
@@ -57,7 +57,7 @@ public final class NpcDefinition {
*/
public static NpcDefinition lookup(int id) {
if (id < 0 || id >= definitions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("npc id is out of bounds");
}
return definitions[id];
}
@@ -142,7 +142,7 @@ public final class NpcDefinition {
*/
public String getInteraction(int slot) {
if (slot < 0 || slot >= interactions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("npc interaction id is out of bounds");
}
return interactions[slot];
}
@@ -237,7 +237,7 @@ public final class NpcDefinition {
*/
public boolean hasInteraction(int slot) {
if (slot < 0 || slot >= interactions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("npc interaction id is out of bounds");
}
return interactions[slot] != null;
}
@@ -314,7 +314,7 @@ public final class NpcDefinition {
*/
public void setInteraction(int slot, String interaction) {
if (slot < 0 || slot >= interactions.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("npc interaction id is out of bounds");
}
interactions[slot] = interaction;
}
@@ -1,4 +1,4 @@
package org.apollo.game.model;
package org.apollo.game.model.inter;
/**
* Contains interface-related constants.
@@ -21,6 +21,12 @@ public class InterfaceConstants {
// 4445 = settings tab, music disabled
// 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.
*/
@@ -1,4 +1,4 @@
package org.apollo.game.model;
package org.apollo.game.model.inter;
import java.util.HashMap;
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.OpenInterfaceEvent;
import org.apollo.game.event.impl.OpenInterfaceSidebarEvent;
import org.apollo.game.model.inter.EnterAmountListener;
import org.apollo.game.model.inter.InterfaceListener;
import org.apollo.game.model.Player;
/**
* 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).
* <p>
* <ul>
* <li><strong>Windows:</strong> the ones people mostly associate with the word interfaces. Things like your bank, the
* wildy warning screen, the trade screen, etc.</li>
* <li><strong>Overlays:</strong> display in the same place as windows, but don't prevent you from moving. For example,
* <li><strong>Windows:</strong> Interfaces such as the bank, the wilderness 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.
* the wilderness level indicator.</li>
* <li><strong>Dialogues:</strong> interfaces which are displayed over the chat box.</li>
* <li><strong>Sidebars:</strong> an interface which displays 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 background:</strong> an interface displayed behind the fullscreen window, typically a blank,
* <li><strong>Dialogues:</strong> Interfaces displayed over the chat box.</li>
* <li><strong>Sidebars:</strong> Interfaces displayed over the inventory area.</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> Interfaces displayed behind the fullscreen window, typically a blank,
* black screen.</li>
* </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;
+21 -2
View File
@@ -1,5 +1,8 @@
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;
/**
@@ -7,20 +10,26 @@ import org.apollo.game.model.def.ObjectDefinition;
*
* @author Major
*/
public final class GameObject {
public final class GameObject implements Entity {
/**
* The object definition.
*/
private final ObjectDefinition definition;
/**
* The position of the game object.
*/
private final Position position;
/**
* Creates the game object.
*
* @param definition The object's definition.
*/
public GameObject(ObjectDefinition definition) {
public GameObject(ObjectDefinition definition, Position position) {
this.definition = definition;
this.position = position;
}
/**
@@ -32,4 +41,14 @@ public final class GameObject {
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;
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;
/**
* Represents a static object in the game world.
*
* @author Graham
* @author Chris Fletcher
* @author Major
*/
public final class StaticObject {
/**
* Initialises the static objects.
*/
public static void init(StaticObject[] objects) {
}
public final class StaticObject implements Entity {
/**
* The object's definition.
@@ -26,7 +21,7 @@ public final class StaticObject {
/**
* The object's id.
*/
private final short id;
private final int id;
/**
* The object's position.
@@ -36,12 +31,12 @@ public final class StaticObject {
/**
* The object's rotation.
*/
private final byte rotation;
private final int rotation;
/**
* The object type.
*/
private final byte type;
private final int type;
/**
* Creates a new static object.
@@ -52,10 +47,10 @@ public final class StaticObject {
* @param rotation The rotation of the object.
*/
public StaticObject(int id, Position position, int type, int rotation) {
this.id = (short) id;
this.id = id;
this.position = position;
this.type = (byte) type;
this.rotation = (byte) rotation;
this.type = type;
this.rotation = rotation;
definition = ObjectDefinition.lookup(id);
}
@@ -68,6 +63,11 @@ public final class StaticObject {
return definition;
}
@Override
public EntityType getEntityType() {
return EntityType.STATIC_OBJECT;
}
/**
* Gets the id of the object.
*
@@ -106,7 +106,7 @@ public final class StaticObject {
@Override
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;
import java.util.ArrayList;
import java.util.List;
import org.apollo.game.model.Entity;
/**
* Represents an 8x8 area of the map.
*
* @author Graham
* @author Major
*/
public final class Sector {
@@ -17,6 +22,11 @@ public final class Sector {
*/
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.
*
@@ -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() {
return coordinates.getX();
public boolean addEntity(Entity entity) {
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() {
return coordinates.getY();
public SectorCoordinates getCoordinates() {
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;
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
*/
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;
/**
* The y coordinate.
* The y coordinate of this sector.
*/
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.
*/
@@ -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.
*/
@@ -63,10 +76,7 @@ public final class SectorCoordinates {
@Override
public int hashCode() {
int hash = 7;
hash = 61 * hash + x;
hash = 61 * hash + y;
return hash;
return 61 * (427 + x) + y;
}
}
@@ -1,10 +1,103 @@
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);
player.sendMessage("You've just advanced " + article + " " + name + " level! You have reached level "
+ skill.getMaximumLevel() + ".");
if (Skill.isCombatSkill(id)) {
player.getSkillSet().calculateCombatLevel();
}
}
}
}
@@ -67,7 +67,7 @@ public abstract class ScheduledTask {
*/
public void setDelay(int delay) {
if (delay < 0) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("delay cannot be less than 0");
}
this.delay = delay;
}
@@ -46,8 +46,8 @@ public final class Scheduler {
*
* @param task The task to schedule.
*/
public void schedule(ScheduledTask task) {
newTasks.add(task);
public boolean schedule(ScheduledTask task) {
return newTasks.add(task);
}
}
}
@@ -30,12 +30,12 @@ public class ForceMovementBlock extends SynchronizationBlock {
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;
/**
* 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;
@@ -44,8 +44,8 @@ public class ForceMovementBlock extends SynchronizationBlock {
*
* @param initialPosition The initial {@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 travelDurationY The length of time (in game ticks) the player's movement along the Y 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 pulses) the player's movement along the Y axis will last.
* @param direction The direction the player should move.
*/
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.
*/
@@ -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.
*/
@@ -49,8 +49,8 @@ public final class MovementSegment extends SynchronizationSegment {
case 2:
return SegmentType.RUN;
default:
throw new IllegalStateException();
throw new IllegalStateException("direction type unsupported");
}
}
}
}
@@ -45,10 +45,6 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
player.getWalkingQueue().pulse();
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();
}
@@ -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;
}
}
@@ -33,7 +33,7 @@ public final class BinaryPlayerLoader implements PlayerLoader {
private static final Position SPAWN_POSITION = new Position(3222, 3222);
@Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception {
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws IOException {
File f = BinaryPlayerUtil.getFile(credentials.getUsername());
if (!f.exists()) {
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));
try {
// read credentials nad privileges
// read credentials and privileges
String name = 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 {
@Override
public void savePlayer(Player player) throws Exception {
public void savePlayer(Player player) throws IOException {
File f = BinaryPlayerUtil.getFile(player.getName());
DataOutputStream out = new DataOutputStream(new FileOutputStream(f));
try {
@@ -11,8 +11,8 @@ import org.apollo.io.player.PlayerSaver;
public final class DiscardPlayerSaver implements PlayerSaver {
@Override
public void savePlayer(Player player) throws Exception {
public void savePlayer(Player player) {
/* discard player */
}
}
}
@@ -21,7 +21,7 @@ public final class DummyPlayerLoader implements PlayerLoader {
private static final Position DEFAULT_POSITION = new Position(3222, 3222);
@Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception {
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) {
int status = LoginConstants.STATUS_OK;
Player player = new Player(credentials, DEFAULT_POSITION);
@@ -31,4 +31,4 @@ public final class DummyPlayerLoader implements PlayerLoader {
return new PlayerLoaderResponse(status, player);
}
}
}
@@ -8,8 +8,7 @@ public final class JdbcPlayerLoader implements PlayerLoader {
@Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception {
return null;
}
}
}
+12 -5
View File
@@ -1,6 +1,7 @@
package org.apollo.login;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -18,6 +19,7 @@ import org.apollo.net.session.LoginSession;
import org.apollo.util.NamedThreadFactory;
import org.apollo.util.xml.XmlNode;
import org.apollo.util.xml.XmlParser;
import org.xml.sax.SAXException;
/**
* The {@link LoginService} manages {@link LoginRequest}s.
@@ -53,9 +55,14 @@ public final class LoginService extends 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();
XmlNode rootNode;
@@ -67,17 +74,17 @@ public final class LoginService extends Service {
}
if (!rootNode.getName().equals("login")) {
throw new Exception("unexpected root node name");
throw new IOException("unexpected root node name");
}
XmlNode loaderNode = rootNode.getChild("loader");
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");
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());
+6 -6
View File
@@ -47,14 +47,14 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel channel = ctx.getChannel();
logger.info("Channel connected: " + channel);
serverContext.getChannelGroup().add(channel);
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel channel = ctx.getChannel();
logger.info("Channel disconnected: " + channel);
serverContext.getChannelGroup().remove(channel);
@@ -65,18 +65,18 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
}
@Override
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) {
e.getChannel().close();
}
@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());
ctx.getChannel().close();
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if (ctx.getAttachment() == null) {
Object msg = e.getMessage();
if (msg instanceof HttpRequest || msg instanceof JagGrabRequest) {
@@ -94,7 +94,7 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
ctx.setAttachment(new UpdateSession(ctx.getChannel(), serverContext));
break;
default:
throw new Exception("Invalid service id");
throw new IllegalStateException("Invalid service id");
}
}
} else {
+2 -2
View File
@@ -43,7 +43,7 @@ public final class HttpPipelineFactory implements ChannelPipelineFactory {
}
@Override
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
// decoders
@@ -60,4 +60,4 @@ public final class HttpPipelineFactory implements ChannelPipelineFactory {
return pipeline;
}
}
}
@@ -66,7 +66,7 @@ public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
}
@Override
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
// decoders
@@ -84,4 +84,4 @@ public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
return pipeline;
}
}
}
@@ -36,7 +36,7 @@ public final class ServicePipelineFactory implements ChannelPipelineFactory {
}
@Override
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("handshakeDecoder", new HandshakeDecoder());
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0));
@@ -44,4 +44,4 @@ public final class ServicePipelineFactory implements ChannelPipelineFactory {
return pipeline;
}
}
}
@@ -29,7 +29,7 @@ public final class GameEventDecoder extends OneToOneDecoder {
}
@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) {
GamePacket packet = (GamePacket) msg;
EventDecoder<?> decoder = release.getEventDecoder(packet.getOpcode());
@@ -30,7 +30,7 @@ public final class GameEventEncoder extends OneToOneEncoder {
@SuppressWarnings("unchecked")
@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) {
Event event = (Event) msg;
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.
*
* @return The length of the buffer.
* @throws IllegalStateException If the builder is not in byte access mode.
*/
public int getLength() {
checkByteAccess();
@@ -105,8 +104,7 @@ public final class GamePacketBuilder {
* @param order The byte order.
* @param transformation The transformation.
* @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode.
* @throws IllegalArgumentException If the combination is invalid.
* @throws IllegalArgumentException If the type, order, or transformation is unknown.
*/
public void put(DataType type, DataOrder order, DataTransformation transformation, Number value) {
checkByteAccess();
@@ -177,8 +175,6 @@ public final class GamePacketBuilder {
* @param type The data type.
* @param order The byte order.
* @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode.
* @throws IllegalArgumentException If the combination is invalid.
*/
public void put(DataType type, DataOrder order, Number value) {
put(type, order, DataTransformation.NONE, value);
@@ -190,8 +186,6 @@ public final class GamePacketBuilder {
* @param type The type.
* @param transformation The transformation.
* @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode.
* @throws IllegalArgumentException If the combination is invalid.
*/
public void put(DataType type, DataTransformation transformation, Number value) {
put(type, DataOrder.BIG, transformation, value);
@@ -202,7 +196,6 @@ public final class GamePacketBuilder {
*
* @param type The data type.
* @param value The value.
* @throws IllegalStateException If this reader is not in byte access mode.
*/
public void put(DataType type, Number value) {
put(type, DataOrder.BIG, DataTransformation.NONE, value);
@@ -213,7 +206,6 @@ public final class GamePacketBuilder {
* {@code flag} is {@code false}, the value of the bit is {@code 0}.
*
* @param flag The flag.
* @throws IllegalStateException If the builder is not in bit access mode.
*/
public void putBit(boolean flag) {
putBit(flag ? 1 : 0);
@@ -223,7 +215,6 @@ public final class GamePacketBuilder {
* Puts a single bit into the buffer with the value {@code value}.
*
* @param value The value.
* @throws IllegalStateException If the builder is not in bit access mode.
*/
public void putBit(int value) {
putBits(1, value);
@@ -234,7 +225,6 @@ public final class GamePacketBuilder {
*
* @param numBits The number of bits to put into the buffer.
* @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.
*/
public void putBits(int numBits, int value) {
@@ -276,7 +266,6 @@ public final class GamePacketBuilder {
* Puts the specified byte array into the buffer.
*
* @param bytes The byte array.
* @throws IllegalStateException If the builder is not in bit access mode.
*/
public void putBytes(byte[] bytes) {
buffer.writeBytes(bytes);
@@ -286,7 +275,6 @@ public final class GamePacketBuilder {
* Puts the bytes from the specified buffer into this packet's buffer.
*
* @param buffer The source {@link ChannelBuffer}.
* @throws IllegalStateException If the builder is not in byte access mode.
*/
public void putBytes(ChannelBuffer buffer) {
byte[] bytes = new byte[buffer.readableBytes()];
@@ -304,7 +292,6 @@ public final class GamePacketBuilder {
*
* @param transformation The transformation.
* @param bytes The byte array.
* @throws IllegalStateException If the builder is not in byte access mode.
*/
public void putBytes(DataTransformation transformation, byte[] bytes) {
if (transformation == DataTransformation.NONE) {
@@ -320,7 +307,6 @@ public final class GamePacketBuilder {
* Puts the specified byte array into the buffer in reverse.
*
* @param bytes The byte array.
* @throws IllegalStateException If the builder is not in byte access mode.
*/
public void putBytesReverse(byte[] bytes) {
checkByteAccess();
@@ -333,7 +319,6 @@ public final class GamePacketBuilder {
* Puts the bytes from the specified buffer into this packet's buffer, in reverse.
*
* @param buffer The source {@link ChannelBuffer}.
* @throws IllegalStateException If the builder is not in byte access mode.
*/
public void putBytesReverse(ChannelBuffer buffer) {
byte[] bytes = new byte[buffer.readableBytes()];
@@ -351,7 +336,6 @@ public final class GamePacketBuilder {
*
* @param transformation The transformation.
* @param bytes The byte array.
* @throws IllegalStateException If the builder is not in byte access mode.
*/
public void putBytesReverse(DataTransformation transformation, byte[] bytes) {
if (transformation == DataTransformation.NONE) {
@@ -367,6 +351,7 @@ public final class GamePacketBuilder {
* Puts a raw builder. Both builders (this and parameter) must be in byte access mode.
*
* @param builder The builder.
* @throws IllegalArgumentException If the builder is not raw.
*/
public void putRawBuilder(GamePacketBuilder builder) {
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.
*
* @param builder The builder.
* @throws IllegalArgumentException If the builder is not raw.
*/
public void putRawBuilderReverse(GamePacketBuilder builder) {
checkByteAccess();
@@ -461,4 +447,4 @@ public final class GamePacketBuilder {
return new GamePacket(opcode, type, buffer);
}
}
}
@@ -1,5 +1,7 @@
package org.apollo.net.codec.game;
import java.io.IOException;
import net.burtleburtle.bob.rand.IsaacRandom;
import org.apollo.net.meta.PacketMetaData;
@@ -57,7 +59,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, GameDecoderState state)
throws Exception {
throws IOException {
switch (state) {
case GAME_OPCODE:
return decodeOpcode(ctx, channel, buffer);
@@ -66,7 +68,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
case GAME_PAYLOAD:
return decodePayload(ctx, channel, buffer);
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}.
* @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()) {
length = buffer.readUnsignedByte();
if (length == 0) {
@@ -98,16 +100,16 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @param channel The channel.
* @param buffer The buffer.
* @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()) {
int encryptedOpcode = buffer.readUnsignedByte();
opcode = encryptedOpcode - random.nextInt() & 0xFF;
PacketMetaData metaData = release.getIncomingPacketMetaData(opcode);
if (metaData == null) {
throw new Exception("Illegal opcode: " + opcode);
throw new IOException("Illegal opcode: " + opcode);
}
type = metaData.getType();
@@ -124,7 +126,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
setState(GameDecoderState.GAME_LENGTH);
break;
default:
throw new Exception("Illegal packet type: " + type);
throw new IOException("Illegal packet type: " + type);
}
}
return null;
@@ -139,7 +141,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @return The frame, or {@code null}.
* @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) {
ChannelBuffer payload = buffer.readBytes(length);
setState(GameDecoderState.GAME_OPCODE);
@@ -158,11 +160,10 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @return The frame, or {@code null}.
* @throws Exception If an error occurs.
*/
private Object decodeZeroLengthPacket(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer)
throws Exception {
private Object decodeZeroLengthPacket(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
ChannelBuffer payload = ChannelBuffers.buffer(0);
setState(GameDecoderState.GAME_OPCODE);
return new GamePacket(opcode, type, payload);
}
}
}
@@ -26,7 +26,7 @@ public final class HandshakeDecoder extends FrameDecoder {
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
if (buffer.readable()) {
int id = buffer.readUnsignedByte();
@@ -43,7 +43,7 @@ public final class HandshakeDecoder extends FrameDecoder {
channel.write(buf); // TODO should it be here?
break;
default:
throw new Exception("Invalid service id");
throw new IllegalArgumentException("Invalid service id");
}
ctx.getPipeline().remove(this);
@@ -52,10 +52,8 @@ public final class HandshakeDecoder extends FrameDecoder {
if (buffer.readable()) {
return new Object[] { message, buffer.readBytes(buffer.readableBytes()) };
} else {
return message;
}
return message;
}
return null;
}
@@ -12,17 +12,16 @@ import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;
public final class JagGrabRequestDecoder extends OneToOneDecoder {
@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) {
String str = (String) msg;
if (str.startsWith("JAGGRAB /")) {
String filePath = str.substring(8).trim();
return new JagGrabRequest(filePath);
} else {
throw new Exception("corrupted request line");
}
throw new IllegalArgumentException("corrupted request line");
}
return msg;
}
}
}
@@ -12,7 +12,7 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
public final class JagGrabResponseEncoder extends OneToOneEncoder {
@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) {
JagGrabResponse resp = (JagGrabResponse) msg;
return resp.getFileData();
@@ -20,4 +20,4 @@ public final class JagGrabResponseEncoder extends OneToOneEncoder {
return msg;
}
}
}
@@ -1,5 +1,6 @@
package org.apollo.net.codec.login;
import java.io.IOException;
import java.math.BigInteger;
import java.security.SecureRandom;
@@ -66,7 +67,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
case LOGIN_PAYLOAD:
return decodePayload(ctx, channel, buffer);
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}.
* @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()) {
usernameHash = buffer.readUnsignedByte();
serverSeed = random.nextLong();
@@ -102,14 +103,14 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
* @param channel The channel.
* @param buffer The buffer.
* @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) {
int loginType = buffer.readUnsignedByte();
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;
@@ -7,14 +7,14 @@ import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
/**
* A class which encodes login response messsages.
* A class which encodes login response messages.
*
* @author Graham
*/
public final class LoginEncoder extends OneToOneEncoder {
@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)) {
return message;
}
@@ -31,4 +31,4 @@ public final class LoginEncoder extends OneToOneEncoder {
return buffer;
}
}
}
@@ -15,7 +15,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder;
public final class UpdateDecoder extends FrameDecoder {
@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) {
int type = buf.readUnsignedByte() + 1;
int file = buf.readUnsignedShort();
@@ -29,4 +29,4 @@ public final class UpdateDecoder extends FrameDecoder {
return null;
}
}
}
@@ -15,7 +15,7 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
public final class UpdateEncoder extends OneToOneEncoder {
@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) {
OnDemandResponse resp = (OnDemandResponse) msg;
@@ -36,4 +36,4 @@ public final class UpdateEncoder extends OneToOneEncoder {
return msg;
}
}
}
+2 -2
View File
@@ -16,7 +16,7 @@ public final class PacketMetaData {
*/
public static PacketMetaData createFixed(int length) {
if (length < 0) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("packet length cannot be less than 0");
}
return new PacketMetaData(PacketType.FIXED, length);
}
@@ -69,7 +69,7 @@ public final class PacketMetaData {
*/
public int getLength() {
if (type != PacketType.FIXED) {
throw new IllegalStateException();
throw new IllegalStateException("can only get the length of a fixed length packet");
}
return length;
}
@@ -17,14 +17,14 @@ public final class PacketMetaDataGroup {
*/
public static PacketMetaDataGroup createFromArray(int[] lengthArray) {
if (lengthArray.length != 256) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("length array must be 256");
}
PacketMetaDataGroup grp = new PacketMetaDataGroup();
for (int i = 0; i < lengthArray.length; i++) {
int length = lengthArray[i];
PacketMetaData metaData = null;
if (length < -3) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("no packet length can have a value less than -3");
} else if (length == -2) {
metaData = PacketMetaData.createVariableShort();
} else if (length == -1) {
@@ -54,13 +54,13 @@ public final class PacketMetaDataGroup {
*
* @param opcode The opcode of the packet.
* @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) {
if (opcode < 0 || opcode >= packets.length) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("opcode is out of bounds");
}
return packets[opcode];
}
}
}
+1 -1
View File
@@ -27,4 +27,4 @@ public enum PacketType {
*/
VARIABLE_SHORT;
}
}
+2 -2
View File
@@ -53,7 +53,7 @@ public abstract class Release {
*/
public final EventDecoder<?> getEventDecoder(int opcode) {
if (opcode < 0 || opcode >= decoders.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("opcode is out of bounds");
}
return decoders[opcode];
}
@@ -106,7 +106,7 @@ public abstract class Release {
*/
public final <E extends Event> void register(int opcode, EventDecoder<E> decoder) {
if (opcode < 0 || opcode >= decoders.length) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException("opcode is out of bounds");
}
decoders[opcode] = decoder;
}
@@ -16,8 +16,22 @@ public class MouseClickEventDecoder extends EventDecoder<MouseClickEvent> {
@Override
public MouseClickEvent decode(GamePacket packet) {
GamePacketReader reader = new GamePacketReader(packet);
reader.getUnsigned(DataType.INT);
return new MouseClickEvent();
int read;
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
public GamePacket encode(RegionChangeEvent event) {
System.out.println("Sending region change event.");
GamePacketBuilder builder = new GamePacketBuilder(73);
builder.put(DataType.SHORT, DataTransformation.ADD, event.getPosition().getCentralSectorX());
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.SwitchTabInterfaceEvent;
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.UpdateSlottedItemsEvent;
import org.apollo.net.meta.PacketMetaDataGroup;
@@ -117,6 +118,7 @@ public final class Release317 extends Release {
SpamPacketEventDecoder spamEventDecoder = new SpamPacketEventDecoder();
register(77, spamEventDecoder);
register(78, spamEventDecoder);
register(165, spamEventDecoder);
register(189, spamEventDecoder);
register(226, spamEventDecoder);
@@ -151,6 +153,7 @@ public final class Release317 extends Release {
register(DisplayTabInterfaceEvent.class, new DisplayTabInterfaceEventEncoder());
register(SetTileItemEvent.class, new SetTileItemEventEncoder());
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
public MouseClickEvent decode(GamePacket packet) {
GamePacketReader reader = new GamePacketReader(packet);
reader.getUnsigned(DataType.INT);
return new MouseClickEvent();
int read;
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);
Position base = event.getBase(), pos = event.getPosition();
int x = pos.getLocalX(base);
builder.put(DataType.BYTE, DataTransformation.NEGATE, x);
int y = pos.getLocalY(base);
builder.put(DataType.BYTE, DataTransformation.ADD, y);
builder.put(DataType.BYTE, DataTransformation.NEGATE, pos.getLocalX(base));
builder.put(DataType.BYTE, DataTransformation.ADD, pos.getLocalY(base));
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.SwitchTabInterfaceEvent;
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.UpdateSlottedItemsEvent;
import org.apollo.net.meta.PacketMetaDataGroup;
@@ -149,6 +150,7 @@ public final class Release377 extends Release {
register(DisplayTabInterfaceEvent.class, new DisplayTabInterfaceEventEncoder());
register(SetTileItemEvent.class, new SetTileItemEventEncoder());
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
public void destroy() throws Exception {
public void destroy() {
context.getService(GameService.class).unregisterPlayer(player);
}
@@ -122,7 +122,7 @@ public final class GameSession extends Session {
}
@Override
public void messageReceived(Object message) throws Exception {
public void messageReceived(Object message) {
Event event = (Event) message;
if (eventQueue.size() >= GameConstants.EVENTS_PER_PULSE) {
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
public void messageReceived(Object message) throws Exception {
public void messageReceived(Object message) {
if (message.getClass() == LoginRequest.class) {
handleLoginRequest((LoginRequest) message);
}
}
}
}
+3 -5
View File
@@ -26,10 +26,8 @@ public abstract class Session {
/**
* Destroys this session.
*
* @throws Exception If an error occurs.
*/
public abstract void destroy() throws Exception;
public abstract void destroy();
/**
* Gets the channel.
@@ -46,6 +44,6 @@ public abstract class Session {
* @param message The message.
* @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
public void destroy() throws Exception {
public void destroy() {
// TODO implement
}
@Override
public void messageReceived(Object message) throws Exception {
public void messageReceived(Object message) {
UpdateDispatcher dispatcher = context.getService(UpdateService.class).getDispatcher();
if (message instanceof OnDemandRequest) {
dispatcher.dispatch(getChannel(), (OnDemandRequest) message);
@@ -46,8 +46,8 @@ public final class UpdateSession extends Session {
} else if (message instanceof HttpRequest) {
dispatcher.dispatch(getChannel(), (HttpRequest) message);
} 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) {
throw new NoSuchElementException();
throw new NoSuchElementException("character does not exist");
}
previousIndex = index;
index++;
@@ -64,7 +64,7 @@ public final class CharacterRepository<T extends Character> implements Iterable<
@Override
public void remove() {
if (previousIndex == -1) {
throw new IllegalStateException();
throw new IllegalStateException("cannot remove as the repository is empty");
}
CharacterRepository.this.remove((T) characters[previousIndex]);
previousIndex = -1;
@@ -167,9 +167,8 @@ public final class CharacterRepository<T extends Character> implements Iterable<
character.setIndex(-1);
size--;
return true;
} else {
return false;
}
return false;
}
/**
@@ -181,4 +180,4 @@ public final class CharacterRepository<T extends Character> implements Iterable<
return size;
}
}
}
+2 -2
View File
@@ -33,7 +33,7 @@ public final class EnumerationUtil {
@Override
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 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.
* @throws Exception If an error occurs during decoding.
*/
protected abstract Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state)
throws Exception;
@Override
protected final Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer)
throws Exception {
protected final Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
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 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.
* @throws Exception If an error occurs during decoding.
*/
protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state)
throws Exception {
protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state) {
return null;
}
@@ -107,4 +103,4 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecod
this.state = state;
}
}
}
@@ -24,4 +24,4 @@ public interface PluginEnvironment {
*/
public void setContext(PluginContext context);
}
}
@@ -53,4 +53,4 @@ public final class RubyPluginEnvironment implements PluginEnvironment {
container.put("$ctx", context);
}
}
}