Update to netty 4.

This commit is contained in:
Major-
2014-01-26 21:02:18 +00:00
parent 4b346f4e24
commit 15141fd875
93 changed files with 793 additions and 1106 deletions
+4 -3
View File
@@ -16,13 +16,14 @@ require 'java'
java_import 'org.apollo.game.event.handler.EventHandler' java_import 'org.apollo.game.event.handler.EventHandler'
java_import 'org.apollo.game.command.CommandListener' java_import 'org.apollo.game.command.CommandListener'
java_import 'org.apollo.game.model.Player' java_import 'org.apollo.game.model.Player'
java_import 'org.apollo.game.model.settings.PrivilegeLevel'
java_import 'org.apollo.game.model.World' java_import 'org.apollo.game.model.World'
java_import 'org.apollo.game.scheduling.ScheduledTask' java_import 'org.apollo.game.scheduling.ScheduledTask'
# Alias the privilege levels. # Alias the privilege levels.
RIGHTS_ADMIN = Player::PrivilegeLevel::ADMINISTRATOR RIGHTS_ADMIN = PrivilegeLevel::ADMINISTRATOR
RIGHTS_MOD = Player::PrivilegeLevel::MODERATOR RIGHTS_MOD = PrivilegeLevel::MODERATOR
RIGHTS_STANDARD = Player::PrivilegeLevel::STANDARD RIGHTS_STANDARD = PrivilegeLevel::STANDARD
# Extends the (Ruby) String class with a method to convert a lower case, # Extends the (Ruby) String class with a method to convert a lower case,
# underscore delimited string to camel-case. # underscore delimited string to camel-case.
+4 -1
View File
@@ -1,5 +1,8 @@
require 'java' require 'java'
java_import 'org.apollo.game.model.Player' java_import 'org.apollo.game.model.Player'
java_import 'org.apollo.game.model.def.ItemDefinition'
java_import 'org.apollo.game.model.def.NpcDefinition'
java_import 'org.apollo.game.model.def.ObjectDefinition'
on :command, :lookup, RIGHTS_ADMIN do |player, command| on :command, :lookup, RIGHTS_ADMIN do |player, command|
args = command.arguments.to_a args = command.arguments.to_a
@@ -37,6 +40,6 @@ on :command, :iteminfo, RIGHTS_ADMIN do |player, command|
definition = ItemDefinition.lookup(id) definition = ItemDefinition.lookup(id)
members = definition.is_members_only ? "members" : "not members" members = definition.is_members_only ? "members" : "not members"
player.send_message("Item #{id} is called #{definition.name}, is #{members} only, and a has a team of #{definition.team}.") player.send_message("Item #{id} is called #{definition.name}, is #{members} only, and has a team of #{definition.team}.")
player.send_message("Its description is \"#{definition.description}\".") player.send_message("Its description is \"#{definition.description}\".")
end end
+25
View File
@@ -0,0 +1,25 @@
require 'java'
java_import 'org.apollo.game.model.Npc'
java_import 'org.apollo.game.model.World'
java_import 'org.apollo.game.model.Position'
def register(npc)
raise "Npc cannot be nil" if npc == nil
World.world.register(npc)
end
### Lumbridge spawns:
# Generic:
register Npc.new(4, Position.new(3232, 3207)) # woman, southernmost house
register Npc.new(1, Position.new(3231, 3237)) # man, house by willow tree
register Npc.new(2, Position.new(3224, 3240)) # man, house by willow tree
register Npc.new(5, Position.new(3229, 3239)) # woman, house by willow tree
# Other:
register Npc.new(0, Position.new(3221, 3221)) # hans
register Npc.new(456, Position.new(3243, 3210)) # father aereck
register Npc.new(519, Position.new(3231, 3203)) # bob from bob's axes
register Npc.new(520, Position.new(3212, 3247)) # shopkeeper
register Npc.new(521, Position.new(3211, 3245)) # shop assistant
register Npc.new(2244, Position.new(3232, 3229)) # lumbridge guide
+1
View File
@@ -1,4 +1,5 @@
require 'java' require 'java'
java_import 'org.apollo.game.model.Animation' java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic' java_import 'org.apollo.game.model.Graphic'
+1
View File
@@ -1,4 +1,5 @@
require 'java' require 'java'
java_import 'org.apollo.game.model.Animation' java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic' java_import 'org.apollo.game.model.Graphic'
java_import 'org.apollo.game.model.Item' java_import 'org.apollo.game.model.Item'
+1
View File
@@ -1,4 +1,5 @@
require 'java' require 'java'
java_import 'org.apollo.game.model.EquipmentConstants' java_import 'org.apollo.game.model.EquipmentConstants'
AIR_ELEMENTS = {} AIR_ELEMENTS = {}
+1
View File
@@ -1,4 +1,5 @@
require 'java' require 'java'
java_import 'org.apollo.game.model.Animation' java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic' java_import 'org.apollo.game.model.Graphic'
java_import 'org.apollo.game.model.Item' java_import 'org.apollo.game.model.Item'
+1
View File
@@ -1,4 +1,5 @@
require 'java' require 'java'
java_import 'org.apollo.game.action.Action' java_import 'org.apollo.game.action.Action'
java_import 'org.apollo.game.event.impl.DisplayTabInterfaceEvent' java_import 'org.apollo.game.event.impl.DisplayTabInterfaceEvent'
java_import 'org.apollo.game.model.EquipmentConstants' java_import 'org.apollo.game.model.EquipmentConstants'
+1
View File
@@ -1,4 +1,5 @@
require 'java' require 'java'
java_import 'org.apollo.game.action.DistancedAction' java_import 'org.apollo.game.action.DistancedAction'
java_import 'org.apollo.game.model.EquipmentConstants' java_import 'org.apollo.game.model.EquipmentConstants'
java_import 'org.apollo.game.model.def.ItemDefinition' java_import 'org.apollo.game.model.def.ItemDefinition'
+1
View File
@@ -1,4 +1,5 @@
require 'java' require 'java'
java_import 'org.apollo.game.model.Animation' java_import 'org.apollo.game.model.Animation'
PICKAXES = {} PICKAXES = {}
+29 -36
View File
@@ -1,30 +1,29 @@
package org.apollo; package org.apollo;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import java.io.File; import java.io.File;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.apollo.fs.IndexedFileSystem; import org.apollo.fs.IndexedFileSystem;
import org.apollo.game.model.World; import org.apollo.game.model.World;
import org.apollo.net.ApolloHandler; import org.apollo.net.ApolloHandler;
import org.apollo.net.HttpPipelineFactory; import org.apollo.net.HttpChannelInitializer;
import org.apollo.net.JagGrabPipelineFactory; import org.apollo.net.JagGrabChannelInitializer;
import org.apollo.net.NetworkConstants; import org.apollo.net.NetworkConstants;
import org.apollo.net.ServicePipelineFactory; import org.apollo.net.ServiceChannelInitializer;
import org.apollo.net.release.Release; import org.apollo.net.release.Release;
import org.apollo.net.release.r317.Release317; import org.apollo.net.release.r317.Release317;
import org.apollo.util.plugin.PluginContext; import org.apollo.util.plugin.PluginContext;
import org.apollo.util.plugin.PluginManager; import org.apollo.util.plugin.PluginManager;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timer;
/** /**
* The core class of the Apollo server. * The core class of the Apollo server.
@@ -74,27 +73,21 @@ public final class Server {
*/ */
private final ServerBootstrap jagGrabBootstrap = new ServerBootstrap(); private final ServerBootstrap jagGrabBootstrap = new ServerBootstrap();
/**
* The {@link ExecutorService} used for network events. The named thread factory is unused as Netty names threads
* itself.
*/
private final ExecutorService networkExecutor = Executors.newCachedThreadPool();
/** /**
* The {@link ServerBootstrap} for the service listener. * The {@link ServerBootstrap} for the service listener.
*/ */
private final ServerBootstrap serviceBootstrap = new ServerBootstrap(); private final ServerBootstrap serviceBootstrap = new ServerBootstrap();
/**
* The event loop group.
*/
private final EventLoopGroup loopGroup = new NioEventLoopGroup();
/** /**
* The service manager. * The service manager.
*/ */
private final ServiceManager serviceManager; private final ServiceManager serviceManager;
/**
* The timer used for idle checking.
*/
private final Timer timer = new HashedWheelTimer();
/** /**
* Creates the Apollo server. * Creates the Apollo server.
* *
@@ -145,22 +138,24 @@ public final class Server {
logger.info("Initialized release #" + release.getReleaseNumber() + "."); logger.info("Initialized release #" + release.getReleaseNumber() + ".");
ChannelFactory factory = new NioServerSocketChannelFactory(networkExecutor, networkExecutor); serviceBootstrap.group(loopGroup);
serviceBootstrap.setFactory(factory); httpBootstrap.group(loopGroup);
httpBootstrap.setFactory(factory); jagGrabBootstrap.group(loopGroup);
jagGrabBootstrap.setFactory(factory);
context = new ServerContext(release, serviceManager); context = new ServerContext(release, serviceManager);
ApolloHandler handler = new ApolloHandler(context); ApolloHandler handler = new ApolloHandler(context);
ChannelPipelineFactory servicePipelineFactory = new ServicePipelineFactory(handler, timer); ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler);
serviceBootstrap.setPipelineFactory(servicePipelineFactory); serviceBootstrap.channel(NioServerSocketChannel.class);
serviceBootstrap.childHandler(serviceInitializer);
ChannelPipelineFactory httpPipelineFactory = new HttpPipelineFactory(handler, timer); ChannelInitializer<SocketChannel> httpInitializer = new HttpChannelInitializer(handler);
httpBootstrap.setPipelineFactory(httpPipelineFactory); httpBootstrap.channel(NioServerSocketChannel.class);
httpBootstrap.childHandler(httpInitializer);
ChannelPipelineFactory jagGrabPipelineFactory = new JagGrabPipelineFactory(handler, timer); ChannelInitializer<SocketChannel> jagGrabInitializer = new JagGrabChannelInitializer(handler);
jagGrabBootstrap.setPipelineFactory(jagGrabPipelineFactory); jagGrabBootstrap.channel(NioServerSocketChannel.class);
jagGrabBootstrap.childHandler(jagGrabInitializer);
} }
/** /**
@@ -169,14 +164,12 @@ public final class Server {
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
public void start() throws Exception { public void start() throws Exception {
PluginManager mgr = new PluginManager(new PluginContext(context)); PluginManager manager = new PluginManager(new PluginContext(context));
serviceManager.startAll(); serviceManager.startAll();
// TODO move this?
int releaseNo = context.getRelease().getReleaseNumber(); int releaseNo = context.getRelease().getReleaseNumber();
IndexedFileSystem fs = new IndexedFileSystem(new File("data/fs/" + releaseNo), true); IndexedFileSystem fs = new IndexedFileSystem(new File("data/fs/" + releaseNo), true);
World.getWorld().init(releaseNo, fs, mgr); World.getWorld().init(releaseNo, fs, manager);
} }
} }
-16
View File
@@ -1,8 +1,6 @@
package org.apollo; package org.apollo;
import org.apollo.net.release.Release; import org.apollo.net.release.Release;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
/** /**
* A {@link ServerContext} is created along with the {@link Server} object. The primary difference is that a reference * A {@link ServerContext} is created along with the {@link Server} object. The primary difference is that a reference
@@ -15,11 +13,6 @@ import org.jboss.netty.channel.group.DefaultChannelGroup;
*/ */
public final class ServerContext { public final class ServerContext {
/**
* The channel group.
*/
private final ChannelGroup group = new DefaultChannelGroup();
/** /**
* The current release. * The current release.
*/ */
@@ -42,15 +35,6 @@ public final class ServerContext {
this.serviceManager.setContext(this); this.serviceManager.setContext(this);
} }
/**
* Gets the channel group.
*
* @return The channel group.
*/
public ChannelGroup getChannelGroup() {
return group;
}
/** /**
* Gets the current release. * Gets the current release.
* *
+2 -2
View File
@@ -109,8 +109,8 @@ public final class ServiceManager {
* @param ctx The server context. * @param ctx The server context.
*/ */
public void setContext(ServerContext ctx) { public void setContext(ServerContext ctx) {
for (Service s : services.values()) { for (Service service : services.values()) {
s.setContext(ctx); service.setContext(ctx);
} }
} }
-6
View File
@@ -109,13 +109,8 @@ public final class IndexedFileSystem implements Closeable {
} }
} }
// the number of archives
int archives = getFileCount(0); int archives = getFileCount(0);
// the hash
int hash = 1234; int hash = 1234;
// the CRCs
int[] crcs = new int[archives]; int[] crcs = new int[archives];
// calculate the CRCs // calculate the CRCs
@@ -138,7 +133,6 @@ public final class IndexedFileSystem implements Closeable {
buffer.putInt(crc); buffer.putInt(crc);
} }
// place the hash into the buffer
buffer.putInt(hash); buffer.putInt(hash);
buffer.flip(); buffer.flip();
+6
View File
@@ -25,6 +25,7 @@ public final class Archive {
int extractedSize = ByteBufferUtil.readUnsignedTriByte(buffer); int extractedSize = ByteBufferUtil.readUnsignedTriByte(buffer);
int size = ByteBufferUtil.readUnsignedTriByte(buffer); int size = ByteBufferUtil.readUnsignedTriByte(buffer);
boolean extracted = false; boolean extracted = false;
if (size != extractedSize) { if (size != extractedSize) {
byte[] compressed = new byte[size]; byte[] compressed = new byte[size];
byte[] uncompressed = new byte[extractedSize]; byte[] uncompressed = new byte[extractedSize];
@@ -33,15 +34,18 @@ public final class Archive {
buffer = ByteBuffer.wrap(uncompressed); buffer = ByteBuffer.wrap(uncompressed);
extracted = true; extracted = true;
} }
int entries = buffer.getShort() & 0xFFFF; int entries = buffer.getShort() & 0xFFFF;
int[] identifiers = new int[entries]; int[] identifiers = new int[entries];
int[] extractedSizes = new int[entries]; int[] extractedSizes = new int[entries];
int[] sizes = new int[entries]; int[] sizes = new int[entries];
for (int i = 0; i < entries; i++) { for (int i = 0; i < entries; i++) {
identifiers[i] = buffer.getInt(); identifiers[i] = buffer.getInt();
extractedSizes[i] = ByteBufferUtil.readUnsignedTriByte(buffer); extractedSizes[i] = ByteBufferUtil.readUnsignedTriByte(buffer);
sizes[i] = ByteBufferUtil.readUnsignedTriByte(buffer); sizes[i] = ByteBufferUtil.readUnsignedTriByte(buffer);
} }
ArchiveEntry[] entry = new ArchiveEntry[entries]; ArchiveEntry[] entry = new ArchiveEntry[entries];
for (int i = 0; i < entries; i++) { for (int i = 0; i < entries; i++) {
ByteBuffer entryBuffer; ByteBuffer entryBuffer;
@@ -85,9 +89,11 @@ public final class Archive {
public ArchiveEntry getEntry(String name) throws FileNotFoundException { public ArchiveEntry getEntry(String name) throws FileNotFoundException {
int hash = 0; int hash = 0;
name = name.toUpperCase(); name = name.toUpperCase();
for (int i = 0; i < name.length(); i++) { for (int i = 0; i < name.length(); i++) {
hash = hash * 61 + name.charAt(i) - 32; hash = hash * 61 + name.charAt(i) - 32;
} }
for (ArchiveEntry entry : entries) { for (ArchiveEntry entry : entries) {
if (entry.getIdentifier() == hash) { if (entry.getIdentifier() == hash) {
return entry; return entry;
@@ -62,7 +62,7 @@ public abstract class DistancedAction<T extends Mob> extends Action<T> {
} else if (mob.getPosition().getDistance(position) <= distance) { } else if (mob.getPosition().getDistance(position) <= distance) {
reached = true; reached = true;
setDelay(delay); setDelay(delay);
if (immediate) { // TODO: required? if (immediate) {
executeAction(); executeAction();
} }
} }
@@ -1,7 +1,7 @@
package org.apollo.game.command; package org.apollo.game.command;
import org.apollo.game.model.Player; import org.apollo.game.model.Player;
import org.apollo.game.model.Player.PrivilegeLevel; import org.apollo.game.model.settings.PrivilegeLevel;
/** /**
* An interface which should be implemented by classes to listen to {@link Command}s. * An interface which should be implemented by classes to listen to {@link Command}s.
@@ -2,8 +2,8 @@ package org.apollo.game.event.handler.impl;
import org.apollo.game.event.handler.EventHandler; import org.apollo.game.event.handler.EventHandler;
import org.apollo.game.event.handler.EventHandlerContext; import org.apollo.game.event.handler.EventHandlerContext;
import org.apollo.game.event.impl.PlayerDesignEvent;
import org.apollo.game.event.impl.CloseInterfaceEvent; import org.apollo.game.event.impl.CloseInterfaceEvent;
import org.apollo.game.event.impl.PlayerDesignEvent;
import org.apollo.game.model.Player; import org.apollo.game.model.Player;
/** /**
@@ -4,8 +4,8 @@ import org.apollo.game.event.handler.EventHandler;
import org.apollo.game.event.handler.EventHandlerContext; import org.apollo.game.event.handler.EventHandlerContext;
import org.apollo.game.event.impl.PlayerDesignEvent; import org.apollo.game.event.impl.PlayerDesignEvent;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
import org.apollo.game.model.Gender;
import org.apollo.game.model.Player; import org.apollo.game.model.Player;
import org.apollo.game.model.settings.Gender;
/** /**
* A handler which verifies {@link PlayerDesignEvent}s. * A handler which verifies {@link PlayerDesignEvent}s.
@@ -1,7 +1,7 @@
package org.apollo.game.event.impl; package org.apollo.game.event.impl;
import org.apollo.game.event.Event; import org.apollo.game.event.Event;
import org.apollo.game.model.PrivacyState; import org.apollo.game.model.settings.PrivacyState;
/** /**
* An {@link Event} sent by the client or server to update the chat and trade privacy state. * An {@link Event} sent by the client or server to update the chat and trade privacy state.
@@ -1,5 +1,7 @@
package org.apollo.game.model; package org.apollo.game.model;
import org.apollo.game.model.settings.Gender;
/** /**
* Represents the appearance of a player. * Represents the appearance of a player.
* *
+38
View File
@@ -37,4 +37,42 @@ public abstract class Entity {
return position; return position;
} }
/**
* 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, loaded from the game resources.
*/
STATIC_OBJECT;
}
} }
-40
View File
@@ -1,40 +0,0 @@
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, loaded from the cache.
*/
STATIC_OBJECT;
}
+1 -1
View File
@@ -46,7 +46,7 @@ public final class Npc extends Mob {
* @param id The id. * @param id The id.
*/ */
public void transform(int id) { public void transform(int id) {
if (id < 0 || id > NpcDefinition.count()) { if (id < 0 || id >= NpcDefinition.count()) {
throw new IllegalArgumentException("Id to transform to is out of bounds"); throw new IllegalArgumentException("Id to transform to is out of bounds");
} }
definition = NpcDefinition.lookup(id); definition = NpcDefinition.lookup(id);
+45 -81
View File
@@ -20,6 +20,9 @@ import org.apollo.game.model.inv.AppearanceInventoryListener;
import org.apollo.game.model.inv.FullInventoryListener; import org.apollo.game.model.inv.FullInventoryListener;
import org.apollo.game.model.inv.InventoryListener; import org.apollo.game.model.inv.InventoryListener;
import org.apollo.game.model.inv.SynchronizationInventoryListener; import org.apollo.game.model.inv.SynchronizationInventoryListener;
import org.apollo.game.model.settings.PrivacyState;
import org.apollo.game.model.settings.PrivilegeLevel;
import org.apollo.game.model.settings.ScreenBrightness;
import org.apollo.game.model.skill.LevelUpSkillListener; import org.apollo.game.model.skill.LevelUpSkillListener;
import org.apollo.game.model.skill.SkillListener; import org.apollo.game.model.skill.SkillListener;
import org.apollo.game.model.skill.SynchronizationSkillListener; import org.apollo.game.model.skill.SynchronizationSkillListener;
@@ -35,68 +38,6 @@ import org.apollo.util.Point;
*/ */
public final class Player extends Mob { public final class Player extends Mob {
/**
* An enumeration with the different privilege levels a player can have.
*
* @author Graham
*/
public enum PrivilegeLevel {
/**
* An administrator (rights 2) account.
*/
ADMINISTRATOR(2),
/**
* A player moderator (rights 1) account.
*/
MODERATOR(1),
/**
* A standard (rights 0) account.
*/
STANDARD(0);
/**
* Gets the privilege level for the specified numerical level.
*
* @param value The numerical level.
* @return The privilege level.
* @throws IllegalArgumentException If the numerical level is invalid.
*/
public static PrivilegeLevel valueOf(int value) {
PrivilegeLevel[] values = values();
if (value < 0 || value > values.length) {
throw new IndexOutOfBoundsException("Invalid privilege level integer value supplied");
}
return values[value];
}
/**
* The numerical level used in the protocol.
*/
private final int value;
/**
* Creates the privilege level.
*
* @param value The numerical level.
*/
private PrivilegeLevel(int value) {
this.value = value;
}
/**
* Gets the numerical level.
*
* @return The numerical level used in the protocol.
*/
public int toInteger() {
return value;
}
}
/** /**
* The player's appearance. * The player's appearance.
*/ */
@@ -185,13 +126,18 @@ public final class Player extends Mob {
/** /**
* The player's run energy. * The player's run energy.
*/ */
private int runEnergy = 100; private int runEnergy = 0;
/** /**
* A flag indicating if this player is running. * A flag indicating if this player is running.
*/ */
private boolean running = false; private boolean running = false;
/**
* The brightness of this player's screen.
*/
private ScreenBrightness screenBrightness;
/** /**
* The {@link GameSession} currently attached to this {@link Player}. * The {@link GameSession} currently attached to this {@link Player}.
*/ */
@@ -397,6 +343,15 @@ public final class Player extends Mob {
return runEnergy; return runEnergy;
} }
/**
* Gets this player's {@link ScreenBrightness}.
*
* @return The screen brightness.
*/
public ScreenBrightness getScreenBrightness() {
return screenBrightness;
}
/** /**
* Gets the game session. * Gets the game session.
* *
@@ -715,24 +670,6 @@ public final class Player extends Mob {
this.privateChatPrivacy = privateChatPrivacy; this.privateChatPrivacy = privateChatPrivacy;
} }
/**
* Sets the public chat {@link PrivacyState}.
*
* @param publicChatPrivacy The privacy state.
*/
public void setPublicChatPrivacy(PrivacyState publicChatPrivacy) {
this.publicChatPrivacy = publicChatPrivacy;
}
/**
* Sets the trade chat {@link PrivacyState}.
*
* @param tradeChatPrivacy The privacy state.
*/
public void setTradeChatPrivacy(PrivacyState tradeChatPrivacy) {
this.tradeChatPrivacy = tradeChatPrivacy;
}
/** /**
* Sets the privilege level. * Sets the privilege level.
* *
@@ -742,6 +679,15 @@ public final class Player extends Mob {
this.privilegeLevel = privilegeLevel; this.privilegeLevel = privilegeLevel;
} }
/**
* Sets the public chat {@link PrivacyState}.
*
* @param publicChatPrivacy The privacy state.
*/
public void setPublicChatPrivacy(PrivacyState publicChatPrivacy) {
this.publicChatPrivacy = publicChatPrivacy;
}
/** /**
* Sets the region changed flag. * Sets the region changed flag.
* *
@@ -761,6 +707,15 @@ public final class Player extends Mob {
send(new UpdateRunEnergyEvent(runEnergy)); send(new UpdateRunEnergyEvent(runEnergy));
} }
/**
* Sets the {@link ScreenBrightness} of this player.
*
* @param brightness The screen brightness.
*/
public void setScreenBrightness(ScreenBrightness brightness) {
this.screenBrightness = brightness;
}
/** /**
* Sets the player's {@link GameSession}. * Sets the player's {@link GameSession}.
* *
@@ -775,6 +730,15 @@ public final class Player extends Mob {
getBlockSet().add(SynchronizationBlock.createAppearanceBlock(this)); getBlockSet().add(SynchronizationBlock.createAppearanceBlock(this));
} }
/**
* Sets the trade chat {@link PrivacyState}.
*
* @param tradeChatPrivacy The privacy state.
*/
public void setTradeChatPrivacy(PrivacyState tradeChatPrivacy) {
this.tradeChatPrivacy = tradeChatPrivacy;
}
/** /**
* Sets whether the player is withdrawing notes from the bank. * Sets whether the player is withdrawing notes from the bank.
* *
@@ -1,7 +1,6 @@
package org.apollo.game.model.obj; package org.apollo.game.model.obj;
import org.apollo.game.model.Entity; 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;
@@ -1,7 +1,6 @@
package org.apollo.game.model.obj; package org.apollo.game.model.obj;
import org.apollo.game.model.Entity; 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;
+2 -2
View File
@@ -47,8 +47,8 @@ public final class Sector {
} }
/** /**
* Adds a {@link Entity} from to sector. Note that this does not spawn the entity, or do any other action * Adds a {@link Entity} from to sector. Note that this does not spawn the entity, or do any other action other than
* other than register it to this sector. * register it to this sector.
* *
* @param entity The entity. * @param entity The entity.
* @return {@code true} if the entity was added, otherwise {@code false}. * @return {@code true} if the entity was added, otherwise {@code false}.
@@ -43,10 +43,7 @@ public final class SectorCoordinates {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) { if (obj == null || getClass() != obj.getClass()) {
return false;
}
if (getClass() != obj.getClass()) {
return false; return false;
} }
final SectorCoordinates other = (SectorCoordinates) obj; final SectorCoordinates other = (SectorCoordinates) obj;
@@ -1,4 +1,4 @@
package org.apollo.game.model; package org.apollo.game.model.settings;
/** /**
* An enumeration containing the two genders (male and female). * An enumeration containing the two genders (male and female).
@@ -1,4 +1,4 @@
package org.apollo.game.model; package org.apollo.game.model.settings;
/** /**
* An enumeration representing the different privacy states for public, private and trade chat. * An enumeration representing the different privacy states for public, private and trade chat.
@@ -8,9 +8,9 @@ package org.apollo.game.model;
public enum PrivacyState { public enum PrivacyState {
/** /**
* Represents the 'friends' state, when only messages from friends and moderators are displayed. * Represents the 'on' state, when all messages are displayed.
*/ */
FRIENDS(2), ON(0),
/** /**
* Represents the 'hidden' state, when all public chat text is displayed over the heads of players, but not in the * Represents the 'hidden' state, when all public chat text is displayed over the heads of players, but not in the
@@ -19,14 +19,14 @@ public enum PrivacyState {
HIDE(1), HIDE(1),
/** /**
* Represents the 'off' state, when only messages from moderators are displayed. * Represents the 'friends' state, when only messages from friends and moderators are displayed.
*/ */
OFF(3), FRIENDS(2),
/** /**
* Represents the 'on' state, when all messages are displayed. * Represents the 'off' state, when only messages from moderators are displayed.
*/ */
ON(0); OFF(3);
/** /**
* Gets the privacy state for the specified numerical value. * Gets the privacy state for the specified numerical value.
@@ -0,0 +1,63 @@
package org.apollo.game.model.settings;
/**
* An enumeration with the different privilege levels a player can have.
*
* @author Graham
*/
public enum PrivilegeLevel {
/**
* An administrator (rights 2) account.
*/
ADMINISTRATOR(2),
/**
* A player moderator (rights 1) account.
*/
MODERATOR(1),
/**
* A standard (rights 0) account.
*/
STANDARD(0);
/**
* Gets the privilege level for the specified numerical level.
*
* @param value The numerical level.
* @return The privilege level.
* @throws IllegalArgumentException If the numerical level is invalid.
*/
public static PrivilegeLevel valueOf(int value) {
PrivilegeLevel[] values = values();
if (value < 0 || value >= values.length) {
throw new IndexOutOfBoundsException("Invalid privilege level integer value supplied");
}
return values[value];
}
/**
* The numerical level used in the protocol.
*/
private final int value;
/**
* Creates the privilege level.
*
* @param value The numerical level.
*/
private PrivilegeLevel(int value) {
this.value = value;
}
/**
* Gets the numerical level.
*
* @return The numerical level used in the protocol.
*/
public int toInteger() {
return value;
}
}
@@ -0,0 +1,68 @@
package org.apollo.game.model.settings;
/**
* An enumeration representing
*
* @author Major
*/
public enum ScreenBrightness {
/**
* Represents the 'dark' screen brightness.
*/
DARK(0),
/**
* Represents the 'normal' screen brightness.
*/
NORMAL(1),
/**
* Represents the 'bright' screen brightness.
*/
BRIGHT(2),
/**
* Represents the 'very bright' screen brightness.
*/
VERY_BRIGHT(3);
/**
* Gets the screen brightness for the specified numerical value.
*
* @param value The numerical value.
* @return The screen brightness.
* @throws IllegalArgumentException If the numerical value is invalid.
*/
public static ScreenBrightness valueOf(int value) {
ScreenBrightness[] values = values();
if (value < 0 || value >= values.length) {
throw new IllegalArgumentException("Invalid screen brightness integer value specified");
}
return values[value];
}
/**
* The numerical value of this brightness.
*/
private final int value;
/**
* Creates the screen brightness.
*
* @param value The numerical value.
*/
private ScreenBrightness(int value) {
this.value = value;
}
/**
* Converts this screen brightness to an integer.
*
* @return The numerical value.
*/
public int toInteger() {
return value;
}
}
@@ -0,0 +1,4 @@
/**
* Contains player setting or customisation-related classes.
*/
package org.apollo.game.model.settings;
@@ -1,7 +1,7 @@
package org.apollo.game.sync.block; package org.apollo.game.sync.block;
import org.apollo.game.event.impl.ChatEvent; import org.apollo.game.event.impl.ChatEvent;
import org.apollo.game.model.Player.PrivilegeLevel; import org.apollo.game.model.settings.PrivilegeLevel;
/** /**
* The chat {@link SynchronizationBlock}. * The chat {@link SynchronizationBlock}.
+1 -1
View File
@@ -14,7 +14,7 @@ import org.xml.sax.SAXException;
* *
* @author Major * @author Major
*/ */
public class RsaKeyParser { public final class RsaKeyParser {
/** /**
* The source {@link InputStream}. * The source {@link InputStream}.
@@ -6,15 +6,16 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
import org.apollo.game.model.Gender;
import org.apollo.game.model.Inventory; import org.apollo.game.model.Inventory;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.Player; import org.apollo.game.model.Player;
import org.apollo.game.model.Player.PrivilegeLevel;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.PrivacyState;
import org.apollo.game.model.Skill; import org.apollo.game.model.Skill;
import org.apollo.game.model.SkillSet; import org.apollo.game.model.SkillSet;
import org.apollo.game.model.settings.Gender;
import org.apollo.game.model.settings.PrivacyState;
import org.apollo.game.model.settings.PrivilegeLevel;
import org.apollo.game.model.settings.ScreenBrightness;
import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoader;
import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.io.player.PlayerLoaderResponse;
import org.apollo.net.codec.login.LoginConstants; import org.apollo.net.codec.login.LoginConstants;
@@ -35,14 +36,12 @@ public final class BinaryPlayerLoader implements PlayerLoader {
@Override @Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws IOException { public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws IOException {
File f = BinaryPlayerUtil.getFile(credentials.getUsername()); File file = BinaryPlayerUtil.getFile(credentials.getUsername());
if (!f.exists()) { if (!file.exists()) {
return new PlayerLoaderResponse(LoginConstants.STATUS_OK, new Player(credentials, SPAWN_POSITION)); return new PlayerLoaderResponse(LoginConstants.STATUS_OK, new Player(credentials, SPAWN_POSITION));
} }
DataInputStream in = new DataInputStream(new FileInputStream(f)); try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
try {
// read credentials and 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);
@@ -58,6 +57,8 @@ public final class BinaryPlayerLoader implements PlayerLoader {
PrivacyState privacyPublicChat = PrivacyState.valueOf(in.readByte()); PrivacyState privacyPublicChat = PrivacyState.valueOf(in.readByte());
PrivacyState privacyPrivateChat = PrivacyState.valueOf(in.readByte()); PrivacyState privacyPrivateChat = PrivacyState.valueOf(in.readByte());
PrivacyState privacyTradeCompete = PrivacyState.valueOf(in.readByte()); PrivacyState privacyTradeCompete = PrivacyState.valueOf(in.readByte());
int runEnergy = in.readByte();
ScreenBrightness brightness = ScreenBrightness.valueOf(in.readByte());
// read position // read position
int x = in.readUnsignedShort(); int x = in.readUnsignedShort();
@@ -84,6 +85,9 @@ public final class BinaryPlayerLoader implements PlayerLoader {
player.setPublicChatPrivacy(privacyPublicChat); player.setPublicChatPrivacy(privacyPublicChat);
player.setPrivateChatPrivacy(privacyPrivateChat); player.setPrivateChatPrivacy(privacyPrivateChat);
player.setTradeChatPrivacy(privacyTradeCompete); player.setTradeChatPrivacy(privacyTradeCompete);
player.setRunEnergy(runEnergy);
player.setScreenBrightness(brightness);
player.setDesigned(designed); player.setDesigned(designed);
player.setAppearance(new Appearance(gender, style, colors)); player.setAppearance(new Appearance(gender, style, colors));
@@ -108,8 +112,6 @@ public final class BinaryPlayerLoader implements PlayerLoader {
} }
return new PlayerLoaderResponse(LoginConstants.STATUS_OK, player); return new PlayerLoaderResponse(LoginConstants.STATUS_OK, player);
} finally {
in.close();
} }
} }
@@ -24,9 +24,9 @@ public final class BinaryPlayerSaver implements PlayerSaver {
@Override @Override
public void savePlayer(Player player) throws IOException { public void savePlayer(Player player) throws IOException {
File f = BinaryPlayerUtil.getFile(player.getName()); File file = BinaryPlayerUtil.getFile(player.getName());
DataOutputStream out = new DataOutputStream(new FileOutputStream(f));
try { try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
// write credentials and privileges // write credentials and privileges
StreamUtil.writeString(out, player.getName()); StreamUtil.writeString(out, player.getName());
StreamUtil.writeString(out, player.getCredentials().getPassword()); StreamUtil.writeString(out, player.getCredentials().getPassword());
@@ -37,6 +37,8 @@ public final class BinaryPlayerSaver implements PlayerSaver {
out.writeByte(player.getPublicChatPrivacy().toInteger()); out.writeByte(player.getPublicChatPrivacy().toInteger());
out.writeByte(player.getPrivateChatPrivacy().toInteger()); out.writeByte(player.getPrivateChatPrivacy().toInteger());
out.writeByte(player.getTradeChatPrivacy().toInteger()); out.writeByte(player.getTradeChatPrivacy().toInteger());
out.writeByte(player.getRunEnergy());
out.writeByte(player.getScreenBrightness().toInteger());
// write position // write position
Position position = player.getPosition(); Position position = player.getPosition();
@@ -66,13 +68,11 @@ public final class BinaryPlayerSaver implements PlayerSaver {
// write skills // write skills
SkillSet skills = player.getSkillSet(); SkillSet skills = player.getSkillSet();
out.writeByte(skills.size()); out.writeByte(skills.size());
for (int i = 0; i < skills.size(); i++) { for (int id = 0; id < skills.size(); id++) {
Skill skill = skills.getSkill(i); Skill skill = skills.getSkill(id);
out.writeByte(skill.getCurrentLevel()); out.writeByte(skill.getCurrentLevel());
out.writeDouble(skill.getExperience()); out.writeDouble(skill.getExperience());
} }
} finally {
out.close();
} }
} }
@@ -1,8 +1,8 @@
package org.apollo.io.player.impl; package org.apollo.io.player.impl;
import org.apollo.game.model.Player; import org.apollo.game.model.Player;
import org.apollo.game.model.Player.PrivilegeLevel;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.settings.PrivilegeLevel;
import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoader;
import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.io.player.PlayerLoaderResponse;
import org.apollo.net.codec.login.LoginConstants; import org.apollo.net.codec.login.LoginConstants;
+23 -41
View File
@@ -1,5 +1,11 @@
package org.apollo.net; package org.apollo.net;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpRequest;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -10,22 +16,14 @@ import org.apollo.net.codec.jaggrab.JagGrabRequest;
import org.apollo.net.session.LoginSession; import org.apollo.net.session.LoginSession;
import org.apollo.net.session.Session; import org.apollo.net.session.Session;
import org.apollo.net.session.UpdateSession; import org.apollo.net.session.UpdateSession;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelUpstreamHandler;
import org.jboss.netty.handler.timeout.IdleStateEvent;
/** /**
* An implementation of {@link SimpleChannelUpstreamHandler} which handles incoming upstream events from Netty. * An implementation of {@link SimpleChannelUpstreamHandler} which handles incoming upstream events from Netty.
* *
* @author Graham * @author Graham
*/ */
public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler { @Sharable
public final class ApolloHandler extends ChannelInboundHandlerAdapter {
/** /**
* The logger for this class. * The logger for this class.
@@ -47,58 +45,42 @@ public final class ApolloHandler extends IdleStateAwareChannelUpstreamHandler {
} }
@Override @Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { public void channelInactive(ChannelHandlerContext ctx) {
Channel channel = ctx.getChannel(); Channel channel = ctx.channel();
logger.info("Channel connected: " + channel); Session session = ctx.attr(NetworkConstants.SESSION_KEY).getAndRemove();
serverContext.getChannelGroup().add(channel); if (session != null) {
session.destroy();
} }
@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel channel = ctx.getChannel();
logger.info("Channel disconnected: " + channel); logger.info("Channel disconnected: " + channel);
serverContext.getChannelGroup().remove(channel); channel.close();
Object attachment = ctx.getAttachment();
if (attachment != null) {
((Session) attachment).destroy();
}
} }
@Override @Override
public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) { public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {
e.getChannel().close(); logger.log(Level.WARNING, "Exception occured for channel: " + ctx.channel() + ", closing...", e);
ctx.channel().close();
} }
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { public void channelRead(ChannelHandlerContext ctx, Object msg) {
logger.log(Level.WARNING, "Exception occured for channel: " + e.getChannel() + ", closing...", e.getCause()); if (ctx.attr(NetworkConstants.SESSION_KEY).get() == null) {
ctx.getChannel().close();
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if (ctx.getAttachment() == null) {
Object msg = e.getMessage();
if (msg instanceof HttpRequest || msg instanceof JagGrabRequest) { if (msg instanceof HttpRequest || msg instanceof JagGrabRequest) {
Session s = new UpdateSession(ctx.getChannel(), serverContext); new UpdateSession(ctx.channel(), serverContext).messageReceived(msg);
s.messageReceived(msg);
// we don't bother to set it as an attachment, as the connection
// will be closed once the request is completed anyway
} else { } else {
HandshakeMessage handshakeMessage = (HandshakeMessage) msg; HandshakeMessage handshakeMessage = (HandshakeMessage) msg;
switch (handshakeMessage.getServiceId()) { switch (handshakeMessage.getServiceId()) {
case HandshakeConstants.SERVICE_GAME: case HandshakeConstants.SERVICE_GAME:
ctx.setAttachment(new LoginSession(ctx.getChannel(), ctx, serverContext)); ctx.attr(NetworkConstants.SESSION_KEY).set(new LoginSession(ctx, serverContext));
break; break;
case HandshakeConstants.SERVICE_UPDATE: case HandshakeConstants.SERVICE_UPDATE:
ctx.setAttachment(new UpdateSession(ctx.getChannel(), serverContext)); ctx.attr(NetworkConstants.SESSION_KEY).set(new UpdateSession(ctx.channel(), serverContext));
break; break;
default: default:
throw new IllegalStateException("Invalid service id"); throw new IllegalStateException("Invalid service id");
} }
} }
} else { } else {
((Session) ctx.getAttachment()).messageReceived(e.getMessage()); ctx.attr(NetworkConstants.SESSION_KEY).get().messageReceived(msg);
} }
} }
@@ -0,0 +1,53 @@
package org.apollo.net;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.timeout.IdleStateHandler;
/**
* A {@link ChannelPipelineFactory} for the HTTP protocol.
*
* @author Graham
*/
public final class HttpChannelInitializer extends ChannelInitializer<SocketChannel> {
/**
* The maximum length of a request, in bytes.
*/
private static final int MAX_REQUEST_LENGTH = 8192;
/**
* The server event handler.
*/
private final ApolloHandler handler;
/**
* Creates the HTTP pipeline factory.
*
* @param handler The file server event handler.
*/
public HttpChannelInitializer(ApolloHandler handler) {
this.handler = handler;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// decoders
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("chunker", new HttpObjectAggregator(MAX_REQUEST_LENGTH));
// encoders
pipeline.addLast("encoder", new HttpResponseEncoder());
// handler
pipeline.addLast("timeout", new IdleStateHandler(NetworkConstants.IDLE_TIME, 0, 0));
pipeline.addLast("handler", handler);
}
}
@@ -1,63 +0,0 @@
package org.apollo.net;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.Timer;
/**
* A {@link ChannelPipelineFactory} for the HTTP protocol.
*
* @author Graham
*/
public final class HttpPipelineFactory implements ChannelPipelineFactory {
/**
* The maximum length of a request, in bytes.
*/
private static final int MAX_REQUEST_LENGTH = 8192;
/**
* The server event handler.
*/
private final ApolloHandler handler;
/**
* The timer used for idle checking.
*/
private final Timer timer;
/**
* Creates the HTTP pipeline factory.
*
* @param handler The file server event handler.
* @param timer The timer used for idle checking.
*/
public HttpPipelineFactory(ApolloHandler handler, Timer timer) {
this.handler = handler;
this.timer = timer;
}
@Override
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
// decoders
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("chunker", new HttpChunkAggregator(MAX_REQUEST_LENGTH));
// encoders
pipeline.addLast("encoder", new HttpResponseEncoder());
// handler
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0));
pipeline.addLast("handler", handler);
return pipeline;
}
}
@@ -1,30 +1,30 @@
package org.apollo.net; package org.apollo.net;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import org.apollo.net.codec.jaggrab.JagGrabRequestDecoder; import org.apollo.net.codec.jaggrab.JagGrabRequestDecoder;
import org.apollo.net.codec.jaggrab.JagGrabResponseEncoder; import org.apollo.net.codec.jaggrab.JagGrabResponseEncoder;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.Timer;
/** /**
* A {@link ChannelPipelineFactory} for the JAGGRAB protocol. * A {@link ChannelPipelineFactory} for the JAGGRAB protocol.
* *
* @author Graham * @author Graham
*/ */
public final class JagGrabPipelineFactory implements ChannelPipelineFactory { public final class JagGrabChannelInitializer extends ChannelInitializer<SocketChannel> {
/** /**
* A buffer with two line feed (LF) characters in it. * A buffer with two line feed (LF) characters in it.
*/ */
private static final ChannelBuffer DOUBLE_LINE_FEED_DELIMITER = ChannelBuffers.buffer(2); private static final ByteBuf DOUBLE_LINE_FEED_DELIMITER = Unpooled.buffer(2);
/** /**
* The character set used in the request. * The character set used in the request.
@@ -40,8 +40,7 @@ public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
* Populates the double line feed buffer. * Populates the double line feed buffer.
*/ */
static { static {
DOUBLE_LINE_FEED_DELIMITER.writeByte(10); DOUBLE_LINE_FEED_DELIMITER.writeByte(10).writeByte(10);
DOUBLE_LINE_FEED_DELIMITER.writeByte(10);
} }
/** /**
@@ -49,25 +48,18 @@ public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
*/ */
private final ApolloHandler handler; private final ApolloHandler handler;
/**
* The timer used for idle checking.
*/
private final Timer timer;
/** /**
* Creates a {@code JAGGRAB} pipeline factory. * Creates a {@code JAGGRAB} pipeline factory.
* *
* @param handler The file server event handler. * @param handler The file server event handler.
* @param timer The timer used for idle checking.
*/ */
public JagGrabPipelineFactory(ApolloHandler handler, Timer timer) { public JagGrabChannelInitializer(ApolloHandler handler) {
this.handler = handler; this.handler = handler;
this.timer = timer;
} }
@Override @Override
public ChannelPipeline getPipeline() { public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = Channels.pipeline(); ChannelPipeline pipeline = ch.pipeline();
// decoders // decoders
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(MAX_REQUEST_LENGTH, DOUBLE_LINE_FEED_DELIMITER)); pipeline.addLast("framer", new DelimiterBasedFrameDecoder(MAX_REQUEST_LENGTH, DOUBLE_LINE_FEED_DELIMITER));
@@ -78,10 +70,8 @@ public final class JagGrabPipelineFactory implements ChannelPipelineFactory {
pipeline.addLast("jaggrab-encoder", new JagGrabResponseEncoder()); pipeline.addLast("jaggrab-encoder", new JagGrabResponseEncoder());
// handler // handler
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0)); pipeline.addLast("timeout", new IdleStateHandler(NetworkConstants.IDLE_TIME, 0, 0));
pipeline.addLast("handler", handler); pipeline.addLast("handler", handler);
return pipeline;
} }
} }
+9
View File
@@ -1,7 +1,11 @@
package org.apollo.net; package org.apollo.net;
import io.netty.util.AttributeKey;
import java.math.BigInteger; import java.math.BigInteger;
import org.apollo.net.session.Session;
/** /**
* Holds various network-related constants such as port numbers. * Holds various network-related constants such as port numbers.
* *
@@ -39,6 +43,11 @@ public final class NetworkConstants {
*/ */
public static final int SERVICE_PORT = 43594; public static final int SERVICE_PORT = 43594;
/**
* The {@link Session} {@link AttributeKey}.
*/
public static final AttributeKey<Session> SESSION_KEY = AttributeKey.valueOf("session");
/** /**
* The terminator of a string. * The terminator of a string.
*/ */
@@ -0,0 +1,39 @@
package org.apollo.net;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import org.apollo.net.codec.handshake.HandshakeDecoder;
/**
* A {@link ChannelPipelineFactory} which creates {@link ChannelPipeline}s for the service pipeline.
*
* @author Graham
*/
public final class ServiceChannelInitializer extends ChannelInitializer<SocketChannel> {
/**
* The network event handler.
*/
private final ApolloHandler handler;
/**
* Creates the service pipeline factory.
*
* @param handler The networking event handler.
*/
public ServiceChannelInitializer(ApolloHandler handler) {
this.handler = handler;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("handshakeDecoder", new HandshakeDecoder());
pipeline.addLast("timeout", new IdleStateHandler(NetworkConstants.IDLE_TIME, 0, 0));
pipeline.addLast("handler", handler);
}
}
@@ -1,47 +0,0 @@
package org.apollo.net;
import org.apollo.net.codec.handshake.HandshakeDecoder;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.timeout.IdleStateHandler;
import org.jboss.netty.util.Timer;
/**
* A {@link ChannelPipelineFactory} which creates {@link ChannelPipeline}s for the service pipeline.
*
* @author Graham
*/
public final class ServicePipelineFactory implements ChannelPipelineFactory {
/**
* The network event handler.
*/
private final ApolloHandler handler;
/**
* The timer used for idle checking.
*/
private final Timer timer;
/**
* Creates the service pipeline factory.
*
* @param handler The networking event handler.
* @param timer The timer used for idle checking.
*/
public ServicePipelineFactory(ApolloHandler handler, Timer timer) {
this.handler = handler;
this.timer = timer;
}
@Override
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("handshakeDecoder", new HandshakeDecoder());
pipeline.addLast("timeout", new IdleStateHandler(timer, NetworkConstants.IDLE_TIME, 0, 0));
pipeline.addLast("handler", handler);
return pipeline;
}
}
@@ -1,18 +1,20 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import org.apollo.game.event.Event; import org.apollo.game.event.Event;
import org.apollo.net.release.EventDecoder; import org.apollo.net.release.EventDecoder;
import org.apollo.net.release.Release; import org.apollo.net.release.Release;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;
/** /**
* A {@link OneToOneDecoder} that decodes {@link GamePacket}s into {@link Event}s. * A {@link OneToOneDecoder} that decodes {@link GamePacket}s into {@link Event}s.
* *
* @author Graham * @author Graham
*/ */
public final class GameEventDecoder extends OneToOneDecoder { public final class GameEventDecoder extends MessageToMessageDecoder<GamePacket> {
/** /**
* The current release. * The current release.
@@ -29,17 +31,14 @@ public final class GameEventDecoder extends OneToOneDecoder {
} }
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) { protected void decode(ChannelHandlerContext ctx, GamePacket msg, List<Object> out) {
if (msg instanceof GamePacket) {
GamePacket packet = (GamePacket) msg; GamePacket packet = (GamePacket) msg;
EventDecoder<?> decoder = release.getEventDecoder(packet.getOpcode()); EventDecoder<?> decoder = release.getEventDecoder(packet.getOpcode());
if (decoder != null) { if (decoder != null) {
return decoder.decode(packet); out.add(decoder.decode(packet));
} } else {
System.out.println("Unidentified packet received - opcode: " + packet.getOpcode() + "."); System.out.println("Unidentified packet received - opcode: " + packet.getOpcode() + ".");
return null;
} }
return msg;
} }
} }
@@ -1,18 +1,20 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.util.List;
import org.apollo.game.event.Event; import org.apollo.game.event.Event;
import org.apollo.net.release.EventEncoder; import org.apollo.net.release.EventEncoder;
import org.apollo.net.release.Release; import org.apollo.net.release.Release;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
/** /**
* A {@link OneToOneEncoder} which encodes {@link Event}s into {@link GamePacket}s. * A {@link OneToOneEncoder} which encodes {@link Event}s into {@link GamePacket}s.
* *
* @author Graham * @author Graham
*/ */
public final class GameEventEncoder extends OneToOneEncoder { public final class GameEventEncoder extends MessageToMessageEncoder<Event> {
/** /**
* The current release. * The current release.
@@ -30,16 +32,11 @@ public final class GameEventEncoder extends OneToOneEncoder {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) { protected void encode(ChannelHandlerContext ctx, Event event, List<Object> out) {
if (msg instanceof Event) {
Event event = (Event) msg;
EventEncoder<Event> encoder = (EventEncoder<Event>) release.getEventEncoder(event.getClass()); EventEncoder<Event> encoder = (EventEncoder<Event>) release.getEventEncoder(event.getClass());
if (encoder != null) { if (encoder != null) {
return encoder.encode(event); out.add(encoder.encode(event));
} }
return null;
}
return msg;
} }
} }
@@ -1,7 +1,8 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import io.netty.buffer.ByteBuf;
import org.apollo.net.meta.PacketType; import org.apollo.net.meta.PacketType;
import org.jboss.netty.buffer.ChannelBuffer;
/** /**
* Represents a single packet used in the in-game protocol. * Represents a single packet used in the in-game protocol.
@@ -23,7 +24,7 @@ public final class GamePacket {
/** /**
* The payload. * The payload.
*/ */
private final ChannelBuffer payload; private final ByteBuf payload;
/** /**
* The packet type. * The packet type.
@@ -37,7 +38,7 @@ public final class GamePacket {
* @param type The packet type. * @param type The packet type.
* @param payload The payload. * @param payload The payload.
*/ */
public GamePacket(int opcode, PacketType type, ChannelBuffer payload) { public GamePacket(int opcode, PacketType type, ByteBuf payload) {
this.opcode = opcode; this.opcode = opcode;
this.type = type; this.type = type;
length = payload.readableBytes(); length = payload.readableBytes();
@@ -67,7 +68,7 @@ public final class GamePacket {
* *
* @return The payload. * @return The payload.
*/ */
public ChannelBuffer getPayload() { public ByteBuf getPayload() {
return payload; return payload;
} }
@@ -1,9 +1,10 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.apollo.net.NetworkConstants; import org.apollo.net.NetworkConstants;
import org.apollo.net.meta.PacketType; import org.apollo.net.meta.PacketType;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
/** /**
* A class which assists in creating a {@link GamePacket}. * A class which assists in creating a {@link GamePacket}.
@@ -20,7 +21,7 @@ public final class GamePacketBuilder {
/** /**
* The buffer. * The buffer.
*/ */
private final ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); private final ByteBuf buffer = Unpooled.buffer();
/** /**
* The current mode. * The current mode.
@@ -240,7 +241,7 @@ public final class GamePacketBuilder {
int requiredSpace = bytePos - buffer.writerIndex() + 1; int requiredSpace = bytePos - buffer.writerIndex() + 1;
requiredSpace += (numBits + 7) / 8; requiredSpace += (numBits + 7) / 8;
buffer.ensureWritableBytes(requiredSpace); buffer.ensureWritable(requiredSpace);
for (; numBits > bitOffset; bitOffset = 8) { for (; numBits > bitOffset; bitOffset = 8) {
int tmp = buffer.getByte(bytePos); int tmp = buffer.getByte(bytePos);
@@ -274,9 +275,9 @@ 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 ByteBuf}.
*/ */
public void putBytes(ChannelBuffer buffer) { public void putBytes(ByteBuf buffer) {
byte[] bytes = new byte[buffer.readableBytes()]; byte[] bytes = new byte[buffer.readableBytes()];
buffer.markReaderIndex(); buffer.markReaderIndex();
try { try {
@@ -318,9 +319,9 @@ 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 ByteBuf}.
*/ */
public void putBytesReverse(ChannelBuffer buffer) { public void putBytesReverse(ByteBuf buffer) {
byte[] bytes = new byte[buffer.readableBytes()]; byte[] bytes = new byte[buffer.readableBytes()];
buffer.markReaderIndex(); buffer.markReaderIndex();
try { try {
@@ -1,6 +1,11 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import net.burtleburtle.bob.rand.IsaacRandom; import net.burtleburtle.bob.rand.IsaacRandom;
@@ -8,10 +13,6 @@ import org.apollo.net.meta.PacketMetaData;
import org.apollo.net.meta.PacketType; import org.apollo.net.meta.PacketType;
import org.apollo.net.release.Release; import org.apollo.net.release.Release;
import org.apollo.util.StatefulFrameDecoder; import org.apollo.util.StatefulFrameDecoder;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
/** /**
* A {@link StatefulFrameDecoder} which decodes game packets. * A {@link StatefulFrameDecoder} which decodes game packets.
@@ -58,15 +59,18 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
} }
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, GameDecoderState state) protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, GameDecoderState state)
throws IOException { throws IOException {
switch (state) { switch (state) {
case GAME_OPCODE: case GAME_OPCODE:
return decodeOpcode(ctx, channel, buffer); decodeOpcode(ctx, in, out);
break;
case GAME_LENGTH: case GAME_LENGTH:
return decodeLength(ctx, channel, buffer); decodeLength(ctx, in, out);
break;
case GAME_PAYLOAD: case GAME_PAYLOAD:
return decodePayload(ctx, channel, buffer); decodePayload(ctx, in, out);
break;
default: default:
throw new IllegalStateException("Invalid game decoder state"); throw new IllegalStateException("Invalid game decoder state");
} }
@@ -81,11 +85,11 @@ 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) { private Object decodeLength(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
if (buffer.readable()) { if (buffer.isReadable()) {
length = buffer.readUnsignedByte(); length = buffer.readUnsignedByte();
if (length == 0) { if (length == 0) {
return decodeZeroLengthPacket(ctx, channel, buffer); decodeZeroLengthPacket(ctx, buffer, out);
} else { } else {
setState(GameDecoderState.GAME_PAYLOAD); setState(GameDecoderState.GAME_PAYLOAD);
} }
@@ -102,8 +106,8 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws IOException If a received opcode or packet type is illegal. * @throws IOException If a received opcode or packet type is illegal.
*/ */
private Object decodeOpcode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws IOException { private void decodeOpcode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws IOException {
if (buffer.readable()) { if (buffer.isReadable()) {
int encryptedOpcode = buffer.readUnsignedByte(); int encryptedOpcode = buffer.readUnsignedByte();
opcode = encryptedOpcode - random.nextInt() & 0xFF; opcode = encryptedOpcode - random.nextInt() & 0xFF;
@@ -117,7 +121,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
case FIXED: case FIXED:
length = metaData.getLength(); length = metaData.getLength();
if (length == 0) { if (length == 0) {
return decodeZeroLengthPacket(ctx, channel, buffer); decodeZeroLengthPacket(ctx, buffer, out);
} else { } else {
setState(GameDecoderState.GAME_PAYLOAD); setState(GameDecoderState.GAME_PAYLOAD);
} }
@@ -129,7 +133,6 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
throw new IOException("Illegal packet type: " + type); throw new IOException("Illegal packet type: " + type);
} }
} }
return null;
} }
/** /**
@@ -141,17 +144,16 @@ 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) { private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
if (buffer.readableBytes() >= length) { if (buffer.readableBytes() >= length) {
ChannelBuffer payload = buffer.readBytes(length); ByteBuf payload = buffer.readBytes(length);
setState(GameDecoderState.GAME_OPCODE); setState(GameDecoderState.GAME_OPCODE);
return new GamePacket(opcode, type, payload); out.add(new GamePacket(opcode, type, payload));
} }
return null;
} }
/** /**
* Decodes a zero length packet. This hackery is required as Netty will throw an Exception If we return a frame but * Decodes a zero length packet. This hackery is required as Netty will throw an exception if we return a frame but
* have read nothing! * have read nothing!
* *
* @param ctx The channel handler context. * @param ctx The channel handler context.
@@ -160,10 +162,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 void decodeZeroLengthPacket(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
ChannelBuffer payload = ChannelBuffers.buffer(0); ByteBuf payload = Unpooled.EMPTY_BUFFER;
setState(GameDecoderState.GAME_OPCODE); setState(GameDecoderState.GAME_OPCODE);
return new GamePacket(opcode, type, payload); out.add(new GamePacket(opcode, type, payload));
} }
} }
@@ -1,20 +1,22 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.util.List;
import net.burtleburtle.bob.rand.IsaacRandom; import net.burtleburtle.bob.rand.IsaacRandom;
import org.apollo.net.meta.PacketType; import org.apollo.net.meta.PacketType;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
/** /**
* A {@link OneToOneEncoder} which encodes in-game packets. * A {@link OneToOneEncoder} which encodes in-game packets.
* *
* @author Graham * @author Graham
*/ */
public final class GamePacketEncoder extends OneToOneEncoder { public final class GamePacketEncoder extends MessageToMessageEncoder<GamePacket> {
/** /**
* The random number generator. * The random number generator.
@@ -31,11 +33,7 @@ public final class GamePacketEncoder extends OneToOneEncoder {
} }
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { protected void encode(ChannelHandlerContext ctx, GamePacket msg, List<Object> out) throws Exception {
if (!(msg instanceof GamePacket)) {
return msg;
}
GamePacket packet = (GamePacket) msg; GamePacket packet = (GamePacket) msg;
PacketType type = packet.getType(); PacketType type = packet.getType();
int headerLength = 1; int headerLength = 1;
@@ -52,7 +50,7 @@ public final class GamePacketEncoder extends OneToOneEncoder {
} }
} }
ChannelBuffer buffer = ChannelBuffers.buffer(headerLength + payloadLength); ByteBuf buffer = Unpooled.buffer(headerLength + payloadLength);
buffer.writeByte(packet.getOpcode() + random.nextInt() & 0xFF); buffer.writeByte(packet.getOpcode() + random.nextInt() & 0xFF);
if (type == PacketType.VARIABLE_BYTE) { if (type == PacketType.VARIABLE_BYTE) {
buffer.writeByte(payloadLength); buffer.writeByte(payloadLength);
@@ -61,7 +59,7 @@ public final class GamePacketEncoder extends OneToOneEncoder {
} }
buffer.writeBytes(packet.getPayload()); buffer.writeBytes(packet.getPayload());
return buffer; out.add(buffer);
} }
} }
@@ -1,7 +1,8 @@
package org.apollo.net.codec.game; package org.apollo.net.codec.game;
import org.apollo.util.ChannelBufferUtil; import io.netty.buffer.ByteBuf;
import org.jboss.netty.buffer.ChannelBuffer;
import org.apollo.util.ByteBufUtil;
/** /**
* A utility class for reading {@link GamePacket}s. * A utility class for reading {@link GamePacket}s.
@@ -18,7 +19,7 @@ public final class GamePacketReader {
/** /**
* The buffer. * The buffer.
*/ */
private final ChannelBuffer buffer; private final ByteBuf buffer;
/** /**
* The current mode. * The current mode.
@@ -324,7 +325,7 @@ public final class GamePacketReader {
*/ */
public String getString() { public String getString() {
checkByteAccess(); checkByteAccess();
return ChannelBufferUtil.readString(buffer); return ByteBufUtil.readString(buffer);
} }
/** /**
@@ -1,14 +1,15 @@
package org.apollo.net.codec.handshake; package org.apollo.net.codec.handshake;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
import org.apollo.net.codec.login.LoginDecoder; import org.apollo.net.codec.login.LoginDecoder;
import org.apollo.net.codec.login.LoginEncoder; import org.apollo.net.codec.login.LoginEncoder;
import org.apollo.net.codec.update.UpdateDecoder; import org.apollo.net.codec.update.UpdateDecoder;
import org.apollo.net.codec.update.UpdateEncoder; import org.apollo.net.codec.update.UpdateEncoder;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
/** /**
* A {@link FrameDecoder} which decodes the handshake and makes changes to the pipeline as appropriate for the selected * A {@link FrameDecoder} which decodes the handshake and makes changes to the pipeline as appropriate for the selected
@@ -16,46 +17,37 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder;
* *
* @author Graham * @author Graham
*/ */
public final class HandshakeDecoder extends FrameDecoder { public final class HandshakeDecoder extends ByteToMessageDecoder {
/**
* Creates the handshake frame decoder.
*/
public HandshakeDecoder() {
super(true);
}
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) { protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
if (buffer.readable()) { if (buffer.isReadable()) {
int id = buffer.readUnsignedByte(); int id = buffer.readUnsignedByte();
switch (id) { switch (id) {
case HandshakeConstants.SERVICE_GAME: case HandshakeConstants.SERVICE_GAME:
ctx.getPipeline().addFirst("loginEncoder", new LoginEncoder()); ctx.pipeline().addFirst("loginEncoder", new LoginEncoder());
ctx.getPipeline().addBefore("handler", "loginDecoder", new LoginDecoder()); ctx.pipeline().addAfter("handshakeDecoder", "loginDecoder", new LoginDecoder());
break; break;
case HandshakeConstants.SERVICE_UPDATE: case HandshakeConstants.SERVICE_UPDATE:
ctx.getPipeline().addFirst("updateEncoder", new UpdateEncoder()); ctx.pipeline().addFirst("updateEncoder", new UpdateEncoder());
ctx.getPipeline().addBefore("handler", "updateDecoder", new UpdateDecoder()); ctx.pipeline().addBefore("handler", "updateDecoder", new UpdateDecoder());
ChannelBuffer buf = ChannelBuffers.buffer(8); ByteBuf buf = ctx.alloc().buffer(8);
buf.writeLong(0); buf.writeLong(0);
channel.write(buf); // TODO should it be here? ctx.channel().writeAndFlush(buf);
break; break;
default: default:
throw new IllegalArgumentException("Invalid service id"); throw new IllegalArgumentException("Invalid service id");
} }
ctx.getPipeline().remove(this); ctx.pipeline().remove(this);
HandshakeMessage message = new HandshakeMessage(id); HandshakeMessage message = new HandshakeMessage(id);
if (buffer.readable()) { out.add(message);
return new Object[] { message, buffer.readBytes(buffer.readableBytes()) }; if (buffer.isReadable()) {
out.add(buffer.readBytes(buffer.readableBytes()));
} }
return message;
} }
return null;
} }
} }
@@ -1,27 +1,26 @@
package org.apollo.net.codec.jaggrab; package org.apollo.net.codec.jaggrab;
import org.jboss.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageDecoder;
import org.jboss.netty.handler.codec.oneone.OneToOneDecoder;
import java.util.List;
/** /**
* A {@link OneToOneDecoder} for the JAGGRAB protocol. * A {@link OneToOneDecoder} for the JAGGRAB protocol.
* *
* @author Graham * @author Graham
*/ */
public final class JagGrabRequestDecoder extends OneToOneDecoder { public final class JagGrabRequestDecoder extends MessageToMessageDecoder<String> {
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel c, Object msg) { protected void decode(ChannelHandlerContext ctx, String msg, List<Object> out) {
if (msg instanceof String) { String request = (String) msg;
String str = (String) msg; if (request.startsWith("JAGGRAB /")) {
if (str.startsWith("JAGGRAB /")) { String filePath = request.substring(8).trim();
String filePath = str.substring(8).trim(); out.add(new JagGrabRequest(filePath));
return new JagGrabRequest(filePath); } else {
}
throw new IllegalArgumentException("corrupted request line"); throw new IllegalArgumentException("corrupted request line");
} }
return msg;
} }
} }
@@ -1,6 +1,6 @@
package org.apollo.net.codec.jaggrab; package org.apollo.net.codec.jaggrab;
import org.jboss.netty.buffer.ChannelBuffer; import io.netty.buffer.ByteBuf;
/** /**
* Represents a single JAGGRAB response. * Represents a single JAGGRAB response.
@@ -12,14 +12,14 @@ public final class JagGrabResponse {
/** /**
* The file data. * The file data.
*/ */
private final ChannelBuffer fileData; private final ByteBuf fileData;
/** /**
* Creates the response. * Creates the response.
* *
* @param fileData The file data. * @param fileData The file data.
*/ */
public JagGrabResponse(ChannelBuffer fileData) { public JagGrabResponse(ByteBuf fileData) {
this.fileData = fileData; this.fileData = fileData;
} }
@@ -28,7 +28,7 @@ public final class JagGrabResponse {
* *
* @return The file data. * @return The file data.
*/ */
public ChannelBuffer getFileData() { public ByteBuf getFileData() {
return fileData; return fileData;
} }
@@ -1,23 +1,20 @@
package org.apollo.net.codec.jaggrab; package org.apollo.net.codec.jaggrab;
import org.jboss.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageEncoder;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import java.util.List;
/** /**
* A {@link OneToOneEncoder} for the JAGGRAB protocol. * A {@link OneToOneEncoder} for the JAGGRAB protocol.
* *
* @author Graham * @author Graham
*/ */
public final class JagGrabResponseEncoder extends OneToOneEncoder { public final class JagGrabResponseEncoder extends MessageToMessageEncoder<JagGrabResponse> {
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) { protected void encode(ChannelHandlerContext ctx, JagGrabResponse response, List<Object> out) {
if (msg instanceof JagGrabResponse) { out.add(response.getFileData());
JagGrabResponse resp = (JagGrabResponse) msg;
return resp.getFileData();
}
return msg;
} }
} }
@@ -1,8 +1,13 @@
package org.apollo.net.codec.login; package org.apollo.net.codec.login;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.List;
import net.burtleburtle.bob.rand.IsaacRandom; import net.burtleburtle.bob.rand.IsaacRandom;
@@ -10,12 +15,8 @@ import org.apollo.fs.FileSystemConstants;
import org.apollo.net.NetworkConstants; import org.apollo.net.NetworkConstants;
import org.apollo.security.IsaacRandomPair; import org.apollo.security.IsaacRandomPair;
import org.apollo.security.PlayerCredentials; import org.apollo.security.PlayerCredentials;
import org.apollo.util.ChannelBufferUtil; import org.apollo.util.ByteBufUtil;
import org.apollo.util.StatefulFrameDecoder; import org.apollo.util.StatefulFrameDecoder;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
/** /**
* A {@link StatefulFrameDecoder} which decodes the login request frames. * A {@link StatefulFrameDecoder} which decodes the login request frames.
@@ -57,15 +58,18 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
} }
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, LoginDecoderState state) protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, LoginDecoderState state)
throws Exception { throws Exception {
switch (state) { switch (state) {
case LOGIN_HANDSHAKE: case LOGIN_HANDSHAKE:
return decodeHandshake(ctx, channel, buffer); decodeHandshake(ctx, in, out);
break;
case LOGIN_HEADER: case LOGIN_HEADER:
return decodeHeader(ctx, channel, buffer); decodeHeader(ctx, in, out);
break;
case LOGIN_PAYLOAD: case LOGIN_PAYLOAD:
return decodePayload(ctx, channel, buffer); decodePayload(ctx, in, out);
break;
default: default:
throw new IllegalStateException("Invalid login decoder state"); throw new IllegalStateException("Invalid login decoder state");
} }
@@ -80,20 +84,19 @@ 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) { private void decodeHandshake(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
if (buffer.readable()) { if (buffer.isReadable()) {
usernameHash = buffer.readUnsignedByte(); usernameHash = buffer.readUnsignedByte();
serverSeed = random.nextLong(); serverSeed = random.nextLong();
ChannelBuffer resp = ChannelBuffers.buffer(17); ByteBuf resp = ctx.alloc().buffer(17);
resp.writeByte(LoginConstants.STATUS_EXCHANGE_DATA); resp.writeByte(LoginConstants.STATUS_EXCHANGE_DATA);
resp.writeLong(0); resp.writeLong(0);
resp.writeLong(serverSeed); resp.writeLong(serverSeed);
channel.write(resp); ctx.channel().writeAndFlush(resp);
setState(LoginDecoderState.LOGIN_HEADER); setState(LoginDecoderState.LOGIN_HEADER);
} }
return null;
} }
/** /**
@@ -105,7 +108,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
* @return The frame, or {@code null}. * @return The frame, or {@code null}.
* @throws IOException If the login type sent by the client is invalid. * @throws IOException If the login type sent by the client is invalid.
*/ */
private Object decodeHeader(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws IOException { private void decodeHeader(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws IOException {
if (buffer.readableBytes() >= 2) { if (buffer.readableBytes() >= 2) {
int loginType = buffer.readUnsignedByte(); int loginType = buffer.readUnsignedByte();
@@ -114,12 +117,10 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
} }
reconnecting = loginType == LoginConstants.TYPE_RECONNECTION; reconnecting = loginType == LoginConstants.TYPE_RECONNECTION;
loginLength = buffer.readUnsignedByte(); loginLength = buffer.readUnsignedByte();
setState(LoginDecoderState.LOGIN_PAYLOAD); setState(LoginDecoderState.LOGIN_PAYLOAD);
} }
return null;
} }
/** /**
@@ -131,9 +132,9 @@ 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 decodePayload(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
if (buffer.readableBytes() >= loginLength) { if (buffer.readableBytes() >= loginLength) {
ChannelBuffer payload = buffer.readBytes(loginLength); ByteBuf payload = buffer.readBytes(loginLength);
if (payload.readUnsignedByte() != 0xFF) { if (payload.readUnsignedByte() != 0xFF) {
throw new Exception("Invalid magic id"); throw new Exception("Invalid magic id");
} }
@@ -157,12 +158,12 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
throw new Exception("Secure payload length mismatch"); throw new Exception("Secure payload length mismatch");
} }
ChannelBuffer securePayload = payload.readBytes(securePayloadLength); ByteBuf securePayload = payload.readBytes(securePayloadLength);
BigInteger bigInteger = new BigInteger(securePayload.array()); BigInteger bigInteger = new BigInteger(securePayload.array());
bigInteger = bigInteger.modPow(NetworkConstants.RSA_EXPONENT, NetworkConstants.RSA_MODULUS); bigInteger = bigInteger.modPow(NetworkConstants.RSA_EXPONENT, NetworkConstants.RSA_MODULUS);
securePayload = ChannelBuffers.wrappedBuffer(bigInteger.toByteArray()); securePayload = Unpooled.wrappedBuffer(bigInteger.toByteArray());
int secureId = securePayload.readUnsignedByte(); int secureId = securePayload.readUnsignedByte();
if (secureId != 10) { if (secureId != 10) {
@@ -177,8 +178,8 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
int uid = securePayload.readInt(); int uid = securePayload.readInt();
String username = ChannelBufferUtil.readString(securePayload); String username = ByteBufUtil.readString(securePayload);
String password = ChannelBufferUtil.readString(securePayload); String password = ByteBufUtil.readString(securePayload);
if (username.length() > 12 || password.length() > 20) { if (username.length() > 12 || password.length() > 20) {
throw new Exception("Username or password too long."); throw new Exception("Username or password too long.");
@@ -199,15 +200,14 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
PlayerCredentials credentials = new PlayerCredentials(username, password, usernameHash, uid); PlayerCredentials credentials = new PlayerCredentials(username, password, usernameHash, uid);
IsaacRandomPair randomPair = new IsaacRandomPair(encodingRandom, decodingRandom); IsaacRandomPair randomPair = new IsaacRandomPair(encodingRandom, decodingRandom);
LoginRequest req = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber, LoginRequest request = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber,
archiveCrcs); archiveCrcs);
if (buffer.readable()) { out.add(request);
return new Object[] { req, buffer.readBytes(buffer.readableBytes()) }; if (buffer.isReadable()) {
out.add(buffer.readBytes(buffer.readableBytes()));
} }
return req;
} }
return null;
} }
} }
@@ -1,34 +1,31 @@
package org.apollo.net.codec.login; package org.apollo.net.codec.login;
import org.jboss.netty.buffer.ChannelBuffer; import io.netty.buffer.ByteBuf;
import org.jboss.netty.buffer.ChannelBuffers; import io.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channel; import io.netty.handler.codec.MessageToMessageEncoder;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; import java.util.List;
/** /**
* A class which encodes login response messages. * A class which encodes login response messages.
* *
* @author Graham * @author Graham
*/ */
public final class LoginEncoder extends OneToOneEncoder { public final class LoginEncoder extends MessageToMessageEncoder<LoginResponse> {
@Override public LoginEncoder() {
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object message) { super(LoginResponse.class);
if (!(message instanceof LoginResponse)) {
return message;
} }
LoginResponse response = (LoginResponse) message; @Override
protected void encode(ChannelHandlerContext ctx, LoginResponse response, List<Object> out) {
ChannelBuffer buffer = ChannelBuffers.buffer(3); ByteBuf buffer = ctx.alloc().buffer(3);
buffer.writeByte(response.getStatus()); buffer.writeByte(response.getStatus());
if (response.getStatus() == LoginConstants.STATUS_OK) { if (response.getStatus() == LoginConstants.STATUS_OK) {
buffer.writeByte(response.getRights()); buffer.writeByte(response.getRights());
buffer.writeByte(response.isFlagged() ? 1 : 0); buffer.writeByte(response.isFlagged() ? 1 : 0);
} }
out.add(buffer);
return buffer;
} }
} }
@@ -1,7 +1,8 @@
package org.apollo.net.codec.update; package org.apollo.net.codec.update;
import io.netty.buffer.ByteBuf;
import org.apollo.fs.FileDescriptor; import org.apollo.fs.FileDescriptor;
import org.jboss.netty.buffer.ChannelBuffer;
/** /**
* Represents a single 'on-demand' response. * Represents a single 'on-demand' response.
@@ -13,7 +14,7 @@ public final class OnDemandResponse {
/** /**
* The chunk data. * The chunk data.
*/ */
private final ChannelBuffer chunkData; private final ByteBuf chunkData;
/** /**
* The chunk id. * The chunk id.
@@ -38,7 +39,7 @@ public final class OnDemandResponse {
* @param chunkId The chunk id. * @param chunkId The chunk id.
* @param chunkData The chunk data. * @param chunkData The chunk data.
*/ */
public OnDemandResponse(FileDescriptor fileDescriptor, int fileSize, int chunkId, ChannelBuffer chunkData) { public OnDemandResponse(FileDescriptor fileDescriptor, int fileSize, int chunkId, ByteBuf chunkData) {
this.fileDescriptor = fileDescriptor; this.fileDescriptor = fileDescriptor;
this.fileSize = fileSize; this.fileSize = fileSize;
this.chunkId = chunkId; this.chunkId = chunkId;
@@ -50,7 +51,7 @@ public final class OnDemandResponse {
* *
* @return The chunk data. * @return The chunk data.
*/ */
public ChannelBuffer getChunkData() { public ByteBuf getChunkData() {
return chunkData; return chunkData;
} }
@@ -1,32 +1,31 @@
package org.apollo.net.codec.update; package org.apollo.net.codec.update;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
import org.apollo.fs.FileDescriptor; import org.apollo.fs.FileDescriptor;
import org.apollo.net.codec.update.OnDemandRequest.Priority; import org.apollo.net.codec.update.OnDemandRequest.Priority;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
/** /**
* A {@link FrameDecoder} for the 'on-demand' protocol. * A {@link ByteToMessageDecoder} for the 'on-demand' protocol.
* *
* @author Graham * @author Graham
*/ */
public final class UpdateDecoder extends FrameDecoder { public final class UpdateDecoder extends ByteToMessageDecoder {
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel c, ChannelBuffer buf) { protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
if (buf.readableBytes() >= 4) { if (buffer.readableBytes() >= 4) {
int type = buf.readUnsignedByte() + 1; int type = buffer.readUnsignedByte() + 1;
int file = buf.readUnsignedShort(); int file = buffer.readUnsignedShort();
int priority = buf.readUnsignedByte(); Priority priority = Priority.valueOf(buffer.readUnsignedByte());
FileDescriptor desc = new FileDescriptor(type, file); FileDescriptor desc = new FileDescriptor(type, file);
Priority p = Priority.valueOf(priority); out.add(new OnDemandRequest(desc, priority));
return new OnDemandRequest(desc, p);
} }
return null;
} }
} }
@@ -1,39 +1,39 @@
package org.apollo.net.codec.update; package org.apollo.net.codec.update;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import java.util.List;
import org.apollo.fs.FileDescriptor; import org.apollo.fs.FileDescriptor;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
/** /**
* A {@link OneToOneEncoder} for the 'on-demand' protocol. * A {@link MessageToMessageEncoder} for the 'on-demand' protocol.
* *
* @author Graham * @author Graham
*/ */
public final class UpdateEncoder extends OneToOneEncoder { public final class UpdateEncoder extends MessageToMessageEncoder<OnDemandResponse> {
@Override @Override
protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) { protected void encode(ChannelHandlerContext ctx, OnDemandResponse msg, List<Object> out) {
if (msg instanceof OnDemandResponse) { if (msg instanceof OnDemandResponse) {
OnDemandResponse response = (OnDemandResponse) msg; OnDemandResponse response = (OnDemandResponse) msg;
FileDescriptor descriptor = response.getFileDescriptor(); FileDescriptor descriptor = response.getFileDescriptor();
int fileSize = response.getFileSize(); int fileSize = response.getFileSize();
int chunkId = response.getChunkId(); int chunkId = response.getChunkId();
ChannelBuffer chunkData = response.getChunkData(); ByteBuf chunkData = response.getChunkData();
ChannelBuffer buffer = ChannelBuffers.buffer(6 + chunkData.readableBytes()); ByteBuf buffer = ctx.alloc().buffer(6 + chunkData.readableBytes());
buffer.writeByte(descriptor.getType() - 1); buffer.writeByte(descriptor.getType() - 1);
buffer.writeShort(descriptor.getFile()); buffer.writeShort(descriptor.getFile());
buffer.writeShort(fileSize); buffer.writeShort(fileSize);
buffer.writeByte(chunkId); buffer.writeByte(chunkId);
buffer.writeBytes(chunkData); buffer.writeBytes(chunkData);
return buffer; out.add(buffer);
} }
return msg;
} }
} }
@@ -1,10 +1,11 @@
package org.apollo.net.release.r317; package org.apollo.net.release.r317;
import io.netty.buffer.Unpooled;
import org.apollo.game.event.impl.EnterAmountEvent; import org.apollo.game.event.impl.EnterAmountEvent;
import org.apollo.net.codec.game.GamePacket; import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.meta.PacketType; import org.apollo.net.meta.PacketType;
import org.apollo.net.release.EventEncoder; import org.apollo.net.release.EventEncoder;
import org.jboss.netty.buffer.ChannelBuffers;
/** /**
* An {@link EventEncoder} for the {@link EnterAmountEvent}. * An {@link EventEncoder} for the {@link EnterAmountEvent}.
@@ -15,7 +16,7 @@ public final class EnterAmountEventEncoder extends EventEncoder<EnterAmountEvent
@Override @Override
public GamePacket encode(EnterAmountEvent event) { public GamePacket encode(EnterAmountEvent event) {
return new GamePacket(27, PacketType.FIXED, ChannelBuffers.EMPTY_BUFFER); return new GamePacket(27, PacketType.FIXED, Unpooled.EMPTY_BUFFER);
} }
} }
@@ -2,7 +2,7 @@ package org.apollo.net.release.r317;
import org.apollo.game.event.impl.PlayerDesignEvent; import org.apollo.game.event.impl.PlayerDesignEvent;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
import org.apollo.game.model.Gender; import org.apollo.game.model.settings.Gender;
import org.apollo.net.codec.game.DataType; import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket; import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketReader; import org.apollo.net.codec.game.GamePacketReader;
@@ -5,12 +5,12 @@ import org.apollo.game.model.Animation;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
import org.apollo.game.model.Direction; import org.apollo.game.model.Direction;
import org.apollo.game.model.EquipmentConstants; import org.apollo.game.model.EquipmentConstants;
import org.apollo.game.model.Gender;
import org.apollo.game.model.Graphic; import org.apollo.game.model.Graphic;
import org.apollo.game.model.Inventory; import org.apollo.game.model.Inventory;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.def.EquipmentDefinition; import org.apollo.game.model.def.EquipmentDefinition;
import org.apollo.game.model.settings.Gender;
import org.apollo.game.sync.block.AnimationBlock; import org.apollo.game.sync.block.AnimationBlock;
import org.apollo.game.sync.block.AppearanceBlock; import org.apollo.game.sync.block.AppearanceBlock;
import org.apollo.game.sync.block.ChatBlock; import org.apollo.game.sync.block.ChatBlock;
@@ -1,10 +1,11 @@
package org.apollo.net.release.r377; package org.apollo.net.release.r377;
import io.netty.buffer.Unpooled;
import org.apollo.game.event.impl.EnterAmountEvent; import org.apollo.game.event.impl.EnterAmountEvent;
import org.apollo.net.codec.game.GamePacket; import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.meta.PacketType; import org.apollo.net.meta.PacketType;
import org.apollo.net.release.EventEncoder; import org.apollo.net.release.EventEncoder;
import org.jboss.netty.buffer.ChannelBuffers;
/** /**
* An {@link EventEncoder} for the {@link EnterAmountEvent}. * An {@link EventEncoder} for the {@link EnterAmountEvent}.
@@ -15,7 +16,7 @@ public final class EnterAmountEventEncoder extends EventEncoder<EnterAmountEvent
@Override @Override
public GamePacket encode(EnterAmountEvent event) { public GamePacket encode(EnterAmountEvent event) {
return new GamePacket(58, PacketType.FIXED, ChannelBuffers.EMPTY_BUFFER); return new GamePacket(58, PacketType.FIXED, Unpooled.EMPTY_BUFFER);
} }
} }
@@ -2,7 +2,7 @@ package org.apollo.net.release.r377;
import org.apollo.game.event.impl.PlayerDesignEvent; import org.apollo.game.event.impl.PlayerDesignEvent;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
import org.apollo.game.model.Gender; import org.apollo.game.model.settings.Gender;
import org.apollo.net.codec.game.DataType; import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket; import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketReader; import org.apollo.net.codec.game.GamePacketReader;
@@ -5,12 +5,12 @@ import org.apollo.game.model.Animation;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
import org.apollo.game.model.Direction; import org.apollo.game.model.Direction;
import org.apollo.game.model.EquipmentConstants; import org.apollo.game.model.EquipmentConstants;
import org.apollo.game.model.Gender;
import org.apollo.game.model.Graphic; import org.apollo.game.model.Graphic;
import org.apollo.game.model.Inventory; import org.apollo.game.model.Inventory;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.def.EquipmentDefinition; import org.apollo.game.model.def.EquipmentDefinition;
import org.apollo.game.model.settings.Gender;
import org.apollo.game.sync.block.AnimationBlock; import org.apollo.game.sync.block.AnimationBlock;
import org.apollo.game.sync.block.AppearanceBlock; import org.apollo.game.sync.block.AppearanceBlock;
import org.apollo.game.sync.block.ChatBlock; import org.apollo.game.sync.block.ChatBlock;
+7 -6
View File
@@ -1,5 +1,9 @@
package org.apollo.net.session; package org.apollo.net.session;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.logging.Level; import java.util.logging.Level;
@@ -13,9 +17,6 @@ import org.apollo.game.event.handler.chain.EventHandlerChain;
import org.apollo.game.event.handler.chain.EventHandlerChainGroup; import org.apollo.game.event.handler.chain.EventHandlerChainGroup;
import org.apollo.game.event.impl.LogoutEvent; import org.apollo.game.event.impl.LogoutEvent;
import org.apollo.game.model.Player; import org.apollo.game.model.Player;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
/** /**
* A game session. * A game session.
@@ -69,8 +70,8 @@ public final class GameSession extends Session {
*/ */
public void dispatchEvent(Event event) { public void dispatchEvent(Event event) {
Channel channel = getChannel(); Channel channel = getChannel();
if (channel.isBound() && channel.isConnected() && channel.isOpen()) { if (channel.isActive() && channel.isOpen()) {
ChannelFuture future = channel.write(event); ChannelFuture future = channel.writeAndFlush(event);
if (event.getClass() == LogoutEvent.class) { if (event.getClass() == LogoutEvent.class) {
future.addListener(ChannelFutureListener.CLOSE); future.addListener(ChannelFutureListener.CLOSE);
} }
@@ -106,7 +107,7 @@ public final class GameSession extends Session {
try { try {
chain.handle(player, event); chain.handle(player, event);
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.SEVERE, "Error handling event.", ex); logger.log(Level.SEVERE, "Error handling event: ", ex);
} }
} }
} }
+18 -17
View File
@@ -1,5 +1,10 @@
package org.apollo.net.session; package org.apollo.net.session;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import org.apollo.ServerContext; import org.apollo.ServerContext;
import org.apollo.game.GameService; import org.apollo.game.GameService;
import org.apollo.game.model.Player; import org.apollo.game.model.Player;
@@ -7,6 +12,7 @@ import org.apollo.game.model.World.RegistrationStatus;
import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.io.player.PlayerLoaderResponse;
import org.apollo.login.LoginService; import org.apollo.login.LoginService;
import org.apollo.net.ApolloHandler; import org.apollo.net.ApolloHandler;
import org.apollo.net.NetworkConstants;
import org.apollo.net.codec.game.GameEventDecoder; import org.apollo.net.codec.game.GameEventDecoder;
import org.apollo.net.codec.game.GameEventEncoder; import org.apollo.net.codec.game.GameEventEncoder;
import org.apollo.net.codec.game.GamePacketDecoder; import org.apollo.net.codec.game.GamePacketDecoder;
@@ -16,10 +22,6 @@ import org.apollo.net.codec.login.LoginRequest;
import org.apollo.net.codec.login.LoginResponse; import org.apollo.net.codec.login.LoginResponse;
import org.apollo.net.release.Release; import org.apollo.net.release.Release;
import org.apollo.security.IsaacRandomPair; import org.apollo.security.IsaacRandomPair;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
/** /**
* A login session. * A login session.
@@ -41,13 +43,12 @@ public final class LoginSession extends Session {
/** /**
* Creates a login session for the specified channel. * Creates a login session for the specified channel.
* *
* @param channel The channel. * @param ctx The context of the {@link ApolloHandler}.
* @param channelContext The context of the {@link ApolloHandler}.
* @param serverContext The server context. * @param serverContext The server context.
*/ */
public LoginSession(Channel channel, ChannelHandlerContext channelContext, ServerContext serverContext) { public LoginSession(ChannelHandlerContext ctx, ServerContext serverContext) {
super(channel); super(ctx.channel());
this.channelContext = channelContext; this.channelContext = ctx;
this.serverContext = serverContext; this.serverContext = serverContext;
} }
@@ -107,7 +108,7 @@ public final class LoginSession extends Session {
} }
} }
ChannelFuture future = channel.write(new LoginResponse(status, rights, log)); ChannelFuture future = channel.writeAndFlush(new LoginResponse(status, rights, log));
destroy(); destroy();
@@ -115,18 +116,18 @@ public final class LoginSession extends Session {
IsaacRandomPair randomPair = request.getRandomPair(); IsaacRandomPair randomPair = request.getRandomPair();
Release release = serverContext.getRelease(); Release release = serverContext.getRelease();
channel.getPipeline().addFirst("eventEncoder", new GameEventEncoder(release)); channel.pipeline().addFirst("eventEncoder", new GameEventEncoder(release));
channel.getPipeline().addBefore("eventEncoder", "gameEncoder", channel.pipeline().addBefore("eventEncoder", "gameEncoder",
new GamePacketEncoder(randomPair.getEncodingRandom())); new GamePacketEncoder(randomPair.getEncodingRandom()));
channel.getPipeline().addBefore("handler", "gameDecoder", channel.pipeline().addBefore("handler", "gameDecoder",
new GamePacketDecoder(randomPair.getDecodingRandom(), serverContext.getRelease())); new GamePacketDecoder(randomPair.getDecodingRandom(), serverContext.getRelease()));
channel.getPipeline().addAfter("gameDecoder", "eventDecoder", new GameEventDecoder(release)); channel.pipeline().addAfter("gameDecoder", "eventDecoder", new GameEventDecoder(release));
channel.getPipeline().remove("loginDecoder"); channel.pipeline().remove("loginDecoder");
channel.getPipeline().remove("loginEncoder"); channel.pipeline().remove("loginEncoder");
channelContext.setAttachment(player.getSession()); channelContext.attr(NetworkConstants.SESSION_KEY).set(player.getSession());
} else { } else {
future.addListener(ChannelFutureListener.CLOSE); future.addListener(ChannelFutureListener.CLOSE);
} }
+3 -3
View File
@@ -1,10 +1,10 @@
package org.apollo.net.session; package org.apollo.net.session;
import org.jboss.netty.channel.Channel; import io.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
/** /**
* A session which is used as the attachment of a {@link ChannelHandlerContext} in Netty. * A session which is used as an attribute of a {@link ChannelHandlerContext} in Netty.
* *
* @author Graham * @author Graham
*/ */
@@ -1,12 +1,13 @@
package org.apollo.net.session; package org.apollo.net.session;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.HttpRequest;
import org.apollo.ServerContext; import org.apollo.ServerContext;
import org.apollo.net.codec.jaggrab.JagGrabRequest; import org.apollo.net.codec.jaggrab.JagGrabRequest;
import org.apollo.net.codec.update.OnDemandRequest; import org.apollo.net.codec.update.OnDemandRequest;
import org.apollo.update.UpdateDispatcher; import org.apollo.update.UpdateDispatcher;
import org.apollo.update.UpdateService; import org.apollo.update.UpdateService;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.handler.codec.http.HttpRequest;
/** /**
* An update session. * An update session.
+1 -1
View File
@@ -1,6 +1,6 @@
/** /**
* Contains {@link org.apollo.net.session.Session} classes which are the * Contains {@link org.apollo.net.session.Session} classes which are the
* equivalent of Netty's {@link org.jboss.netty.channel.Channel}s but are * equivalent of Netty's {@link io.netty.channel.Channel}s but are
* designed for Apollo to use itself - unlike Netty's which are purely * designed for Apollo to use itself - unlike Netty's which are purely
* designed for networking. * designed for networking.
*/ */
+1 -1
View File
@@ -1,6 +1,6 @@
package org.apollo.update; package org.apollo.update;
import org.jboss.netty.channel.Channel; import io.netty.channel.Channel;
/** /**
* A specialised request which contains a channel as well as the request object itself. * A specialised request which contains a channel as well as the request object itself.
+24 -24
View File
@@ -1,5 +1,14 @@
package org.apollo.update; package org.apollo.update;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -11,14 +20,6 @@ import org.apollo.update.resource.CombinedResourceProvider;
import org.apollo.update.resource.HypertextResourceProvider; import org.apollo.update.resource.HypertextResourceProvider;
import org.apollo.update.resource.ResourceProvider; import org.apollo.update.resource.ResourceProvider;
import org.apollo.update.resource.VirtualResourceProvider; import org.apollo.update.resource.VirtualResourceProvider;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
/** /**
* A worker which services HTTP requests. * A worker which services HTTP requests.
@@ -60,8 +61,8 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
* @param description The error description. * @param description The error description.
* @return The error page as a buffer. * @return The error page as a buffer.
*/ */
private ChannelBuffer createErrorPage(HttpResponseStatus status, String description) { private ByteBuf createErrorPage(HttpResponseStatus status, String description) {
String title = status.getCode() + " " + status.getReasonPhrase(); String title = status.code() + " " + status.reasonPhrase();
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
@@ -75,7 +76,7 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
builder.append(SERVER_IDENTIFIER); builder.append(SERVER_IDENTIFIER);
builder.append(" Server</address></body></html>"); builder.append(" Server</address></body></html>");
return ChannelBuffers.copiedBuffer(builder.toString(), Charset.defaultCharset()); return Unpooled.copiedBuffer(builder.toString(), Charset.defaultCharset());
} }
/** /**
@@ -116,7 +117,7 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
String path = request.getUri(); String path = request.getUri();
ByteBuffer buf = provider.get(path); ByteBuffer buf = provider.get(path);
ChannelBuffer wrapped; ByteBuf wrapped;
HttpResponseStatus status = HttpResponseStatus.OK; HttpResponseStatus status = HttpResponseStatus.OK;
String mime = getMimeType(request.getUri()); String mime = getMimeType(request.getUri());
@@ -126,23 +127,22 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
wrapped = createErrorPage(status, "The page you requested could not be found."); wrapped = createErrorPage(status, "The page you requested could not be found.");
mime = "text/html"; mime = "text/html";
} else { } else {
wrapped = ChannelBuffers.wrappedBuffer(buf); wrapped = Unpooled.wrappedBuffer(buf);
} }
HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), status); HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), status);
response.setHeader("Date", new Date()); response.headers().set("Date", new Date());
response.setHeader("Server", SERVER_IDENTIFIER); response.headers().set("Server", SERVER_IDENTIFIER);
response.setHeader("Content-type", mime + ", charset=" + CHARACTER_SET.name()); response.headers().set("Content-type", mime + ", charset=" + CHARACTER_SET.name());
response.setHeader("Cache-control", "no-cache"); response.headers().set("Cache-control", "no-cache");
response.setHeader("Pragma", "no-cache"); response.headers().set("Pragma", "no-cache");
response.setHeader("Expires", new Date(0)); response.headers().set("Expires", new Date(0));
response.setHeader("Connection", "close"); response.headers().set("Connection", "close");
response.setHeader("Content-length", wrapped.readableBytes()); response.headers().set("Content-length", wrapped.readableBytes());
response.setChunked(false);
response.setContent(wrapped);
channel.write(response).addListener(ChannelFutureListener.CLOSE); channel.write(response);
channel.writeAndFlush(wrapped).addListener(ChannelFutureListener.CLOSE);
} }
} }
@@ -1,5 +1,10 @@
package org.apollo.update; package org.apollo.update;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -8,10 +13,6 @@ import org.apollo.net.codec.jaggrab.JagGrabRequest;
import org.apollo.net.codec.jaggrab.JagGrabResponse; import org.apollo.net.codec.jaggrab.JagGrabResponse;
import org.apollo.update.resource.ResourceProvider; import org.apollo.update.resource.ResourceProvider;
import org.apollo.update.resource.VirtualResourceProvider; import org.apollo.update.resource.VirtualResourceProvider;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFutureListener;
/** /**
* A worker which services JAGGRAB requests. * A worker which services JAGGRAB requests.
@@ -41,8 +42,8 @@ public final class JagGrabRequestWorker extends RequestWorker<JagGrabRequest, Re
if (buf == null) { if (buf == null) {
channel.close(); channel.close();
} else { } else {
ChannelBuffer wrapped = ChannelBuffers.wrappedBuffer(buf); ByteBuf wrapped = Unpooled.wrappedBuffer(buf);
channel.write(new JagGrabResponse(wrapped)).addListener(ChannelFutureListener.CLOSE); channel.writeAndFlush(new JagGrabResponse(wrapped)).addListener(ChannelFutureListener.CLOSE);
} }
} }
@@ -1,5 +1,9 @@
package org.apollo.update; package org.apollo.update;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@@ -7,9 +11,6 @@ import org.apollo.fs.FileDescriptor;
import org.apollo.fs.IndexedFileSystem; import org.apollo.fs.IndexedFileSystem;
import org.apollo.net.codec.update.OnDemandRequest; import org.apollo.net.codec.update.OnDemandRequest;
import org.apollo.net.codec.update.OnDemandResponse; import org.apollo.net.codec.update.OnDemandResponse;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
/** /**
* A worker which services 'on-demand' requests. * A worker which services 'on-demand' requests.
@@ -53,10 +54,10 @@ public final class OnDemandRequestWorker extends RequestWorker<OnDemandRequest,
byte[] tmp = new byte[chunkSize]; byte[] tmp = new byte[chunkSize];
buffer.get(tmp, 0, tmp.length); buffer.get(tmp, 0, tmp.length);
ChannelBuffer chunkData = ChannelBuffers.wrappedBuffer(tmp, 0, chunkSize); ByteBuf chunkData = Unpooled.wrappedBuffer(tmp, 0, chunkSize);
OnDemandResponse response = new OnDemandResponse(desc, length, chunk, chunkData); OnDemandResponse response = new OnDemandResponse(desc, length, chunk, chunkData);
channel.write(response); channel.writeAndFlush(response);
} }
} }
+2 -2
View File
@@ -1,8 +1,8 @@
package org.apollo.update; package org.apollo.update;
import java.io.IOException; import io.netty.channel.Channel;
import org.jboss.netty.channel.Channel; import java.io.IOException;
/** /**
* The base class for request workers. * The base class for request workers.
+3 -2
View File
@@ -1,13 +1,14 @@
package org.apollo.update; package org.apollo.update;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.HttpRequest;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.PriorityBlockingQueue;
import org.apollo.net.codec.jaggrab.JagGrabRequest; import org.apollo.net.codec.jaggrab.JagGrabRequest;
import org.apollo.net.codec.update.OnDemandRequest; import org.apollo.net.codec.update.OnDemandRequest;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.handler.codec.http.HttpRequest;
/** /**
* A class which dispatches requests to worker threads. * A class which dispatches requests to worker threads.
@@ -30,36 +30,36 @@ public final class HypertextResourceProvider extends ResourceProvider {
@Override @Override
public boolean accept(String path) throws IOException { public boolean accept(String path) throws IOException {
File f = new File(base, path); File file = new File(base, path);
URI target = f.toURI().normalize(); URI target = file.toURI().normalize();
if (target.toASCIIString().startsWith(base.toURI().normalize().toASCIIString())) { if (target.toASCIIString().startsWith(base.toURI().normalize().toASCIIString())) {
if (f.isDirectory()) { if (file.isDirectory()) {
f = new File(f, "index.html"); file = new File(file, "index.html");
} }
return f.exists(); return file.exists();
} }
return false; return false;
} }
@Override @Override
public ByteBuffer get(String path) throws IOException { public ByteBuffer get(String path) throws IOException {
File f = new File(base, path); File file = new File(base, path);
if (f.isDirectory()) { if (file.isDirectory()) {
f = new File(f, "index.html"); file = new File(file, "index.html");
} }
if (!f.exists()) { if (!file.exists()) {
return null; return null;
} }
RandomAccessFile raf = new RandomAccessFile(f, "r"); RandomAccessFile raf = new RandomAccessFile(file, "r");
ByteBuffer buf; ByteBuffer buffer;
try { try {
buf = raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length()); buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
} finally { } finally {
raf.close(); raf.close();
} }
return buf; return buffer;
} }
} }
@@ -1,15 +1,15 @@
package org.apollo.util; package org.apollo.util;
import io.netty.buffer.ByteBuf;
import org.apollo.net.NetworkConstants; import org.apollo.net.NetworkConstants;
import org.jboss.netty.buffer.ChannelBuffer;
/** /**
* A utility class which provides extra {@link ChannelBuffer}-related methods which deal with data types used in the * A utility class which provides extra {@link ByteBuf}-related methods which deal with data types used in the protocol.
* protocol.
* *
* @author Graham * @author Graham
*/ */
public final class ChannelBufferUtil { public final class ByteBufUtil {
/** /**
* Reads a string from the specified buffer. * Reads a string from the specified buffer.
@@ -17,10 +17,10 @@ public final class ChannelBufferUtil {
* @param buffer The buffer. * @param buffer The buffer.
* @return The string. * @return The string.
*/ */
public static String readString(ChannelBuffer buffer) { public static String readString(ByteBuf buffer) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
int character; int character;
while (buffer.readable() && (character = buffer.readUnsignedByte()) != NetworkConstants.STRING_TERMINATOR) { while (buffer.isReadable() && (character = buffer.readUnsignedByte()) != NetworkConstants.STRING_TERMINATOR) {
builder.append((char) character); builder.append((char) character);
} }
return builder.toString(); return builder.toString();
@@ -29,7 +29,7 @@ public final class ChannelBufferUtil {
/** /**
* Default private constructor to prevent instantiation by other classes. * Default private constructor to prevent instantiation by other classes.
*/ */
private ChannelBufferUtil() { private ByteBufUtil() {
} }
+17 -20
View File
@@ -1,11 +1,12 @@
package org.apollo.util; package org.apollo.util;
import org.jboss.netty.buffer.ChannelBuffer; import io.netty.buffer.ByteBuf;
import org.jboss.netty.channel.Channel; import io.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder; import io.netty.handler.codec.ByteToMessageDecoder;
import org.jboss.netty.handler.codec.replay.ReplayingDecoder; import io.netty.handler.codec.ReplayingDecoder;
import org.jboss.netty.handler.codec.replay.VoidEnum;
import java.util.List;
/** /**
* A stateful implementation of a {@link FrameDecoder} which may be extended and used by other classes. The current * A stateful implementation of a {@link FrameDecoder} which may be extended and used by other classes. The current
@@ -14,8 +15,8 @@ import org.jboss.netty.handler.codec.replay.VoidEnum;
* The state may be changed by calling the {@link StatefulFrameDecoder#setState(Enum)} method. * The state may be changed by calling the {@link StatefulFrameDecoder#setState(Enum)} method.
* *
* The current state is supplied as a parameter in the * The current state is supplied as a parameter in the
* {@link StatefulFrameDecoder#decode(ChannelHandlerContext, Channel, ChannelBuffer, Enum)} and * {@link StatefulFrameDecoder#decode(ChannelHandlerContext, Channel, ByteBuf, Enum)} and
* {@link StatefulFrameDecoder#decodeLast(ChannelHandlerContext, Channel, ChannelBuffer, Enum)} methods. * {@link StatefulFrameDecoder#decodeLast(ChannelHandlerContext, Channel, ByteBuf, Enum)} methods.
* *
* This class is not thread safe: it is recommended that the state is only set in the decode methods overriden. * This class is not thread safe: it is recommended that the state is only set in the decode methods overriden.
* *
@@ -25,7 +26,7 @@ import org.jboss.netty.handler.codec.replay.VoidEnum;
* @author Graham * @author Graham
* @param <T> The state enumeration. * @param <T> The state enumeration.
*/ */
public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecoder { public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMessageDecoder {
/** /**
* The current state. * The current state.
@@ -50,13 +51,12 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecod
* @throws NullPointerException If the state is {@code null}. * @throws NullPointerException If the state is {@code null}.
*/ */
public StatefulFrameDecoder(T state, boolean unwrap) { public StatefulFrameDecoder(T state, boolean unwrap) {
super(unwrap);
setState(state); setState(state);
} }
@Override @Override
protected final Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
return decode(ctx, channel, buffer, state); decode(ctx, in, out, state);
} }
/** /**
@@ -66,14 +66,12 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecod
* @param channel The channel. * @param channel The channel.
* @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.
*/ */
protected abstract Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state) protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, T state) throws Exception;
throws Exception;
@Override @Override
protected final Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) { protected final void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
return decodeLast(ctx, channel, buffer, state); decodeLast(ctx, in, out, state);
} }
/** /**
@@ -84,10 +82,9 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends FrameDecod
* @param channel The channel. * @param channel The channel.
* @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.
*/ */
protected Object decodeLast(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, T state) { protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, T state) {
return null;
} }
/** /**
@@ -41,7 +41,7 @@ public final class PluginContext {
* @param listener The listener. * @param listener The listener.
*/ */
public void addCommandListener(String name, CommandListener listener) { public void addCommandListener(String name, CommandListener listener) {
World.getWorld().getCommandDispatcher().register(name, listener); // TODO best way? World.getWorld().getCommandDispatcher().register(name, listener);
} }
/** /**
@@ -160,7 +160,6 @@ public final class PluginManager {
if (dependency == null) { if (dependency == null) {
throw new DependencyException("Unresolved dependency: " + dependencyId + "."); throw new DependencyException("Unresolved dependency: " + dependencyId + ".");
} }
start(env, plugin, plugins, started); start(env, plugin, plugins, started);
} }
@@ -1,66 +0,0 @@
package org.apollo.net.codec.game;
import static org.junit.Assert.*;
import net.burtleburtle.bob.rand.IsaacRandom;
import org.apollo.net.meta.PacketType;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.junit.Test;
/**
* A test for the {@link GamePacketEncoder} class.
* @author Graham
*/
public class TestGamePacketEncoder {
/**
* Tests the {@link GamePacketEncoder#encode(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.Channel, Object)}
* method.
* @throws Exception If an error occurs.
*/
@Test
public void testEncode() throws Exception {
// generates 243, 141, 34, -223, 121...
IsaacRandom random = new IsaacRandom(new int[] { 0, 0, 0, 0 });
GamePacketEncoder encoder = new GamePacketEncoder(random);
ChannelBuffer payload = ChannelBuffers.wrappedBuffer("Hello".getBytes());
GamePacket packet = new GamePacket(10, PacketType.FIXED, payload.copy());
ChannelBuffer buf = (ChannelBuffer) encoder.encode(null, null, packet);
assertEquals(6, buf.readableBytes());
assertEquals(253, buf.readUnsignedByte());
assertEquals('H', buf.readUnsignedByte());
assertEquals('e', buf.readUnsignedByte());
assertEquals('l', buf.readUnsignedByte());
assertEquals('l', buf.readUnsignedByte());
assertEquals('o', buf.readUnsignedByte());
packet = new GamePacket(9, PacketType.VARIABLE_BYTE, payload.copy());
buf = (ChannelBuffer) encoder.encode(null, null, packet);
assertEquals(7, buf.readableBytes());
assertEquals(150, buf.readUnsignedByte());
assertEquals(5, buf.readUnsignedByte());
assertEquals('H', buf.readUnsignedByte());
assertEquals('e', buf.readUnsignedByte());
assertEquals('l', buf.readUnsignedByte());
assertEquals('l', buf.readUnsignedByte());
assertEquals('o', buf.readUnsignedByte());
packet = new GamePacket(0, PacketType.VARIABLE_SHORT, payload.copy());
buf = (ChannelBuffer) encoder.encode(null, null, packet);
assertEquals(8, buf.readableBytes());
assertEquals(34, buf.readUnsignedByte());
assertEquals(5, buf.readUnsignedShort());
assertEquals('H', buf.readUnsignedByte());
assertEquals('e', buf.readUnsignedByte());
assertEquals('l', buf.readUnsignedByte());
assertEquals('l', buf.readUnsignedByte());
assertEquals('o', buf.readUnsignedByte());
}
}
@@ -1,49 +0,0 @@
package org.apollo.util;
import static org.junit.Assert.*;
import java.nio.ByteBuffer;
import org.apollo.net.NetworkConstants;
import org.junit.Test;
/**
* A test for the {@link ByteBufferUtil} class.
* @author Graham
*/
public class TestByteBufferUtil {
/**
* Tests the {@link ByteBufferUtil#readUnsignedTriByte(ByteBuffer)} method.
*/
@Test
public void testReadUnsignedTriByte() {
ByteBuffer buf = ByteBuffer.allocate(3);
buf.put((byte) 123);
buf.put((byte) 45);
buf.put((byte) 67);
buf.flip();
assertEquals(8072515, ByteBufferUtil.readUnsignedTriByte(buf));
}
/**
* Tests the {@link ByteBufferUtil#readString(ByteBuffer)} method.
*/
@Test
public void testReadString() {
ByteBuffer buf = ByteBuffer.allocate(8);
buf.put((byte) 'h');
buf.put((byte) 'e');
buf.put((byte) 'l');
buf.put((byte) 'l');
buf.put((byte) 'o');
buf.put((byte) NetworkConstants.STRING_TERMINATOR);
buf.put((byte) 66);
buf.put((byte) 6);
buf.flip();
assertEquals("hello", ByteBufferUtil.readString(buf));
}
}
@@ -1,44 +0,0 @@
package org.apollo.util;
import static org.junit.Assert.*;
import org.apollo.util.ChannelBufferUtil;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.junit.Test;
/**
* A test for the {@link ChannelBufferUtil} class.
* @author Graham
*/
public final class TestChannelBufferUtil {
/**
* Test the {@link ChannelBufferUtil#readString(ChannelBuffer)}
* method.
*/
@Test
public void testReadString() {
ChannelBuffer buf = ChannelBuffers.buffer(6);
buf.writeBytes(new byte[] { 'H', 'e', 'l', 'l', 'o', 10 });
String str = ChannelBufferUtil.readString(buf);
assertEquals("Hello", str);
buf = ChannelBuffers.buffer(5);
buf.writeBytes(new byte[] { 'W', 'o', 'r', 'l', 'd' });
str = ChannelBufferUtil.readString(buf);
assertEquals("World", str);
buf = ChannelBuffers.buffer(3);
buf.writeByte('!');
buf.writeByte(10);
buf.writeByte('.');
str = ChannelBufferUtil.readString(buf);
assertEquals("!", str);
str = ChannelBufferUtil.readString(buf);
assertEquals(".", str);
}
}
@@ -1,43 +0,0 @@
package org.apollo.util;
import static org.junit.Assert.*;
import java.io.IOException;
import org.junit.Test;
/**
* A test for the {@link CompressionUtil} class.
* @author Graham
*/
public class TestCompressionUtil {
/**
* Tests the {@link CompressionUtil#gzip(byte[])} and
* {@link CompressionUtil#ungzip(byte[], byte[])} methods.
* @throws IOException If an I/O error occurs.
*/
@Test
public void testGzip() throws IOException {
String str = "Hello, World!";
byte[] data = str.getBytes();
byte[] compressed = CompressionUtil.gzip(data);
CompressionUtil.ungzip(compressed, data);
assertEquals(str, new String(data));
}
/**
* Tests the {@link CompressionUtil#bzip2(byte[])} and
* {@link CompressionUtil#unbzip2(byte[], byte[])} methods.
* @throws IOException If an I/O error occurs.
*/
@Test
public void testBzip2() throws IOException {
String str = "Hello, World!";
byte[] data = str.getBytes();
byte[] compressed = CompressionUtil.bzip2(data);
CompressionUtil.unbzip2(compressed, data);
assertEquals(str, new String(data));
}
}
@@ -1,24 +0,0 @@
package org.apollo.util;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* A test for the {@link LanguageUtil} class.
* @author Graham
*/
public class TestLanguageUtil {
/**
* Tests the {@link LanguageUtil#getIndefiniteArticle(String)} method.
*/
@Test
public void testIndefiniteArticle() {
assertEquals("an", LanguageUtil.getIndefiniteArticle("apple"));
assertEquals("an", LanguageUtil.getIndefiniteArticle("urn"));
assertEquals("a", LanguageUtil.getIndefiniteArticle("nose"));
assertEquals("a", LanguageUtil.getIndefiniteArticle("foot"));
}
}
-48
View File
@@ -1,48 +0,0 @@
package org.apollo.util;
import static org.junit.Assert.*;
import org.junit.Test;
/**
* A test for the {@link TextUtil} class.
* @author Graham
*/
public class TestTextUtil {
/**
* Tests the {@link TextUtil#compress(String, byte[])} and
* {@link TextUtil#uncompress(byte[], int)} methods.
*/
@Test
public void testCompression() {
String str = "hello, world!";
byte[] compressed = new byte[128];
int len = TextUtil.compress(str, compressed);
String uncompressed = TextUtil.uncompress(compressed, len);
assertEquals(str, uncompressed);
}
/**
* Tests the {@link TextUtil#filterInvalidCharacters(String)} method.
*/
@Test
public void testFilter() {
String str = "this contains <<< invalid characters";
String filtered = "this contains invalid characters";
assertEquals(filtered, TextUtil.filterInvalidCharacters(str));
}
/**
* Tets the {@link TextUtil#capitalize(String)} method.
*/
@Test
public void testCapitalize() {
String str = "tHiS is CRAP capitAliZation. do You AGreE? YES!";
String capitalized = "This is crap capitalization. Do you agree? Yes!";
assertEquals(capitalized, TextUtil.capitalize(str));
}
}
@@ -1,99 +0,0 @@
package org.apollo.util.xml;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.Set;
import org.junit.Test;
import org.xml.sax.SAXException;
/**
* A test for the {@link XmlParser} class.
* @author Graham
*/
public final class TestXmlParser {
/**
* A test for the {@link XmlParser#parse(java.io.InputStream)} method.
* @throws SAXException If a SAX error occurs.
* @throws IOException If an I/O error occurs.
*/
@Test
public void testParseInputStream() throws SAXException, IOException {
XmlParser parser = new XmlParser();
InputStream is = new ByteArrayInputStream("<root a='1' b='2' c='3'><z><y><x></x></y></z></root>".getBytes());
XmlNode root = parser.parse(is);
assertEquals(root.getName(), "root");
assertEquals(root.getAttributeCount(), 3);
assertEquals(root.getChildCount(), 1);
assertFalse(root.hasValue());
Set<String> attributeNames = root.getAttributeNames();
assertTrue(attributeNames.contains("a"));
assertTrue(attributeNames.contains("b"));
assertTrue(attributeNames.contains("c"));
assertFalse(attributeNames.contains("z"));
assertFalse(attributeNames.contains("y"));
assertFalse(attributeNames.contains("x"));
assertEquals("1", root.getAttribute("a"));
assertEquals("2", root.getAttribute("b"));
assertEquals("3", root.getAttribute("c"));
assertNull(root.getAttribute("z"));
assertNull(root.getAttribute("y"));
assertNull(root.getAttribute("x"));
XmlNode[] firstChild = root.getChildren().toArray(new XmlNode[1]);
assertEquals(1, firstChild.length);
assertEquals("z", firstChild[0].getName());
XmlNode[] secondChild = firstChild[0].getChildren().toArray(new XmlNode[1]);
assertEquals(1, secondChild.length);
assertEquals("y", secondChild[0].getName());
XmlNode[] thirdChild = secondChild[0].getChildren().toArray(new XmlNode[1]);
assertEquals(1, thirdChild.length);
assertEquals("x", thirdChild[0].getName());
assertEquals(0, thirdChild[0].getChildCount());
}
/**
* A test for the {@link XmlParser#parse(java.io.Reader)} method.
* @throws SAXException If a SAX error occurs.
* @throws IOException If an I/O error occurs.
*/
@Test
public void testParseReader() throws SAXException, IOException {
XmlParser parser = new XmlParser();
Reader reader = new StringReader("<alphabet><a>1</a><b>2</b><c>3</c></alphabet>");
XmlNode root = parser.parse(reader);
assertEquals(root.getName(), "alphabet");
assertEquals(root.getAttributeCount(), 0);
assertEquals(root.getChildCount(), 3);
assertFalse(root.hasValue());
XmlNode[] children = root.getChildren().toArray(new XmlNode[3]);
assertEquals(children[0].getName(), "a");
assertEquals(children[1].getName(), "b");
assertEquals(children[2].getName(), "c");
assertEquals(children[0].getValue(), "1");
assertEquals(children[1].getValue(), "2");
assertEquals(children[2].getValue(), "3");
for (int i = 0; i < 3; i++) {
assertTrue(children[i].hasValue());
assertEquals(children[i].getAttributeCount(), 0);
}
}
}