Remove the World singleton.

This commit is contained in:
Major-
2015-03-28 13:46:50 +00:00
parent 7cf31a2888
commit 3bd3ddd226
68 changed files with 620 additions and 323 deletions
+2 -12
View File
@@ -81,7 +81,7 @@ class ProcMessageHandler < MessageHandler
# Creates the ProcMessageListener. # Creates the ProcMessageListener.
def initialize(block, option) def initialize(block, option)
super() super($world)
@block = block @block = block
@option = option @option = option
end end
@@ -200,15 +200,5 @@ def on_command(args, proc)
raise 'Command message must have one or two arguments.' unless (1..2).include?(args.length) raise 'Command message must have one or two arguments.' unless (1..2).include?(args.length)
rights = args.length == 2 ? args[1] : RIGHTS_STANDARD rights = args.length == 2 ? args[1] : RIGHTS_STANDARD
PluginContext::add_command_listener(args[0].to_s, ProcCommandListener.new(rights, proc)) $world.command_dispatcher.register(args[0].to_s, ProcCommandListener.new(rights, proc))
end
# Defines an action to be taken upon login.
def on_login(proc)
PluginContext::add_login_listener(ProcLoginListener.new(proc))
end
# Defines an action to be taken upon logout.
def on_logout(proc)
PluginContext::add_logout_listener(ProcLogoutListener.new(proc))
end end
+3 -1
View File
@@ -4,7 +4,9 @@ java_import 'org.apollo.game.model.Position'
# Sends the player's position. # Sends the player's position.
on :command, :pos, RIGHTS_MOD do |player, command| on :command, :pos, RIGHTS_MOD do |player, command|
player.send_message("You are at: #{player.position}.") position = player.position
player.send_message("You are at: #{position}.")
player.send_message("Local coordinates: (#{position.get_local_x}, #{position.get_local_y}).")
end end
# Teleports the player to the specified position. # Teleports the player to the specified position.
+1 -1
View File
@@ -47,7 +47,7 @@ def get_npc(hash)
z = hash.delete(:z) z = hash.delete(:z)
position = Position.new(hash.delete(:x), hash.delete(:y), z == nil ? 0 : z) position = Position.new(hash.delete(:x), hash.delete(:y), z == nil ? 0 : z)
return Npc.new(id, position) return Npc.new($world, id, position)
end end
# Applies a decoded hash (one aquired using parse_hash) to the specified npc. # Applies a decoded hash (one aquired using parse_hash) to the specified npc.
@@ -18,8 +18,8 @@ CHARACTER_DESIGN = 3559
# Sends the appropriate data to the client when the player logs in to the game. # Sends the appropriate data to the client when the player logs in to the game.
on :login do |event, player| on :login do |event, player|
if player.in_tutorial_island if player.in_tutorial_island
TutorialInstructions::show_instruction(player) # TutorialInstructions::show_instruction(player)
INITIAL_TABS.each_with_index { |tab, index| player.send(SwitchTabInterfaceMessage.new(index, tab)) } # INITIAL_TABS.each_with_index { |tab, index| player.send(SwitchTabInterfaceMessage.new(index, tab)) }
if (player.tutorial_island_progress == :not_started) if (player.tutorial_island_progress == :not_started)
show_hint_icon(player) show_hint_icon(player)
+11 -29
View File
@@ -52,7 +52,6 @@ public final class Server {
SocketAddress http = new InetSocketAddress(NetworkConstants.HTTP_PORT); SocketAddress http = new InetSocketAddress(NetworkConstants.HTTP_PORT);
SocketAddress jaggrab = new InetSocketAddress(NetworkConstants.JAGGRAB_PORT); SocketAddress jaggrab = new InetSocketAddress(NetworkConstants.JAGGRAB_PORT);
server.start();
server.bind(service, http, jaggrab); server.bind(service, http, jaggrab);
logger.fine("Starting apollo took " + (System.currentTimeMillis() - start) + " ms."); logger.fine("Starting apollo took " + (System.currentTimeMillis() - start) + " ms.");
} catch (Throwable t) { } catch (Throwable t) {
@@ -60,11 +59,6 @@ public final class Server {
} }
} }
/**
* The server's context.
*/
private ServerContext context;
/** /**
* The {@link ServerBootstrap} for the HTTP listener. * The {@link ServerBootstrap} for the HTTP listener.
*/ */
@@ -85,11 +79,6 @@ public final class Server {
*/ */
private final EventLoopGroup loopGroup = new NioEventLoopGroup(); private final EventLoopGroup loopGroup = new NioEventLoopGroup();
/**
* The service manager.
*/
private final ServiceManager serviceManager = new ServiceManager();
/** /**
* Creates the Apollo server. * Creates the Apollo server.
* *
@@ -109,13 +98,13 @@ public final class Server {
public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) { public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) {
try { try {
logger.fine("Binding service listener to address: " + serviceAddress + "..."); logger.fine("Binding service listener to address: " + serviceAddress + "...");
serviceBootstrap.bind(serviceAddress).sync(); serviceBootstrap.bind(serviceAddress).syncUninterruptibly();
logger.fine("Binding HTTP listener to address: " + httpAddress + "..."); logger.fine("Binding HTTP listener to address: " + httpAddress + "...");
httpBootstrap.bind(httpAddress).sync(); httpBootstrap.bind(httpAddress).syncUninterruptibly();
logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "..."); logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
jagGrabBootstrap.bind(jagGrabAddress).sync(); jagGrabBootstrap.bind(jagGrabAddress).syncUninterruptibly();
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.SEVERE, "Binding to a port failed: ensure apollo isn't already running.", e); logger.log(Level.SEVERE, "Binding to a port failed: ensure apollo isn't already running.", e);
System.exit(1); System.exit(1);
@@ -128,11 +117,9 @@ public final class Server {
* Initialises the server. * Initialises the server.
* *
* @param releaseClassName The class name of the current active {@link Release}. * @param releaseClassName The class name of the current active {@link Release}.
* @throws ClassNotFoundException If the release class could not be found. * @throws Exception If an error occurs.
* @throws IllegalAccessException If the release class could not be accessed.
* @throws InstantiationException If the release class could not be instantiated.
*/ */
public void init(String releaseClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException { public void init(String releaseClassName) throws Exception {
Class<?> clazz = Class.forName(releaseClassName); Class<?> clazz = Class.forName(releaseClassName);
Release release = (Release) clazz.newInstance(); Release release = (Release) clazz.newInstance();
@@ -142,7 +129,9 @@ public final class Server {
httpBootstrap.group(loopGroup); httpBootstrap.group(loopGroup);
jagGrabBootstrap.group(loopGroup); jagGrabBootstrap.group(loopGroup);
context = new ServerContext(release, serviceManager); World world = new World();
ServiceManager serviceManager = new ServiceManager(world);
ServerContext context = new ServerContext(release, serviceManager);
ApolloHandler handler = new ApolloHandler(context); ApolloHandler handler = new ApolloHandler(context);
ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler); ChannelInitializer<SocketChannel> serviceInitializer = new ServiceChannelInitializer(handler);
@@ -156,20 +145,13 @@ public final class Server {
ChannelInitializer<SocketChannel> jagGrabInitializer = new JagGrabChannelInitializer(handler); ChannelInitializer<SocketChannel> jagGrabInitializer = new JagGrabChannelInitializer(handler);
jagGrabBootstrap.channel(NioServerSocketChannel.class); jagGrabBootstrap.channel(NioServerSocketChannel.class);
jagGrabBootstrap.childHandler(jagGrabInitializer); jagGrabBootstrap.childHandler(jagGrabInitializer);
}
/** PluginManager manager = new PluginManager(world, new PluginContext(context));
* Starts the server.
*
* @throws Exception If an error occurs.
*/
public void start() throws Exception {
PluginManager manager = new PluginManager(new PluginContext(context));
serviceManager.startAll(); serviceManager.startAll();
int releaseNo = context.getRelease().getReleaseNumber(); int releaseNo = release.getReleaseNumber();
IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs", Integer.toString(releaseNo)), true); IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs", Integer.toString(releaseNo)), true);
World.getWorld().init(releaseNo, fs, manager); world.init(releaseNo, fs, manager);
} }
} }
+17 -1
View File
@@ -1,17 +1,33 @@
package org.apollo; package org.apollo;
import org.apollo.game.model.World;
/** /**
* Represents a service that the server provides. * Represents a service that the server provides for a {@link World}.
* *
* @author Graham * @author Graham
*/ */
public abstract class Service { public abstract class Service {
/**
* The World this Service is for.
*/
protected final World world;
/** /**
* The server context. * The server context.
*/ */
private ServerContext context; private ServerContext context;
/**
* Creates the Service.
*
* @param world The {@link World} the Service is for.
*/
public Service(World world) {
this.world = world;
}
/** /**
* Gets the {@link ServerContext}. * Gets the {@link ServerContext}.
* *
+8 -7
View File
@@ -7,6 +7,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.apollo.game.model.World;
import org.apollo.util.xml.XmlNode; import org.apollo.util.xml.XmlNode;
import org.apollo.util.xml.XmlParser; import org.apollo.util.xml.XmlParser;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@@ -31,12 +32,13 @@ public final class ServiceManager {
/** /**
* Creates and initializes the {@link ServiceManager}. * Creates and initializes the {@link ServiceManager}.
* *
* @param world The {@link World} to create the {@link Service}s for.
* @throws IOException If there is an error reading from the xml file. * @throws IOException If there is an error reading from the xml file.
* @throws SAXException If there is an error parsing the xml file. * @throws SAXException If there is an error parsing the xml file.
* @throws ReflectiveOperationException If there is an error accessing or creating services using reflection. * @throws ReflectiveOperationException If there is an error accessing or creating services using reflection.
*/ */
public ServiceManager() throws IOException, SAXException, ReflectiveOperationException { public ServiceManager(World world) throws IOException, SAXException, ReflectiveOperationException {
init(); init(world);
} }
/** /**
@@ -53,14 +55,13 @@ public final class ServiceManager {
/** /**
* Initializes this service manager. * Initializes this service manager.
* *
* @param world The {@link World} to create the {@link Service}s for.
* @throws SAXException If the service XML file could not be parsed. * @throws SAXException If the service XML file could not be parsed.
* @throws IOException If the file could not be accessed. * @throws IOException If the file could not be accessed.
* @throws IllegalAccessException If the service could not be accessed. * @throws ReflectiveOperationException If the Service could not be created.
* @throws InstantiationException If the service could not be instantiated.
* @throws ClassNotFoundException If the service could not be found.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void init() throws SAXException, IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { private void init(World world) throws SAXException, IOException, ReflectiveOperationException {
logger.fine("Registering services..."); logger.fine("Registering services...");
XmlParser parser = new XmlParser(); XmlParser parser = new XmlParser();
@@ -84,7 +85,7 @@ public final class ServiceManager {
} }
Class<? extends Service> service = (Class<? extends Service>) Class.forName(child.getValue()); Class<? extends Service> service = (Class<? extends Service>) Class.forName(child.getValue());
register((Class<Service>) service, service.newInstance()); register((Class<Service>) service, service.getConstructor(World.class).newInstance(world));
} }
} }
@@ -11,6 +11,7 @@ import java.util.function.Predicate;
import org.apollo.fs.IndexedFileSystem; import org.apollo.fs.IndexedFileSystem;
import org.apollo.fs.decoder.MapFileDecoder.MapDefinition; import org.apollo.fs.decoder.MapFileDecoder.MapDefinition;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.area.Region; import org.apollo.game.model.area.Region;
import org.apollo.game.model.area.RegionRepository; import org.apollo.game.model.area.RegionRepository;
import org.apollo.game.model.area.collision.CollisionMatrix; import org.apollo.game.model.area.collision.CollisionMatrix;
@@ -70,10 +71,11 @@ public final class GameObjectDecoder {
/** /**
* Decodes the GameObjects from their MapDefinitions. * Decodes the GameObjects from their MapDefinitions.
* *
* @param world The {@link World} containing the StaticGameObjects.
* @return The decoded objects. * @return The decoded objects.
* @throws IOException If there is an error decoding the {@link MapDefinition}s. * @throws IOException If there is an error decoding the {@link MapDefinition}s.
*/ */
public GameObject[] decode() throws IOException { public GameObject[] decode(World world) throws IOException {
Map<Integer, MapDefinition> definitions = MapFileDecoder.decode(fs); Map<Integer, MapDefinition> definitions = MapFileDecoder.decode(fs);
for (Entry<Integer, MapDefinition> entry : definitions.entrySet()) { for (Entry<Integer, MapDefinition> entry : definitions.entrySet()) {
@@ -85,7 +87,7 @@ public final class GameObjectDecoder {
ByteBuffer objects = fs.getFile(4, definition.getObjectFile()); ByteBuffer objects = fs.getFile(4, definition.getObjectFile());
ByteBuffer decompressed = ByteBuffer.wrap(CompressionUtil.degzip(objects)); ByteBuffer decompressed = ByteBuffer.wrap(CompressionUtil.degzip(objects));
decodeObjects(decompressed, x, y); decodeObjects(world, decompressed, x, y);
ByteBuffer terrain = fs.getFile(4, definition.getTerrainFile()); ByteBuffer terrain = fs.getFile(4, definition.getTerrainFile());
decompressed = ByteBuffer.wrap(CompressionUtil.degzip(terrain)); decompressed = ByteBuffer.wrap(CompressionUtil.degzip(terrain));
@@ -189,11 +191,12 @@ public final class GameObjectDecoder {
/** /**
* Decodes object data stored in the specified {@link ByteBuffer}. * Decodes object data stored in the specified {@link ByteBuffer}.
* *
* @param world The {@link World} containing the StaticGameObjects.
* @param buffer The ByteBuffer. * @param buffer The ByteBuffer.
* @param x The x coordinate of the top left tile of the map file. * @param x The x coordinate of the top left tile of the map file.
* @param y The y coordinate of the top left tile of the map file. * @param y The y coordinate of the top left tile of the map file.
*/ */
private void decodeObjects(ByteBuffer buffer, int x, int y) { private void decodeObjects(World world, ByteBuffer buffer, int x, int y) {
int id = -1; int id = -1;
int idOffset = BufferUtil.readSmart(buffer); int idOffset = BufferUtil.readSmart(buffer);
@@ -215,7 +218,7 @@ public final class GameObjectDecoder {
int orientation = attributes & 0x3; int orientation = attributes & 0x3;
Position position = new Position(x + localX, y + localY, height); Position position = new Position(x + localX, y + localY, height);
GameObject object = new StaticGameObject(id, position, type, orientation); GameObject object = new StaticGameObject(world, id, position, type, orientation);
objects.add(object); objects.add(object);
block(object, position); block(object, position);
+9 -12
View File
@@ -59,11 +59,13 @@ public final class GameService extends Service {
private ClientSynchronizer synchronizer; private ClientSynchronizer synchronizer;
/** /**
* Creates the game service. * Creates the GameService.
* *
* @param world The {@link World} the GameService is for.
* @throws Exception If an error occurs during initialization. * @throws Exception If an error occurs during initialization.
*/ */
public GameService() throws Exception { public GameService(World world) throws Exception {
super(world);
init(); init();
} }
@@ -74,7 +76,7 @@ public final class GameService extends Service {
*/ */
public void finalizePlayerUnregistration(Player player) { public void finalizePlayerUnregistration(Player player) {
synchronized (this) { synchronized (this) {
World.getWorld().unregister(player); world.unregister(player);
} }
} }
@@ -93,14 +95,12 @@ public final class GameService extends Service {
* @throws IOException If there is an error with the file (e.g. does not exist, cannot be read, does not contain * @throws IOException If there is an error with the file (e.g. does not exist, cannot be read, does not contain
* valid nodes). * valid nodes).
* @throws SAXException If there is an error parsing the file. * @throws SAXException If there is an error parsing the file.
* @throws ClassNotFoundException If a message handler could not be found. * @throws ReflectiveOperationException If a MessageHandler could not be created.
* @throws InstantiationException If a message handler could not be instantiated.
* @throws IllegalAccessException If a message handler could not be accessed.
*/ */
private void init() throws IOException, SAXException, ClassNotFoundException, InstantiationException, IllegalAccessException { private void init() throws IOException, SAXException, ReflectiveOperationException {
try (InputStream is = new FileInputStream("data/messages.xml")) { try (InputStream is = new FileInputStream("data/messages.xml")) {
MessageHandlerChainParser chainGroupParser = new MessageHandlerChainParser(is); MessageHandlerChainParser chainGroupParser = new MessageHandlerChainParser(is);
chainGroup = chainGroupParser.parse(); chainGroup = chainGroupParser.parse(world);
} }
try (InputStream is = new FileInputStream("data/synchronizer.xml")) { try (InputStream is = new FileInputStream("data/synchronizer.xml")) {
@@ -127,7 +127,6 @@ public final class GameService extends Service {
public void pulse() { public void pulse() {
synchronized (this) { synchronized (this) {
LoginService loginService = getContext().getService(LoginService.class); LoginService loginService = getContext().getService(LoginService.class);
World world = World.getWorld();
int unregistered = 0; int unregistered = 0;
Player old; Player old;
@@ -144,7 +143,7 @@ public final class GameService extends Service {
} }
world.pulse(); world.pulse();
synchronizer.synchronize(); synchronizer.synchronize(world.getPlayerRepository(), world.getNpcRepository());
} }
} }
@@ -156,8 +155,6 @@ public final class GameService extends Service {
* @return A {@link RegistrationStatus}. * @return A {@link RegistrationStatus}.
*/ */
public RegistrationStatus registerPlayer(Player player, GameSession session) { public RegistrationStatus registerPlayer(Player player, GameSession session) {
World world = World.getWorld();
synchronized (this) { synchronized (this) {
RegistrationStatus status = world.register(player); RegistrationStatus status = world.register(player);
if (status == RegistrationStatus.OK) { if (status == RegistrationStatus.OK) {
@@ -2,6 +2,7 @@ package org.apollo.game.command;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -18,10 +19,12 @@ public final class CommandDispatcher {
private final Map<String, CommandListener> listeners = new HashMap<>(); private final Map<String, CommandListener> listeners = new HashMap<>();
/** /**
* Creates the command dispatcher and registers a listener for the credits command. * Initialises this CommandDispatcher.
*
* @param authors The {@link Set} of plugin authors.
*/ */
public CommandDispatcher() { public void init(Set<String> authors) {
listeners.put("credits", new CreditsCommandListener()); listeners.put("credits", new CreditsCommandListener(authors));
} }
/** /**
@@ -4,9 +4,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.util.plugin.PluginManager;
import com.google.common.collect.ImmutableSet;
/** /**
* Implements a {@code ::credits} command that lists the authors of all plugins used in the server. * Implements a {@code ::credits} command that lists the authors of all plugins used in the server.
@@ -15,6 +15,20 @@ import org.apollo.util.plugin.PluginManager;
*/ */
public final class CreditsCommandListener extends CommandListener { public final class CreditsCommandListener extends CommandListener {
/**
* The Set of authors.
*/
private final Set<String> authors;
/**
* Creates the CreditsCommandListener.
*
* @param authors The {@link Set} of authors.
*/
public CreditsCommandListener(Set<String> authors) {
this.authors = ImmutableSet.copyOf(authors);
}
/* /*
* If you are considering removing this command, please bear in mind that Apollo took several people thousands of * If you are considering removing this command, please bear in mind that Apollo took several people thousands of
* hours to create. We released it to the world for free and it isn't much to ask to leave this command in. It isn't * hours to create. We released it to the world for free and it isn't much to ask to leave this command in. It isn't
@@ -26,9 +40,6 @@ public final class CreditsCommandListener extends CommandListener {
@Override @Override
public void execute(Player player, Command command) { public void execute(Player player, Command command) {
PluginManager mgr = World.getWorld().getPluginManager();
final Set<String> authors = mgr.getAuthors();
List<String> text = new ArrayList<>(12 + authors.size()); List<String> text = new ArrayList<>(12 + authors.size());
text.add("@dre@Apollo"); text.add("@dre@Apollo");
text.add("@dre@Introduction"); text.add("@dre@Introduction");
@@ -1,6 +1,7 @@
package org.apollo.game.message.handler; package org.apollo.game.message.handler;
import org.apollo.game.message.Message; import org.apollo.game.message.Message;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
@@ -11,6 +12,20 @@ import org.apollo.game.model.entity.Player;
*/ */
public abstract class MessageHandler<M extends Message> { public abstract class MessageHandler<M extends Message> {
/**
* The World the Message occurred in.
*/
protected final World world;
/**
* Creates the MessageHandler.
*
* @param world The {@link World} the {@link Message} occurred in.
*/
public MessageHandler(World world) {
this.world = world;
}
/** /**
* Handles a message. * Handles a message.
* *
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ButtonMessage; import org.apollo.game.message.impl.ButtonMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
@@ -12,6 +13,15 @@ import org.apollo.game.model.entity.Player;
*/ */
public final class BankButtonMessageHandler extends MessageHandler<ButtonMessage> { public final class BankButtonMessageHandler extends MessageHandler<ButtonMessage> {
/**
* Creates the BankButtonMessageHandler.
*
* @param world The {@link World} the {@link ButtonMessage} occurred in.
*/
public BankButtonMessageHandler(World world) {
super(world);
}
/** /**
* The withdraw as item button id. * The withdraw as item button id.
*/ */
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ItemActionMessage; import org.apollo.game.message.impl.ItemActionMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inter.EnterAmountListener; import org.apollo.game.model.inter.EnterAmountListener;
import org.apollo.game.model.inter.bank.BankConstants; import org.apollo.game.model.inter.bank.BankConstants;
@@ -41,21 +42,12 @@ public final class BankMessageHandler extends MessageHandler<ItemActionMessage>
} }
/** /**
* Handles a deposit action. * Creates the BankMessageHandler.
* *
* @param ctx The message handler context. * @param world The {@link World} the {@link ItemActionMessage} occurred in.
* @param player The player.
* @param message The message.
*/ */
private static void deposit(MessageHandlerContext ctx, Player player, ItemActionMessage message) { public BankMessageHandler(World world) {
int amount = optionToAmount(message.getOption()); super(world);
if (amount == -1) {
EnterAmountListener listener = new BankDepositEnterAmountListener(player, message.getSlot(), message.getId());
player.getInterfaceSet().openEnterAmountDialogue(listener);
} else if (!BankUtils.deposit(player, message.getSlot(), message.getId(), amount)) {
ctx.breakHandlerChain();
}
} }
@Override @Override
@@ -69,6 +61,24 @@ public final class BankMessageHandler extends MessageHandler<ItemActionMessage>
} }
} }
/**
* Handles a deposit action.
*
* @param ctx The message handler context.
* @param player The player.
* @param message The message.
*/
private void deposit(MessageHandlerContext ctx, Player player, ItemActionMessage message) {
int amount = optionToAmount(message.getOption());
if (amount == -1) {
EnterAmountListener listener = new BankDepositEnterAmountListener(player, message.getSlot(), message.getId());
player.getInterfaceSet().openEnterAmountDialogue(listener);
} else if (!BankUtils.deposit(player, message.getSlot(), message.getId(), amount)) {
ctx.breakHandlerChain();
}
}
/** /**
* Handles a withdraw action. * Handles a withdraw action.
* *
@@ -76,7 +86,7 @@ public final class BankMessageHandler extends MessageHandler<ItemActionMessage>
* @param player The player. * @param player The player.
* @param message The message. * @param message The message.
*/ */
private static void withdraw(MessageHandlerContext ctx, Player player, ItemActionMessage message) { private void withdraw(MessageHandlerContext ctx, Player player, ItemActionMessage message) {
int amount = optionToAmount(message.getOption()); int amount = optionToAmount(message.getOption());
if (amount == -1) { if (amount == -1) {
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ChatMessage; import org.apollo.game.message.impl.ChatMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.sync.block.SynchronizationBlock; import org.apollo.game.sync.block.SynchronizationBlock;
@@ -13,6 +14,15 @@ import org.apollo.game.sync.block.SynchronizationBlock;
*/ */
public final class ChatMessageHandler extends MessageHandler<ChatMessage> { public final class ChatMessageHandler extends MessageHandler<ChatMessage> {
/**
* Creates the ChatMessageHandler.
*
* @param world The {@link World} the {@link ChatMessage} occurred in.
*/
public ChatMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ChatMessage message) { public void handle(MessageHandlerContext ctx, Player player, ChatMessage message) {
player.getBlockSet().add(SynchronizationBlock.createChatBlock(player, message)); player.getBlockSet().add(SynchronizationBlock.createChatBlock(player, message));
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ChatMessage; import org.apollo.game.message.impl.ChatMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
@@ -12,6 +13,15 @@ import org.apollo.game.model.entity.Player;
*/ */
public final class ChatVerificationHandler extends MessageHandler<ChatMessage> { public final class ChatVerificationHandler extends MessageHandler<ChatMessage> {
/**
* Creates the ChatVerificationHandler.
*
* @param world The {@link World} the {@link ChatMessage} occurred in.
*/
public ChatVerificationHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ChatMessage message) { public void handle(MessageHandlerContext ctx, Player player, ChatMessage message) {
int color = message.getTextColor(); int color = message.getTextColor();
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ClosedInterfaceMessage; import org.apollo.game.message.impl.ClosedInterfaceMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
@@ -12,6 +13,15 @@ import org.apollo.game.model.entity.Player;
*/ */
public final class ClosedInterfaceMessageHandler extends MessageHandler<ClosedInterfaceMessage> { public final class ClosedInterfaceMessageHandler extends MessageHandler<ClosedInterfaceMessage> {
/**
* Creates the ClosedInterfaceMessageHandler.
*
* @param world The {@link World} the {@link ClosedInterfaceMessage} occurred in.
*/
public ClosedInterfaceMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ClosedInterfaceMessage message) { public void handle(MessageHandlerContext ctx, Player player, ClosedInterfaceMessage message) {
player.getInterfaceSet().interfaceClosed(); player.getInterfaceSet().interfaceClosed();
@@ -1,6 +1,7 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler.impl;
import org.apollo.game.command.Command; import org.apollo.game.command.Command;
import org.apollo.game.message.Message;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.CommandMessage; import org.apollo.game.message.impl.CommandMessage;
@@ -14,6 +15,15 @@ import org.apollo.game.model.entity.Player;
*/ */
public final class CommandMessageHandler extends MessageHandler<CommandMessage> { public final class CommandMessageHandler extends MessageHandler<CommandMessage> {
/**
* Creates the CommandMessageHandler.
*
* @param world The {@link World} the {@link Message} occurred in.
*/
public CommandMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, CommandMessage message) { public void handle(MessageHandlerContext ctx, Player player, CommandMessage message) {
String[] components = message.getCommand().split(" "); String[] components = message.getCommand().split(" ");
@@ -23,7 +33,7 @@ public final class CommandMessageHandler extends MessageHandler<CommandMessage>
System.arraycopy(components, 1, arguments, 0, arguments.length); System.arraycopy(components, 1, arguments, 0, arguments.length);
Command command = new Command(name, arguments); Command command = new Command(name, arguments);
World.getWorld().getCommandDispatcher().dispatch(player, command); world.getCommandDispatcher().dispatch(player, command);
} }
} }
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ButtonMessage; import org.apollo.game.message.impl.ButtonMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inter.InterfaceType; import org.apollo.game.model.inter.InterfaceType;
@@ -14,12 +15,21 @@ import org.apollo.game.model.inter.InterfaceType;
*/ */
public final class DialogueButtonHandler extends MessageHandler<ButtonMessage> { public final class DialogueButtonHandler extends MessageHandler<ButtonMessage> {
/**
* Creates the DialogueButtonHandler.
*
* @param world The {@link World} the {@link ButtonMessage} occurred in.
*/
public DialogueButtonHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ButtonMessage message) { public void handle(MessageHandlerContext ctx, Player player, ButtonMessage message) {
if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) { if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) {
boolean breakChain = player.getInterfaceSet().buttonClicked(message.getWidgetId()); boolean terminate = player.getInterfaceSet().buttonClicked(message.getWidgetId());
if (breakChain) { if (terminate) {
ctx.breakHandlerChain(); ctx.breakHandlerChain();
} }
} }
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.DialogueContinueMessage; import org.apollo.game.message.impl.DialogueContinueMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inter.InterfaceType; import org.apollo.game.model.inter.InterfaceType;
@@ -13,6 +14,15 @@ import org.apollo.game.model.inter.InterfaceType;
*/ */
public final class DialogueContinueMessageHandler extends MessageHandler<DialogueContinueMessage> { public final class DialogueContinueMessageHandler extends MessageHandler<DialogueContinueMessage> {
/**
* Creates the DialogueContinueMessageHandler.
*
* @param world The {@link World} the {@link DialogueContinueMessage} occurred in.
*/
public DialogueContinueMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, DialogueContinueMessage message) { public void handle(MessageHandlerContext ctx, Player player, DialogueContinueMessage message) {
if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) { if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) {
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.EnteredAmountMessage; import org.apollo.game.message.impl.EnteredAmountMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
@@ -12,6 +13,15 @@ import org.apollo.game.model.entity.Player;
*/ */
public final class EnteredAmountMessageHandler extends MessageHandler<EnteredAmountMessage> { public final class EnteredAmountMessageHandler extends MessageHandler<EnteredAmountMessage> {
/**
* Creates the EnteredAmountMessageHandler.
*
* @param world The {@link World} the {@link EnteredAmountMessage} occurred in.
*/
public EnteredAmountMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, EnteredAmountMessage message) { public void handle(MessageHandlerContext ctx, Player player, EnteredAmountMessage message) {
player.getInterfaceSet().enteredAmount(message.getAmount()); player.getInterfaceSet().enteredAmount(message.getAmount());
@@ -4,6 +4,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ItemOptionMessage; import org.apollo.game.message.impl.ItemOptionMessage;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.World;
import org.apollo.game.model.def.EquipmentDefinition; import org.apollo.game.model.def.EquipmentDefinition;
import org.apollo.game.model.entity.EquipmentConstants; import org.apollo.game.model.entity.EquipmentConstants;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -21,9 +22,23 @@ import org.apollo.util.LanguageUtil;
*/ */
public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> { public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> {
/**
* The option used when equipping an item.
*/
private static final int EQUIP_OPTION = 2;
/**
* Creates the EquipItemHandler.
*
* @param world The {@link World} the {@link ItemOptionMessage} occurred in.
*/
public EquipItemHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemOptionMessage message) { public void handle(MessageHandlerContext ctx, Player player, ItemOptionMessage message) {
if (message.getOption() != 2 || message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID) { if (message.getOption() != EQUIP_OPTION || message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID) {
return; return;
} }
@@ -82,7 +97,8 @@ public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> {
return; return;
} }
if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null && EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) { if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null
&& EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) {
equipment.set(EquipmentConstants.SHIELD, inventory.reset(inventorySlot)); equipment.set(EquipmentConstants.SHIELD, inventory.reset(inventorySlot));
inventory.add(equipment.reset(EquipmentConstants.WEAPON)); inventory.add(equipment.reset(EquipmentConstants.WEAPON));
return; return;
@@ -4,6 +4,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ItemOnItemMessage; import org.apollo.game.message.impl.ItemOnItemMessage;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inter.bank.BankConstants; import org.apollo.game.model.inter.bank.BankConstants;
import org.apollo.game.model.inv.Inventory; import org.apollo.game.model.inv.Inventory;
@@ -16,6 +17,15 @@ import org.apollo.game.model.inv.SynchronizationInventoryListener;
*/ */
public final class ItemOnItemVerificationHandler extends MessageHandler<ItemOnItemMessage> { public final class ItemOnItemVerificationHandler extends MessageHandler<ItemOnItemMessage> {
/**
* Creates the ItemOnItemVerificationHandler.
*
* @param world The {@link World} the {@link ItemOnItemMessage} occurred in.
*/
public ItemOnItemVerificationHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemOnItemMessage message) { public void handle(MessageHandlerContext ctx, Player player, ItemOnItemMessage message) {
Inventory inventory; Inventory inventory;
@@ -4,6 +4,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ItemOnObjectMessage; import org.apollo.game.message.impl.ItemOnObjectMessage;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inter.bank.BankConstants; import org.apollo.game.model.inter.bank.BankConstants;
import org.apollo.game.model.inv.Inventory; import org.apollo.game.model.inv.Inventory;
@@ -16,9 +17,19 @@ import org.apollo.game.model.inv.SynchronizationInventoryListener;
*/ */
public final class ItemOnObjectVerificationHandler extends MessageHandler<ItemOnObjectMessage> { public final class ItemOnObjectVerificationHandler extends MessageHandler<ItemOnObjectMessage> {
/**
* Creates the ItemOnObjectVerificationHandler.
*
* @param world The {@link World} the {@link ItemOnObjectMessage} occurred in.
*/
public ItemOnObjectVerificationHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemOnObjectMessage message) { public void handle(MessageHandlerContext ctx, Player player, ItemOnObjectMessage message) {
if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID && message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) { if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID
&& message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) {
ctx.breakHandlerChain(); ctx.breakHandlerChain();
return; return;
} }
@@ -7,6 +7,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.InventoryItemMessage; import org.apollo.game.message.impl.InventoryItemMessage;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inter.bank.BankConstants; import org.apollo.game.model.inter.bank.BankConstants;
import org.apollo.game.model.inv.Inventory; import org.apollo.game.model.inv.Inventory;
@@ -20,6 +21,15 @@ import org.apollo.game.model.inv.SynchronizationInventoryListener;
*/ */
public final class ItemVerificationHandler extends MessageHandler<InventoryItemMessage> { public final class ItemVerificationHandler extends MessageHandler<InventoryItemMessage> {
/**
* Creates the ItemVerificationHandler.
*
* @param world The {@link World} the {@link InventoryItemMessage} occurred in.
*/
public ItemVerificationHandler(World world) {
super(world);
}
/** /**
* A supplier for an {@link Inventory}. * A supplier for an {@link Inventory}.
* *
@@ -18,13 +18,18 @@ import org.apollo.util.MobRepository;
public final class NpcActionVerificationHandler extends MessageHandler<NpcActionMessage> { public final class NpcActionVerificationHandler extends MessageHandler<NpcActionMessage> {
/** /**
* The world's npc repository. * Creates the NpcActionVerificationHandler.
*
* @param world The {@link World} the {@link NpcActionMessage} occurred in.
*/ */
private final MobRepository<Npc> repository = World.getWorld().getNpcRepository(); public NpcActionVerificationHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, NpcActionMessage message) { public void handle(MessageHandlerContext ctx, Player player, NpcActionMessage message) {
int index = message.getIndex(); int index = message.getIndex();
MobRepository<Npc> repository = world.getNpcRepository();
if (index < 0 || index >= repository.capacity()) { if (index < 0 || index >= repository.capacity()) {
ctx.breakHandlerChain(); ctx.breakHandlerChain();
@@ -9,7 +9,6 @@ import org.apollo.game.message.impl.ObjectActionMessage;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World; import org.apollo.game.model.World;
import org.apollo.game.model.area.Region; import org.apollo.game.model.area.Region;
import org.apollo.game.model.area.RegionRepository;
import org.apollo.game.model.def.ObjectDefinition; import org.apollo.game.model.def.ObjectDefinition;
import org.apollo.game.model.entity.Entity.EntityType; import org.apollo.game.model.entity.Entity.EntityType;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -23,9 +22,24 @@ import org.apollo.game.model.entity.obj.GameObject;
public final class ObjectActionVerificationHandler extends MessageHandler<ObjectActionMessage> { public final class ObjectActionVerificationHandler extends MessageHandler<ObjectActionMessage> {
/** /**
* The world's RegionRepository. * Indicates whether or not the {@link List} of {@link GameObject}s contains the object with the specified id.
*
* @param id The id of the object.
* @param objects The list of objects.
* @return {@code true} if the list does contain the object with the specified id, otherwise {@code false}.
*/ */
private final RegionRepository repository = World.getWorld().getRegionRepository(); private static boolean containsObject(int id, Set<GameObject> objects) {
return objects.stream().anyMatch(object -> object.getId() == id);
}
/**
* Creates the ObjectActionVerificationHandler.
*
* @param world The {@link World} the {@link ObjectActionMessage} occurred in.
*/
public ObjectActionVerificationHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ObjectActionMessage message) { public void handle(MessageHandlerContext ctx, Player player, ObjectActionMessage message) {
@@ -35,9 +49,8 @@ public final class ObjectActionVerificationHandler extends MessageHandler<Object
return; return;
} }
Position position = message.getPosition(); Position position = message.getPosition();
Region region = repository.fromPosition(position); Region region = world.getRegionRepository().fromPosition(position);
Set<GameObject> objects = region.getEntities(position, EntityType.STATIC_OBJECT, EntityType.DYNAMIC_OBJECT); Set<GameObject> objects = region.getEntities(position, EntityType.STATIC_OBJECT, EntityType.DYNAMIC_OBJECT);
if (!player.getPosition().isWithinDistance(position, 15) || !containsObject(id, objects)) { if (!player.getPosition().isWithinDistance(position, 15) || !containsObject(id, objects)) {
@@ -52,15 +65,4 @@ public final class ObjectActionVerificationHandler extends MessageHandler<Object
} }
} }
/**
* Indicates whether or not the {@link List} of {@link GameObject}s contains the object with the specified id.
*
* @param id The id of the object.
* @param objects The list of objects.
* @return {@code true} if the list does contain the object with the specified id, otherwise {@code false}.
*/
private static boolean containsObject(int id, Set<GameObject> objects) {
return objects.stream().anyMatch(object -> object.getId() == id);
}
} }
@@ -15,13 +15,18 @@ import org.apollo.util.MobRepository;
public final class PlayerActionVerificationHandler extends MessageHandler<PlayerActionMessage> { public final class PlayerActionVerificationHandler extends MessageHandler<PlayerActionMessage> {
/** /**
* The world's player repository. * Creates the PlayerActionVerificationHandler.
*
* @param world The {@link World} the {@link PlayerActionMessage} occurred in.
*/ */
private final MobRepository<Player> repository = World.getWorld().getPlayerRepository(); public PlayerActionVerificationHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, PlayerActionMessage message) { public void handle(MessageHandlerContext ctx, Player player, PlayerActionMessage message) {
int index = message.getIndex(); int index = message.getIndex();
MobRepository<Player> repository = world.getPlayerRepository();
if (index < 0 || index >= repository.capacity()) { if (index < 0 || index >= repository.capacity()) {
ctx.breakHandlerChain(); ctx.breakHandlerChain();
@@ -4,6 +4,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.CloseInterfaceMessage; import org.apollo.game.message.impl.CloseInterfaceMessage;
import org.apollo.game.message.impl.PlayerDesignMessage; import org.apollo.game.message.impl.PlayerDesignMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
@@ -13,6 +14,15 @@ import org.apollo.game.model.entity.Player;
*/ */
public final class PlayerDesignMessageHandler extends MessageHandler<PlayerDesignMessage> { public final class PlayerDesignMessageHandler extends MessageHandler<PlayerDesignMessage> {
/**
* Creates the PlayerDesignMessageHandler.
*
* @param world The {@link World} the {@link PlayerDesignMessage} occurred in.
*/
public PlayerDesignMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, PlayerDesignMessage message) { public void handle(MessageHandlerContext ctx, Player player, PlayerDesignMessage message) {
player.setAppearance(message.getAppearance()); player.setAppearance(message.getAppearance());
@@ -4,6 +4,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.PlayerDesignMessage; import org.apollo.game.message.impl.PlayerDesignMessage;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.entity.setting.Gender; import org.apollo.game.model.entity.setting.Gender;
@@ -14,6 +15,15 @@ import org.apollo.game.model.entity.setting.Gender;
*/ */
public final class PlayerDesignVerificationHandler extends MessageHandler<PlayerDesignMessage> { public final class PlayerDesignVerificationHandler extends MessageHandler<PlayerDesignMessage> {
/**
* Creates the PlayerDesignVerificationHandler.
*
* @param world The {@link World} the {@link PlayerDesignMessage} occurred in.
*/
public PlayerDesignVerificationHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, PlayerDesignMessage message) { public void handle(MessageHandlerContext ctx, Player player, PlayerDesignMessage message) {
if (!valid(message.getAppearance())) { if (!valid(message.getAppearance())) {
@@ -27,7 +37,7 @@ public final class PlayerDesignVerificationHandler extends MessageHandler<Player
* @param appearance The appearance combination. * @param appearance The appearance combination.
* @return {@code true} if so, {@code false} if not. * @return {@code true} if so, {@code false} if not.
*/ */
private static boolean valid(Appearance appearance) { private boolean valid(Appearance appearance) {
int[] colors = appearance.getColors(); int[] colors = appearance.getColors();
int[] maxColors = new int[] { 11, 15, 15, 5, 7 }; int[] maxColors = new int[] { 11, 15, 15, 5, 7 };
@@ -53,7 +63,7 @@ public final class PlayerDesignVerificationHandler extends MessageHandler<Player
* @param appearance The appearance combination. * @param appearance The appearance combination.
* @return {@code true} if so, {@code false} if not. * @return {@code true} if so, {@code false} if not.
*/ */
private static boolean validFemaleStyle(Appearance appearance) { private boolean validFemaleStyle(Appearance appearance) {
int[] styles = appearance.getStyle(); int[] styles = appearance.getStyle();
int[] minStyles = new int[] { 45, 255, 56, 61, 67, 70, 79 }; int[] minStyles = new int[] { 45, 255, 56, 61, 67, 70, 79 };
int[] maxStyles = new int[] { 54, 255, 60, 65, 68, 77, 80 }; int[] maxStyles = new int[] { 54, 255, 60, 65, 68, 77, 80 };
@@ -73,7 +83,7 @@ public final class PlayerDesignVerificationHandler extends MessageHandler<Player
* @param appearance The appearance combination. * @param appearance The appearance combination.
* @return {@code true} if so, {@code false} if not. * @return {@code true} if so, {@code false} if not.
*/ */
private static boolean validMaleStyle(Appearance appearance) { private boolean validMaleStyle(Appearance appearance) {
int[] styles = appearance.getStyle(); int[] styles = appearance.getStyle();
int[] minStyles = new int[] { 0, 10, 18, 26, 33, 36, 42 }; int[] minStyles = new int[] { 0, 10, 18, 26, 33, 36, 42 };
int[] maxStyles = new int[] { 8, 17, 25, 31, 34, 40, 43 }; int[] maxStyles = new int[] { 8, 17, 25, 31, 34, 40, 43 };
@@ -4,6 +4,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ItemActionMessage; import org.apollo.game.message.impl.ItemActionMessage;
import org.apollo.game.model.Item; import org.apollo.game.model.Item;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inv.Inventory; import org.apollo.game.model.inv.Inventory;
import org.apollo.game.model.inv.SynchronizationInventoryListener; import org.apollo.game.model.inv.SynchronizationInventoryListener;
@@ -16,6 +17,15 @@ import org.apollo.game.model.inv.SynchronizationInventoryListener;
*/ */
public final class RemoveEquippedItemHandler extends MessageHandler<ItemActionMessage> { public final class RemoveEquippedItemHandler extends MessageHandler<ItemActionMessage> {
/**
* Creates the RemoveEquippedItemHandler.
*
* @param world The {@link World} the {@link ItemActionMessage} occurred in.
*/
public RemoveEquippedItemHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemActionMessage message) { public void handle(MessageHandlerContext ctx, Player player, ItemActionMessage message) {
if (message.getOption() == 1 && message.getInterfaceId() == SynchronizationInventoryListener.EQUIPMENT_ID) { if (message.getOption() == 1 && message.getInterfaceId() == SynchronizationInventoryListener.EQUIPMENT_ID) {
@@ -3,6 +3,7 @@ package org.apollo.game.message.handler.impl;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.SwitchItemMessage; import org.apollo.game.message.impl.SwitchItemMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.inter.bank.BankConstants; import org.apollo.game.model.inter.bank.BankConstants;
import org.apollo.game.model.inv.Inventory; import org.apollo.game.model.inv.Inventory;
@@ -16,6 +17,15 @@ import org.apollo.game.model.inv.SynchronizationInventoryListener;
*/ */
public final class SwitchItemMessageHandler extends MessageHandler<SwitchItemMessage> { public final class SwitchItemMessageHandler extends MessageHandler<SwitchItemMessage> {
/**
* Creates the SwitchItemMessageHandler.
*
* @param world The {@link World} the {@link SwitchItemMessage} occurred in.
*/
public SwitchItemMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, SwitchItemMessage message) { public void handle(MessageHandlerContext ctx, Player player, SwitchItemMessage message) {
Inventory inventory; Inventory inventory;
@@ -37,9 +47,10 @@ public final class SwitchItemMessageHandler extends MessageHandler<SwitchItemMes
return; // not a known inventory, ignore return; // not a known inventory, ignore
} }
if (message.getOldSlot() >= 0 && message.getNewSlot() >= 0 && message.getOldSlot() < inventory.capacity() && message.getNewSlot() < inventory.capacity()) { int old = message.getOldSlot(), next = message.getNewSlot();
if (old >= 0 && next >= 0 && old < inventory.capacity() && next < inventory.capacity()) {
// events must be fired for it to work if a sidebar inventory overlay is used // events must be fired for it to work if a sidebar inventory overlay is used
inventory.swap(insertPermitted && message.isInserting(), message.getOldSlot(), message.getNewSlot()); inventory.swap(insertPermitted && message.isInserting(), old, next);
} }
} }
@@ -4,6 +4,7 @@ import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext; import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.WalkMessage; import org.apollo.game.message.impl.WalkMessage;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.entity.WalkingQueue; import org.apollo.game.model.entity.WalkingQueue;
@@ -14,6 +15,15 @@ import org.apollo.game.model.entity.WalkingQueue;
*/ */
public final class WalkMessageHandler extends MessageHandler<WalkMessage> { public final class WalkMessageHandler extends MessageHandler<WalkMessage> {
/**
* Creates the WalkMessageHandler.
*
* @param world The {@link World} the {@link WalkMessage} occurred in.
*/
public WalkMessageHandler(World world) {
super(world);
}
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, WalkMessage message) { public void handle(MessageHandlerContext ctx, Player player, WalkMessage message) {
WalkingQueue queue = player.getWalkingQueue(); WalkingQueue queue = player.getWalkingQueue();
@@ -2,6 +2,7 @@ package org.apollo.game.message.impl;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt;
import org.apollo.game.message.Message; import org.apollo.game.message.Message;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
@@ -62,7 +63,7 @@ public final class HintIconMessage extends Message {
* @return The HintIconMessage. * @return The HintIconMessage.
*/ */
public static HintIconMessage forNpc(int index) { public static HintIconMessage forNpc(int index) {
return new HintIconMessage(Type.NPC, Optional.of(index), Optional.empty()); return new HintIconMessage(Type.NPC, OptionalInt.of(index), Optional.empty());
} }
/** /**
@@ -72,7 +73,7 @@ public final class HintIconMessage extends Message {
* @return The HintIconMessage. * @return The HintIconMessage.
*/ */
public static HintIconMessage forPlayer(int index) { public static HintIconMessage forPlayer(int index) {
return new HintIconMessage(Type.PLAYER, Optional.of(index), Optional.empty()); return new HintIconMessage(Type.PLAYER, OptionalInt.of(index), Optional.empty());
} }
/** /**
@@ -96,7 +97,7 @@ public final class HintIconMessage extends Message {
/** /**
* The index of the Mob, if applicable. * The index of the Mob, if applicable.
*/ */
private final Optional<Integer> index; private final OptionalInt index;
/** /**
* The Position of the tile, if applicable. * The Position of the tile, if applicable.
@@ -115,7 +116,7 @@ public final class HintIconMessage extends Message {
* @param index The index of the Mob, if applicable. * @param index The index of the Mob, if applicable.
* @param position The Position of the tile, if applicable. * @param position The Position of the tile, if applicable.
*/ */
private HintIconMessage(Type type, Optional<Integer> index, Optional<Position> position) { private HintIconMessage(Type type, OptionalInt index, Optional<Position> position) {
this.type = type; this.type = type;
this.index = index; this.index = index;
this.position = position; this.position = position;
@@ -128,7 +129,7 @@ public final class HintIconMessage extends Message {
* @throws NoSuchElementException If no index is available for this HintIcon. * @throws NoSuchElementException If no index is available for this HintIcon.
*/ */
public int getIndex() { public int getIndex() {
return index.get(); return index.getAsInt();
} }
/** /**
+6 -19
View File
@@ -23,9 +23,9 @@ import org.apollo.game.model.def.NpcDefinition;
import org.apollo.game.model.def.ObjectDefinition; import org.apollo.game.model.def.ObjectDefinition;
import org.apollo.game.model.entity.Entity; import org.apollo.game.model.entity.Entity;
import org.apollo.game.model.entity.Entity.EntityType; import org.apollo.game.model.entity.Entity.EntityType;
import org.apollo.game.model.entity.obj.GameObject;
import org.apollo.game.model.entity.Npc; import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.entity.obj.GameObject;
import org.apollo.game.model.event.Event; import org.apollo.game.model.event.Event;
import org.apollo.game.model.event.EventListener; import org.apollo.game.model.event.EventListener;
import org.apollo.game.model.event.EventListenerChainSet; import org.apollo.game.model.event.EventListenerChainSet;
@@ -77,24 +77,10 @@ public final class World {
*/ */
private static final Logger logger = Logger.getLogger(World.class.getName()); private static final Logger logger = Logger.getLogger(World.class.getName());
/**
* The world.
*/
private static final World world = new World();
/**
* Gets the world.
*
* @return The world.
*/
public static World getWorld() {
return world;
}
/** /**
* The command dispatcher. * The command dispatcher.
*/ */
private final CommandDispatcher commandDispatcher = new CommandDispatcher(); private CommandDispatcher commandDispatcher = new CommandDispatcher();
/** /**
* The EventListenerChainSet for this World. * The EventListenerChainSet for this World.
@@ -144,7 +130,7 @@ public final class World {
/** /**
* Creates the world. * Creates the world.
*/ */
private World() { public World() {
} }
@@ -247,14 +233,15 @@ public final class World {
logger.fine("Loaded " + objectDefs.length + " object definitions."); logger.fine("Loaded " + objectDefs.length + " object definitions.");
GameObjectDecoder staticDecoder = new GameObjectDecoder(fs, regions); GameObjectDecoder staticDecoder = new GameObjectDecoder(fs, regions);
GameObject[] objects = staticDecoder.decode(); GameObject[] objects = staticDecoder.decode(this);
placeEntities(objects); placeEntities(objects);
logger.fine("Loaded " + objects.length + " static objects."); logger.fine("Loaded " + objects.length + " static objects.");
npcMovement = new NpcMovementTask(); // Must be exactly here because of ordering issues. npcMovement = new NpcMovementTask(regions); // Must be exactly here because of ordering issues.
scheduler.schedule(npcMovement); scheduler.schedule(npcMovement);
manager.start(); manager.start();
commandDispatcher.init(manager.getAuthors());
pluginManager = manager; pluginManager = manager;
} }
+33 -16
View File
@@ -1,6 +1,7 @@
package org.apollo.game.model.entity; package org.apollo.game.model.entity;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.area.EntityUpdateType; import org.apollo.game.model.area.EntityUpdateType;
import org.apollo.game.model.area.Region; import org.apollo.game.model.area.Region;
import org.apollo.game.model.area.update.UpdateOperation; import org.apollo.game.model.area.update.UpdateOperation;
@@ -17,21 +18,16 @@ public abstract class Entity {
*/ */
public enum EntityType { public enum EntityType {
/**
* An Item that is positioned on the ground.
*/
GROUND_ITEM,
/**
* A GameObject that is loaded statically (i.e. from the game resources) at start-up.
*/
STATIC_OBJECT,
/** /**
* A GameObject that is loaded dynamically, usually for specific Players. * A GameObject that is loaded dynamically, usually for specific Players.
*/ */
DYNAMIC_OBJECT, DYNAMIC_OBJECT,
/**
* An Item that is positioned on the ground.
*/
GROUND_ITEM,
/** /**
* An Npc. * An Npc.
*/ */
@@ -45,7 +41,12 @@ public abstract class Entity {
/** /**
* A projectile (e.g. an arrow). * A projectile (e.g. an arrow).
*/ */
PROJECTILE; PROJECTILE,
/**
* A GameObject that is loaded statically (i.e. from the game resources) at start-up.
*/
STATIC_OBJECT;
/** /**
* Returns whether or not this EntityType is for a Mob. * Returns whether or not this EntityType is for a Mob.
@@ -59,16 +60,23 @@ public abstract class Entity {
} }
/** /**
* The position of this entity. * The Position of this Entity.
*/ */
protected Position position; protected Position position;
/** /**
* Creates a new entity with the specified position. * The World containing this Entity.
*
* @param position The position.
*/ */
public Entity(Position position) { protected final World world;
/**
* Creates the Entity.
*
* @param world The {@link World} containing the Entity.
* @param position The {@link Position} of the Entity.
*/
public Entity(World world, Position position) {
this.world = world;
this.position = position; this.position = position;
} }
@@ -91,6 +99,15 @@ public abstract class Entity {
return position; return position;
} }
/**
* Gets the {@link World} this Entity is in.
*
* @return The World.
*/
public World getWorld() {
return world;
}
@Override @Override
public abstract int hashCode(); public abstract int hashCode();
@@ -2,8 +2,9 @@ package org.apollo.game.model.entity;
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.area.Region; import org.apollo.game.model.World;
import org.apollo.game.model.area.EntityUpdateType; import org.apollo.game.model.area.EntityUpdateType;
import org.apollo.game.model.area.Region;
import org.apollo.game.model.area.update.ItemUpdateOperation; import org.apollo.game.model.area.update.ItemUpdateOperation;
import org.apollo.game.model.area.update.UpdateOperation; import org.apollo.game.model.area.update.UpdateOperation;
@@ -17,24 +18,26 @@ public final class GroundItem extends Entity {
/** /**
* Creates a new GroundItem. * Creates a new GroundItem.
* *
* @param world The {@link World} containing the GroundItem.
* @param position The {@link Position} of the Item. * @param position The {@link Position} of the Item.
* @param item The Item displayed on the ground. * @param item The Item displayed on the ground.
* @return The GroundItem. * @return The GroundItem.
*/ */
public static GroundItem create(Position position, Item item) { public static GroundItem create(World world, Position position, Item item) {
return new GroundItem(position, item, -1); return new GroundItem(world, position, item, -1);
} }
/** /**
* Creates a new dropped GroundItem. * Creates a new dropped GroundItem.
* *
* @param world The {@link World} containing the GroundItem.
* @param position The {@link Position} of the Item. * @param position The {@link Position} of the Item.
* @param item The Item displayed on the ground. * @param item The Item displayed on the ground.
* @param owner The the {@link Player} who dropped this GroundItem. * @param owner The the {@link Player} who dropped this GroundItem.
* @return The GroundItem. * @return The GroundItem.
*/ */
public static GroundItem dropped(Position position, Item item, Player owner) { public static GroundItem dropped(World world, Position position, Item item, Player owner) {
return new GroundItem(position, item, owner.getIndex()); return new GroundItem(world, position, item, owner.getIndex());
} }
/** /**
@@ -50,12 +53,13 @@ public final class GroundItem extends Entity {
/** /**
* Creates the GroundItem. * Creates the GroundItem.
* *
* @param position The {@link Position} of the Item. * @param world The {@link World} containing the GroundItem.
* @param position The {@link Position} of the GroundItem.
* @param item The Item displayed on the ground. * @param item The Item displayed on the ground.
* @param index The index of the {@link Player} who dropped this GroundItem. * @param index The index of the {@link Player} who dropped this GroundItem.
*/ */
private GroundItem(Position position, Item item, int index) { private GroundItem(World world, Position position, Item item, int index) {
super(position); super(world, position);
this.item = item; this.item = item;
this.index = index; this.index = index;
} }
+15 -13
View File
@@ -116,22 +116,24 @@ public abstract class Mob extends Entity {
private transient boolean teleporting = false; private transient boolean teleporting = false;
/** /**
* Creates the mob with the specified initial {@link Position}. * Creates the Mob.
* *
* @param position The position. * @param world The {@link World} containing the Mob
* @param position The {@link Position} of the Mob.
*/ */
public Mob(Position position) { public Mob(World world, Position position) {
this(position, null); this(world, position, null);
} }
/** /**
* Creates the mob. * Creates the Mob.
* *
* @param position The initial position. * @param world The {@link World} containing the Mob
* @param definition The {@link NpcDefinition}. * @param position The {@link Position} of the Mob.
* @param definition The {@link NpcDefinition} of the Mob.
*/ */
public Mob(Position position, NpcDefinition definition) { public Mob(World world, Position position, NpcDefinition definition) {
super(position); super(world, position);
this.definition = Optional.ofNullable(definition); this.definition = Optional.ofNullable(definition);
init(); init();
@@ -435,9 +437,9 @@ public abstract class Mob extends Entity {
* @param position The Position. * @param position The Position.
*/ */
public final void setPosition(Position position) { public final void setPosition(Position position) {
if (World.getWorld().submit(new MobPositionUpdateEvent(this, position))) { if (world.submit(new MobPositionUpdateEvent(this, position))) {
Position old = this.position; Position old = this.position;
RegionRepository repository = World.getWorld().getRegionRepository(); RegionRepository repository = world.getRegionRepository();
Region current = repository.fromPosition(old), next = repository.fromPosition(position); Region current = repository.fromPosition(old), next = repository.fromPosition(position);
current.removeEntity(this); current.removeEntity(this);
@@ -482,7 +484,7 @@ public abstract class Mob extends Entity {
} }
this.action = action; this.action = action;
return World.getWorld().schedule(action); return world.schedule(action);
} }
/** /**
@@ -541,7 +543,7 @@ public abstract class Mob extends Entity {
* Initialises this mob. * Initialises this mob.
*/ */
private void init() { private void init() {
World.getWorld().schedule(new SkillNormalizationTask(this)); world.schedule(new SkillNormalizationTask(this));
} }
} }
+9 -6
View File
@@ -3,6 +3,7 @@ package org.apollo.game.model.entity;
import java.util.Optional; import java.util.Optional;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.def.NpcDefinition; import org.apollo.game.model.def.NpcDefinition;
import org.apollo.game.sync.block.SynchronizationBlock; import org.apollo.game.sync.block.SynchronizationBlock;
@@ -22,24 +23,26 @@ public final class Npc extends Mob {
private Optional<Position[]> boundaries; private Optional<Position[]> boundaries;
/** /**
* Creates a new Npc with the specified id and {@link Position}. * Creates the Npc.
* *
* @param world The {@link World} containing the Npc.
* @param id The id. * @param id The id.
* @param position The position. * @param position The position.
*/ */
public Npc(int id, Position position) { public Npc(World world, int id, Position position) {
this(position, NpcDefinition.lookup(id), null); this(world, position, NpcDefinition.lookup(id), null);
} }
/** /**
* Creates a new Npc with the specified {@link NpcDefinition} and {@link Position}. * Creates the Npc.
* *
* @param world The {@link World} containing the Npc.
* @param position The Position. * @param position The Position.
* @param definition The NpcDefinition. * @param definition The NpcDefinition.
* @param boundaries The boundary Positions. * @param boundaries The boundary Positions.
*/ */
public Npc(Position position, NpcDefinition definition, Position[] boundaries) { public Npc(World world, Position position, NpcDefinition definition, Position[] boundaries) {
super(position, definition); super(world, position, definition);
this.boundaries = Optional.ofNullable(boundaries); this.boundaries = Optional.ofNullable(boundaries);
} }
+6 -6
View File
@@ -195,13 +195,14 @@ public final class Player extends Mob {
private transient int worldId = 1; private transient int worldId = 1;
/** /**
* Creates the {@link Player}. * Creates the Player.
* *
* @param world The {@link World} containing the Player.
* @param credentials The player's credentials. * @param credentials The player's credentials.
* @param position The initial position. * @param position The initial position.
*/ */
public Player(PlayerCredentials credentials, Position position) { public Player(World world, PlayerCredentials credentials, Position position) {
super(position); super(world, position);
this.credentials = credentials; this.credentials = credentials;
init(); init();
@@ -597,7 +598,7 @@ public final class Player extends Mob {
* Logs the player out, if possible. * Logs the player out, if possible.
*/ */
public void logout() { public void logout() {
if (World.getWorld().submit(new LogoutEvent(this))) { if (world.submit(new LogoutEvent(this))) {
send(new LogoutMessage()); send(new LogoutMessage());
} }
} }
@@ -698,7 +699,7 @@ public final class Player extends Mob {
bank.forceRefresh(); bank.forceRefresh();
skillSet.forceRefresh(); skillSet.forceRefresh();
World.getWorld().submit(new LoginEvent(this)); world.submit(new LoginEvent(this));
} }
/** /**
@@ -747,7 +748,6 @@ public final class Player extends Mob {
send(new IgnoreListMessage(ignores)); send(new IgnoreListMessage(ignores));
} }
World world = World.getWorld();
for (String username : friends) { for (String username : friends) {
int worldId = world.isPlayerOnline(username) ? world.getPlayer(username).worldId : 0; int worldId = world.isPlayerOnline(username) ? world.getPlayer(username).worldId : 0;
send(new SendFriendMessage(username, worldId)); send(new SendFriendMessage(username, worldId));
@@ -5,6 +5,7 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
@@ -31,7 +32,7 @@ public final class DynamicGameObject extends GameObject {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj instanceof WeakPlayerReference) { if (obj instanceof WeakPlayerReference) {
WeakPlayerReference other = (WeakPlayerReference) obj; WeakPlayerReference other = (WeakPlayerReference) obj; // TODO need to have a reference queue
Player player = get(); Player player = get();
return player != null && player.equals(other.get()); return player != null && player.equals(other.get());
@@ -51,27 +52,29 @@ public final class DynamicGameObject extends GameObject {
/** /**
* Creates a DynamicGameObject that is visible only to {@link Player}s specified later. * Creates a DynamicGameObject that is visible only to {@link Player}s specified later.
* *
* @param world The {@link World} containing the DynamicGameObject.
* @param id The id of the DynamicGameObject * @param id The id of the DynamicGameObject
* @param position The {@link Position} of the DynamicGameObject. * @param position The {@link Position} of the DynamicGameObject.
* @param type The type of the DynamicGameObject. * @param type The type of the DynamicGameObject.
* @param orientation The orientation of the DynamicGameObject. * @param orientation The orientation of the DynamicGameObject.
* @return The DynamicGameObject. * @return The DynamicGameObject.
*/ */
public static DynamicGameObject createLocal(int id, Position position, int type, int orientation) { public static DynamicGameObject createLocal(World world, int id, Position position, int type, int orientation) {
return new DynamicGameObject(id, position, type, orientation, false); return new DynamicGameObject(world, id, position, type, orientation, false);
} }
/** /**
* Creates a DynamicGameObject that is always visible. * Creates a DynamicGameObject that is always visible.
* *
* @param world The {@link World} containing the DynamicGameObject.
* @param id The id of the DynamicGameObject * @param id The id of the DynamicGameObject
* @param position The {@link Position} of the DynamicGameObject. * @param position The {@link Position} of the DynamicGameObject.
* @param type The type of the DynamicGameObject. * @param type The type of the DynamicGameObject.
* @param orientation The orientation of the DynamicGameObject. * @param orientation The orientation of the DynamicGameObject.
* @return The DynamicGameObject. * @return The DynamicGameObject.
*/ */
public static DynamicGameObject createPublic(int id, Position position, int type, int orientation) { public static DynamicGameObject createPublic(World world, int id, Position position, int type, int orientation) {
return new DynamicGameObject(id, position, type, orientation, true); return new DynamicGameObject(world, id, position, type, orientation, true);
} }
/** /**
@@ -87,14 +90,15 @@ public final class DynamicGameObject extends GameObject {
/** /**
* Creates the DynamicGameObject. * Creates the DynamicGameObject.
* *
* @param world The {@link World} containing the DynamicGameObject.
* @param id The id of the DynamicGameObject * @param id The id of the DynamicGameObject
* @param position The {@link Position} of the DynamicGameObject. * @param position The {@link Position} of the DynamicGameObject.
* @param type The type of the DynamicGameObject. * @param type The type of the DynamicGameObject.
* @param orientation The orientation of the DynamicGameObject. * @param orientation The orientation of the DynamicGameObject.
* @param alwaysVisible The flag indicates whether or not this DynamicGameObject is visible to every player. * @param alwaysVisible The flag indicates whether or not this DynamicGameObject is visible to every player.
*/ */
private DynamicGameObject(int id, Position position, int type, int orientation, boolean alwaysVisible) { private DynamicGameObject(World world, int id, Position position, int type, int orientation, boolean alwaysVisible) {
super(id, position, type, orientation); super(world, id, position, type, orientation);
this.alwaysVisible = alwaysVisible; this.alwaysVisible = alwaysVisible;
} }
@@ -126,7 +130,7 @@ public final class DynamicGameObject extends GameObject {
} }
@Override @Override
public boolean viewableBy(Player player) { public boolean viewableBy(Player player, World world) {
return alwaysVisible || players.contains(new WeakPlayerReference(player)); return alwaysVisible || players.contains(new WeakPlayerReference(player));
} }
@@ -1,6 +1,7 @@
package org.apollo.game.model.entity.obj; package org.apollo.game.model.entity.obj;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.area.EntityUpdateType; import org.apollo.game.model.area.EntityUpdateType;
import org.apollo.game.model.area.Region; import org.apollo.game.model.area.Region;
import org.apollo.game.model.area.update.ObjectUpdateOperation; import org.apollo.game.model.area.update.ObjectUpdateOperation;
@@ -26,13 +27,14 @@ public abstract class GameObject extends Entity {
/** /**
* Creates the GameObject. * Creates the GameObject.
* *
* @param world The {@link World} containing the GameObject.
* @param id The id of the GameObject * @param id The id of the GameObject
* @param position The {@link Position} of the GameObject. * @param position The {@link Position} of the GameObject.
* @param type The type of the GameObject. * @param type The type of the GameObject.
* @param orientation The orientation of the GameObject. * @param orientation The orientation of the GameObject.
*/ */
public GameObject(int id, Position position, int type, int orientation) { public GameObject(World world, int id, Position position, int type, int orientation) {
super(position); super(world, position);
this.packed = id << 8 | (type & 0x3F) << 2 | orientation & 0x3; this.packed = id << 8 | (type & 0x3F) << 2 | orientation & 0x3;
} }
@@ -102,8 +104,9 @@ public abstract class GameObject extends Entity {
* Returns whether or not this GameObject can be seen by the specified {@link Player}. * Returns whether or not this GameObject can be seen by the specified {@link Player}.
* *
* @param player The Player. * @param player The Player.
* @param world The {@link World} containing the GameObject.
* @return {@code true} if the Player can see this GameObject, {@code false} if not. * @return {@code true} if the Player can see this GameObject, {@code false} if not.
*/ */
public abstract boolean viewableBy(Player player); public abstract boolean viewableBy(Player player, World world);
} }
@@ -16,13 +16,14 @@ public final class StaticGameObject extends GameObject {
/** /**
* Creates the StaticGameObject. * Creates the StaticGameObject.
* *
* @param world The {@link World} containing the StaticGameObject.
* @param id The id of the StaticGameObject * @param id The id of the StaticGameObject
* @param position The {@link Position} of the StaticGameObject. * @param position The {@link Position} of the StaticGameObject.
* @param type The type code of the StaticGameObject. * @param type The type code of the StaticGameObject.
* @param orientation The orientation of the StaticGameObject. * @param orientation The orientation of the StaticGameObject.
*/ */
public StaticGameObject(int id, Position position, int type, int orientation) { public StaticGameObject(World world, int id, Position position, int type, int orientation) {
super(id, position, type, orientation); super(world, id, position, type, orientation);
} }
@Override @Override
@@ -31,8 +32,8 @@ public final class StaticGameObject extends GameObject {
} }
@Override @Override
public boolean viewableBy(Player player) { public boolean viewableBy(Player player, World world) {
RegionRepository repository = World.getWorld().getRegionRepository(); RegionRepository repository = world.getRegionRepository();
RegionCoordinates coordinates = position.getRegionCoordinates(); RegionCoordinates coordinates = position.getRegionCoordinates();
return repository.get(coordinates).contains(this); return repository.get(coordinates).contains(this);
@@ -10,6 +10,7 @@ import java.util.Queue;
import java.util.Set; import java.util.Set;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.area.RegionRepository;
/** /**
* A {@link PathfindingAlgorithm} that utilises the A* algorithm to find a solution. * A {@link PathfindingAlgorithm} that utilises the A* algorithm to find a solution.
@@ -33,9 +34,11 @@ public final class AStarPathfindingAlgorithm extends PathfindingAlgorithm {
/** /**
* Creates the A* pathfinding algorithm with the specified heuristic. * Creates the A* pathfinding algorithm with the specified heuristic.
* *
* @param repository The {@link RegionRepository}.
* @param heuristic The heuristic. * @param heuristic The heuristic.
*/ */
public AStarPathfindingAlgorithm(Heuristic heuristic) { public AStarPathfindingAlgorithm(RegionRepository repository, Heuristic heuristic) {
super(repository);
this.heuristic = heuristic; this.heuristic = heuristic;
} }
@@ -5,7 +5,6 @@ import java.util.Optional;
import org.apollo.game.model.Direction; import org.apollo.game.model.Direction;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.area.Region; import org.apollo.game.model.area.Region;
import org.apollo.game.model.area.RegionRepository; import org.apollo.game.model.area.RegionRepository;
import org.apollo.game.model.entity.Entity.EntityType; import org.apollo.game.model.entity.Entity.EntityType;
@@ -20,9 +19,18 @@ import com.google.common.base.Preconditions;
abstract class PathfindingAlgorithm { abstract class PathfindingAlgorithm {
/** /**
* The repository of Regions. * The RegionRepository.
*/ */
private static final RegionRepository REPOSITORY = World.getWorld().getRegionRepository(); private final RegionRepository repository;
/**
* Creates the PathfindingAlgorithm.
*
* @param repository The {@link RegionRepository}.
*/
public PathfindingAlgorithm(RegionRepository repository) {
this.repository = repository;
}
/** /**
* Finds a valid path from the origin {@link Position} to the target one. * Finds a valid path from the origin {@link Position} to the target one.
@@ -77,7 +85,7 @@ abstract class PathfindingAlgorithm {
} }
Position next = new Position(x, y, height); Position next = new Position(x, y, height);
Region region = REPOSITORY.get(next.getRegionCoordinates()); Region region = repository.get(next.getRegionCoordinates());
if (region.traversable(next, EntityType.NPC, direction) && (positions.length == 0 || inside(next, positions))) { if (region.traversable(next, EntityType.NPC, direction) && (positions.length == 0 || inside(next, positions))) {
return true; return true;
} }
@@ -6,6 +6,7 @@ import java.util.Optional;
import org.apollo.game.model.Direction; import org.apollo.game.model.Direction;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.area.RegionRepository;
/** /**
* A very simple pathfinding algorithm that simply walks in the direction of the target until it either reaches it or is * A very simple pathfinding algorithm that simply walks in the direction of the target until it either reaches it or is
@@ -15,6 +16,15 @@ import org.apollo.game.model.Position;
*/ */
public final class SimplePathfindingAlgorithm extends PathfindingAlgorithm { public final class SimplePathfindingAlgorithm extends PathfindingAlgorithm {
/**
* Creates the SimplePathfindingAlgorithm.
*
* @param repository The {@link RegionRepository}.
*/
public SimplePathfindingAlgorithm(RegionRepository repository) {
super(repository);
}
/** /**
* The Optional containing the boundary Positions. * The Optional containing the boundary Positions.
*/ */
@@ -12,7 +12,6 @@ import org.apollo.game.message.impl.OpenInterfaceMessage;
import org.apollo.game.message.impl.OpenInterfaceSidebarMessage; import org.apollo.game.message.impl.OpenInterfaceSidebarMessage;
import org.apollo.game.message.impl.OpenOverlayMessage; import org.apollo.game.message.impl.OpenOverlayMessage;
import org.apollo.game.message.impl.OpenSidebarMessage; import org.apollo.game.message.impl.OpenSidebarMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.event.impl.CloseInterfacesEvent; import org.apollo.game.model.event.impl.CloseInterfacesEvent;
import org.apollo.game.model.inter.dialogue.DialogueListener; import org.apollo.game.model.inter.dialogue.DialogueListener;
@@ -87,7 +86,7 @@ public final class InterfaceSet {
*/ */
public void close() { public void close() {
CloseInterfacesEvent event = new CloseInterfacesEvent(player); CloseInterfacesEvent event = new CloseInterfacesEvent(player);
if (World.getWorld().submit(event)) { if (player.getWorld().submit(event)) {
closeAndNotify(); closeAndNotify();
player.send(new CloseInterfaceMessage()); player.send(new CloseInterfaceMessage());
} }
@@ -7,6 +7,7 @@ import java.util.Queue;
import java.util.Random; import java.util.Random;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.area.RegionRepository;
import org.apollo.game.model.entity.Npc; import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.WalkingQueue; import org.apollo.game.model.entity.WalkingQueue;
import org.apollo.game.model.entity.path.SimplePathfindingAlgorithm; import org.apollo.game.model.entity.path.SimplePathfindingAlgorithm;
@@ -39,7 +40,7 @@ public final class NpcMovementTask extends ScheduledTask {
/** /**
* The PathfindingAlgorithm used by this Task. * The PathfindingAlgorithm used by this Task.
*/ */
private final SimplePathfindingAlgorithm algorithm = new SimplePathfindingAlgorithm(); private final SimplePathfindingAlgorithm algorithm;
/** /**
* The Queue of Npcs. * The Queue of Npcs.
@@ -48,9 +49,12 @@ public final class NpcMovementTask extends ScheduledTask {
/** /**
* Creates the NpcMovementTask. * Creates the NpcMovementTask.
*
* @param repository The {@link RegionRepository}.
*/ */
public NpcMovementTask() { public NpcMovementTask(RegionRepository repository) {
super(DELAY, false); super(DELAY, false);
algorithm = new SimplePathfindingAlgorithm(repository);
} }
/** /**
@@ -1,5 +1,9 @@
package org.apollo.game.sync; package org.apollo.game.sync;
import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.Player;
import org.apollo.util.MobRepository;
/** /**
* The {@link ClientSynchronizer} manages the update sequence which keeps clients synchronized with the in-game world. * The {@link ClientSynchronizer} manages the update sequence which keeps clients synchronized with the in-game world.
* There are two implementations distributed with Apollo: {@link SequentialClientSynchronizer} which is optimized for a * There are two implementations distributed with Apollo: {@link SequentialClientSynchronizer} which is optimized for a
@@ -16,7 +20,10 @@ public abstract class ClientSynchronizer {
/** /**
* Synchronizes the state of the clients with the state of the server. * Synchronizes the state of the clients with the state of the server.
*
* @param players The {@link MobRepository} containing the {@link Player}s.
* @param npcs The {@link MobRepository} containing the {@link Npc}s.
*/ */
public abstract void synchronize(); public abstract void synchronize(MobRepository<Player> players, MobRepository<Npc> npcs);
} }
@@ -10,7 +10,6 @@ import java.util.concurrent.ThreadFactory;
import org.apollo.game.GameService; import org.apollo.game.GameService;
import org.apollo.game.message.impl.RegionUpdateMessage; import org.apollo.game.message.impl.RegionUpdateMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.area.RegionCoordinates; import org.apollo.game.model.area.RegionCoordinates;
import org.apollo.game.model.entity.Npc; import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -58,9 +57,7 @@ public final class ParallelClientSynchronizer extends ClientSynchronizer {
} }
@Override @Override
public void synchronize() { public void synchronize(MobRepository<Player> players, MobRepository<Npc> npcs) {
MobRepository<Player> players = World.getWorld().getPlayerRepository();
MobRepository<Npc> npcs = World.getWorld().getNpcRepository();
int playerCount = players.size(); int playerCount = players.size();
int npcCount = npcs.size(); int npcCount = npcs.size();
@@ -6,7 +6,6 @@ import java.util.Map;
import org.apollo.game.GameService; import org.apollo.game.GameService;
import org.apollo.game.message.impl.RegionUpdateMessage; import org.apollo.game.message.impl.RegionUpdateMessage;
import org.apollo.game.model.World;
import org.apollo.game.model.area.RegionCoordinates; import org.apollo.game.model.area.RegionCoordinates;
import org.apollo.game.model.entity.Npc; import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -31,10 +30,7 @@ import org.apollo.util.MobRepository;
public final class SequentialClientSynchronizer extends ClientSynchronizer { public final class SequentialClientSynchronizer extends ClientSynchronizer {
@Override @Override
public void synchronize() { public void synchronize(MobRepository<Player> players, MobRepository<Npc> npcs) {
MobRepository<Player> players = World.getWorld().getPlayerRepository();
MobRepository<Npc> npcs = World.getWorld().getNpcRepository();
Map<RegionCoordinates, List<RegionUpdateMessage>> updates = new HashMap<>(); Map<RegionCoordinates, List<RegionUpdateMessage>> updates = new HashMap<>();
Map<RegionCoordinates, List<RegionUpdateMessage>> snapshots = new HashMap<>(); Map<RegionCoordinates, List<RegionUpdateMessage>> snapshots = new HashMap<>();
@@ -6,7 +6,6 @@ import java.util.List;
import org.apollo.game.message.impl.NpcSynchronizationMessage; import org.apollo.game.message.impl.NpcSynchronizationMessage;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Npc; import org.apollo.game.model.entity.Npc;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.sync.seg.AddNpcSegment; import org.apollo.game.sync.seg.AddNpcSegment;
@@ -50,7 +49,8 @@ public final class NpcSynchronizationTask extends SynchronizationTask {
for (Iterator<Npc> it = localNpcs.iterator(); it.hasNext();) { for (Iterator<Npc> it = localNpcs.iterator(); it.hasNext();) {
Npc npc = it.next(); Npc npc = it.next();
if (!npc.isActive() || npc.isTeleporting() || npc.getPosition().getLongestDelta(playerPosition) > player.getViewingDistance()) { if (!npc.isActive() || npc.isTeleporting()
|| npc.getPosition().getLongestDelta(playerPosition) > player.getViewingDistance()) {
it.remove(); it.remove();
segments.add(new RemoveMobSegment()); segments.add(new RemoveMobSegment());
} else { } else {
@@ -60,7 +60,7 @@ public final class NpcSynchronizationTask extends SynchronizationTask {
int added = 0; int added = 0;
for (Npc npc : World.getWorld().getNpcRepository()) { for (Npc npc : player.getWorld().getNpcRepository()) {
if (localNpcs.size() >= 255) { if (localNpcs.size() >= 255) {
player.flagExcessiveNpcs(); player.flagExcessiveNpcs();
break; break;
@@ -69,7 +69,8 @@ public final class NpcSynchronizationTask extends SynchronizationTask {
} }
Position npcPosition = npc.getPosition(); Position npcPosition = npc.getPosition();
if (npcPosition.isWithinDistance(playerPosition, player.getViewingDistance()) && !localNpcs.contains(npc) && npcPosition.getHeight() == playerPosition.getHeight()) { if (npcPosition.isWithinDistance(playerPosition, player.getViewingDistance()) && !localNpcs.contains(npc)
&& npcPosition.getHeight() == playerPosition.getHeight()) {
localNpcs.add(npc); localNpcs.add(npc);
added++; added++;
npc.turnTo(npc.getFacingPosition()); npc.turnTo(npc.getFacingPosition());
@@ -6,7 +6,6 @@ import java.util.List;
import org.apollo.game.message.impl.PlayerSynchronizationMessage; import org.apollo.game.message.impl.PlayerSynchronizationMessage;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
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;
@@ -80,7 +79,7 @@ public final class PlayerSynchronizationTask extends SynchronizationTask {
int added = 0; int added = 0;
MobRepository<Player> repository = World.getWorld().getPlayerRepository(); MobRepository<Player> repository = player.getWorld().getPlayerRepository();
for (Iterator<Player> it = repository.iterator(); it.hasNext();) { for (Iterator<Player> it = repository.iterator(); it.hasNext();) {
Player other = it.next(); Player other = it.next();
if (localPlayers.size() >= 255) { if (localPlayers.size() >= 255) {
@@ -12,7 +12,6 @@ import org.apollo.game.message.impl.GroupedRegionUpdateMessage;
import org.apollo.game.message.impl.RegionChangeMessage; import org.apollo.game.message.impl.RegionChangeMessage;
import org.apollo.game.message.impl.RegionUpdateMessage; import org.apollo.game.message.impl.RegionUpdateMessage;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.area.Region; import org.apollo.game.model.area.Region;
import org.apollo.game.model.area.RegionCoordinates; import org.apollo.game.model.area.RegionCoordinates;
import org.apollo.game.model.area.RegionRepository; import org.apollo.game.model.area.RegionRepository;
@@ -169,7 +168,7 @@ public final class PrePlayerSynchronizationTask extends SynchronizationTask {
RegionCoordinates base = position.getRegionCoordinates(); RegionCoordinates base = position.getRegionCoordinates();
int baseX = base.getX(), baseY = base.getY(); int baseX = base.getX(), baseY = base.getY();
RegionRepository repository = World.getWorld().getRegionRepository(); RegionRepository repository = player.getWorld().getRegionRepository();
List<GroupedRegionUpdateMessage> messages = new ArrayList<>(); List<GroupedRegionUpdateMessage> messages = new ArrayList<>();
for (int x = baseX - REGION_COUNT; x <= baseX + REGION_COUNT; x++) { for (int x = baseX - REGION_COUNT; x <= baseX + REGION_COUNT; x++) {
@@ -11,6 +11,7 @@ import org.apollo.game.message.Message;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerChain; import org.apollo.game.message.handler.MessageHandlerChain;
import org.apollo.game.message.handler.MessageHandlerChainGroup; import org.apollo.game.message.handler.MessageHandlerChainGroup;
import org.apollo.game.model.World;
import org.apollo.util.xml.XmlNode; import org.apollo.util.xml.XmlNode;
import org.apollo.util.xml.XmlParser; import org.apollo.util.xml.XmlParser;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@@ -45,15 +46,13 @@ public final class MessageHandlerChainParser {
/** /**
* Parses the XML and produces a group of {@link MessageHandlerChain}s. * Parses the XML and produces a group of {@link MessageHandlerChain}s.
* *
* @param world The {@link World} this MessageHandlerChainGroup is for.
* @return A {@link MessageHandlerChainGroup}.
* @throws IOException If an I/O error occurs. * @throws IOException If an I/O error occurs.
* @throws SAXException If a SAX error occurs. * @throws SAXException If a SAX error occurs.
* @throws ClassNotFoundException If a class was not found. * @throws ReflectiveOperationException If a reflection error occurs.
* @throws IllegalAccessException If a class was accessed illegally.
* @throws InstantiationException If a class could not be instantiated.
* @return A {@link MessageHandlerChainGroup}.
*/ */
@SuppressWarnings("unchecked") public MessageHandlerChainGroup parse(World world) throws IOException, SAXException, ReflectiveOperationException {
public MessageHandlerChainGroup parse() throws IOException, SAXException, ClassNotFoundException, InstantiationException, IllegalAccessException {
XmlNode messages = parser.parse(is); XmlNode messages = parser.parse(is);
if (!messages.getName().equals("messages")) { if (!messages.getName().equals("messages")) {
throw new IOException("Root node name is not 'messages'."); throw new IOException("Root node name is not 'messages'.");
@@ -80,6 +79,7 @@ public final class MessageHandlerChainParser {
throw new IOException("Type node must have a value."); throw new IOException("Type node must have a value.");
} }
@SuppressWarnings("unchecked")
Class<? extends Message> messageClass = (Class<? extends Message>) Class.forName(messageClassName); Class<? extends Message> messageClass = (Class<? extends Message>) Class.forName(messageClassName);
List<MessageHandler<?>> handlers = new ArrayList<>(); List<MessageHandler<?>> handlers = new ArrayList<>();
@@ -93,13 +93,15 @@ public final class MessageHandlerChainParser {
throw new IOException("Handler node must have a value."); throw new IOException("Handler node must have a value.");
} }
Class<? extends MessageHandler<?>> handlerClass = (Class<? extends MessageHandler<?>>) Class.forName(handlerClassName); @SuppressWarnings("unchecked")
MessageHandler<?> handler = handlerClass.newInstance(); Class<? extends MessageHandler<?>> handlerClass = (Class<? extends MessageHandler<?>>) Class
.forName(handlerClassName);
MessageHandler<?> handler = handlerClass.getConstructor(World.class).newInstance(world);
handlers.add(handler); handlers.add(handler);
} }
MessageHandler<?>[] handlersArray = handlers.toArray(new MessageHandler<?>[handlers.size()]); MessageHandler<?>[] handlersArray = handlers.toArray(new MessageHandler<?>[handlers.size()]);
@SuppressWarnings("rawtypes") @SuppressWarnings({ "rawtypes", "unchecked" })
MessageHandlerChain<?> chain = new MessageHandlerChain(handlersArray); MessageHandlerChain<?> chain = new MessageHandlerChain(handlersArray);
chains.put(messageClass, chain); chains.put(messageClass, chain);
@@ -19,6 +19,7 @@ import java.util.Set;
import org.apollo.game.model.Appearance; import org.apollo.game.model.Appearance;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.entity.Skill; import org.apollo.game.model.entity.Skill;
import org.apollo.game.model.entity.SkillSet; import org.apollo.game.model.entity.SkillSet;
@@ -48,7 +49,16 @@ import com.lambdaworks.crypto.SCryptUtil;
* @author Graham * @author Graham
* @author Major * @author Major
*/ */
public final class BinaryPlayerSerializer implements PlayerSerializer { public final class BinaryPlayerSerializer extends PlayerSerializer {
/**
* Creates the BinaryPlayerSerializer.
*
* @param world The {@link World} to place the {@link Player}s in.
*/
public BinaryPlayerSerializer(World world) {
super(world);
}
/** /**
* The Path to the saved games directory. * The Path to the saved games directory.
@@ -69,7 +79,7 @@ public final class BinaryPlayerSerializer implements PlayerSerializer {
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws IOException { public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws IOException {
Path path = getFile(credentials.getUsername()); Path path = getFile(credentials.getUsername());
if (!Files.exists(path)) { if (!Files.exists(path)) {
Player player = new Player(credentials, TUTORIAL_ISLAND_SPAWN); Player player = new Player(world, credentials, TUTORIAL_ISLAND_SPAWN);
credentials.setPassword(SCryptUtil.scrypt(credentials.getPassword(), 16384, 8, 1)); credentials.setPassword(SCryptUtil.scrypt(credentials.getPassword(), 16384, 8, 1));
return new PlayerLoaderResponse(LoginConstants.STATUS_OK, player); return new PlayerLoaderResponse(LoginConstants.STATUS_OK, player);
@@ -108,7 +118,7 @@ public final class BinaryPlayerSerializer implements PlayerSerializer {
colors[slot] = in.readUnsignedByte(); colors[slot] = in.readUnsignedByte();
} }
Player player = new Player(credentials, new Position(x, y, height)); Player player = new Player(world, credentials, new Position(x, y, height));
player.setPrivilegeLevel(privilege); player.setPrivilegeLevel(privilege);
player.setMembers(members); player.setMembers(members);
player.setChatPrivacy(chatPrivacy); player.setChatPrivacy(chatPrivacy);
@@ -1,5 +1,6 @@
package org.apollo.io.player; package org.apollo.io.player;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.model.entity.setting.MembershipStatus; import org.apollo.game.model.entity.setting.MembershipStatus;
import org.apollo.game.model.entity.setting.PrivilegeLevel; import org.apollo.game.model.entity.setting.PrivilegeLevel;
@@ -12,13 +13,22 @@ import org.apollo.security.PlayerCredentials;
* @author Graham * @author Graham
* @author Major * @author Major
*/ */
public final class DummyPlayerSerializer implements PlayerSerializer { public final class DummyPlayerSerializer extends PlayerSerializer {
/**
* Creates the DummyPlayerSerializer.
*
* @param world The {@link World} to place the {@link Player}s in.
*/
public DummyPlayerSerializer(World world) {
super(world);
}
@Override @Override
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) { public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) {
int status = LoginConstants.STATUS_OK; int status = LoginConstants.STATUS_OK;
Player player = new Player(credentials, TUTORIAL_ISLAND_SPAWN); Player player = new Player(world, credentials, TUTORIAL_ISLAND_SPAWN);
player.setPrivilegeLevel(PrivilegeLevel.ADMINISTRATOR); player.setPrivilegeLevel(PrivilegeLevel.ADMINISTRATOR);
player.setMembers(MembershipStatus.PAID); player.setMembers(MembershipStatus.PAID);
@@ -1,5 +1,6 @@
package org.apollo.io.player; package org.apollo.io.player;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.security.PlayerCredentials; import org.apollo.security.PlayerCredentials;
@@ -8,7 +9,16 @@ import org.apollo.security.PlayerCredentials;
* *
* @author Major * @author Major
*/ */
public final class JdbcPlayerSerializer implements PlayerSerializer { public final class JdbcPlayerSerializer extends PlayerSerializer {
/**
* Creates the JdbcPlayerSerializer.
*
* @param world The {@link World} to place the {@link Player}s in.
*/
public JdbcPlayerSerializer(World world) {
super(world);
}
@Override @Override
public void savePlayer(Player player) throws Exception { public void savePlayer(Player player) throws Exception {
+19 -4
View File
@@ -1,6 +1,7 @@
package org.apollo.io.player; package org.apollo.io.player;
import org.apollo.game.model.Position; import org.apollo.game.model.Position;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.security.PlayerCredentials; import org.apollo.security.PlayerCredentials;
@@ -11,12 +12,26 @@ import org.apollo.security.PlayerCredentials;
* @author Graham * @author Graham
* @author Major * @author Major
*/ */
public interface PlayerSerializer { public abstract class PlayerSerializer {
/** /**
* The spawn point for Players, on Tutorial Island. * The spawn point for Players, on Tutorial Island.
*/ */
Position TUTORIAL_ISLAND_SPAWN = new Position(3093, 3104); protected static final Position TUTORIAL_ISLAND_SPAWN = new Position(3093, 3104);
/**
* The World this PlayerSerializer is for.
*/
protected final World world;
/**
* Creates the PlayerSerializer.
*
* @param world The {@link World} this PlayerSerializer is for.
*/
public PlayerSerializer(World world) {
this.world = world;
}
/** /**
* Loads a {@link Player}. * Loads a {@link Player}.
@@ -25,7 +40,7 @@ public interface PlayerSerializer {
* @return The {@link PlayerLoaderResponse}. * @return The {@link PlayerLoaderResponse}.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
public PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception; public abstract PlayerLoaderResponse loadPlayer(PlayerCredentials credentials) throws Exception;
/** /**
* Saves a {@link Player}. * Saves a {@link Player}.
@@ -33,6 +48,6 @@ public interface PlayerSerializer {
* @param player The Player to save. * @param player The Player to save.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
public void savePlayer(Player player) throws Exception; public abstract void savePlayer(Player player) throws Exception;
} }
+7 -6
View File
@@ -7,6 +7,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import org.apollo.Service; import org.apollo.Service;
import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.io.player.PlayerLoaderResponse;
import org.apollo.io.player.PlayerSerializer; import org.apollo.io.player.PlayerSerializer;
@@ -41,9 +42,11 @@ public final class LoginService extends Service {
/** /**
* Creates the login service. * Creates the login service.
* *
* @param world The {@link World} to log Players in to.
* @throws Exception If an error occurs. * @throws Exception If an error occurs.
*/ */
public LoginService() throws Exception { public LoginService(World world) throws Exception {
super(world);
init(); init();
} }
@@ -52,11 +55,9 @@ public final class LoginService extends Service {
* *
* @throws SAXException If there is an error parsing the XML file. * @throws SAXException If there is an error parsing the XML file.
* @throws IOException If there is an error accessing the file. * @throws IOException If there is an error accessing the file.
* @throws ClassNotFoundException If the player loader/saver implementation could not be found. * @throws ReflectiveOperationException If the {@link PlayerSerializer} implementation could not be created.
* @throws IllegalAccessException If the player loader/saver implementation could not be accessed.
* @throws InstantiationException If the player loader/saver implementation could not be instantiated.
*/ */
private void init() throws SAXException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { private void init() throws SAXException, IOException, ReflectiveOperationException {
XmlParser parser = new XmlParser(); XmlParser parser = new XmlParser();
XmlNode rootNode; XmlNode rootNode;
@@ -74,7 +75,7 @@ public final class LoginService extends Service {
} }
Class<?> clazz = Class.forName(serializer.getValue()); Class<?> clazz = Class.forName(serializer.getValue());
this.serializer = (PlayerSerializer) clazz.newInstance(); this.serializer = (PlayerSerializer) clazz.getConstructor(World.class).newInstance(world);
} }
/** /**
@@ -22,7 +22,7 @@ public final class UpdateEncoder extends MessageToMessageEncoder<OnDemandRespons
int chunkId = response.getChunkId(); int chunkId = response.getChunkId();
ByteBuf chunkData = response.getChunkData(); ByteBuf chunkData = response.getChunkData();
ByteBuf buffer = ctx.alloc().buffer(6 + chunkData.readableBytes()); ByteBuf buffer = ctx.alloc().buffer(2 * Byte.BYTES + 2 * Short.BYTES + 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);
@@ -10,7 +10,7 @@ import org.apollo.net.release.MessageEncoder;
* *
* @author Major * @author Major
*/ */
public final class MobAnimationResetEventEncoder extends MessageEncoder<MobAnimationResetMessage> { public final class MobAnimationResetMessageEncoder extends MessageEncoder<MobAnimationResetMessage> {
@Override @Override
public GamePacket encode(MobAnimationResetMessage message) { public GamePacket encode(MobAnimationResetMessage message) {
+3 -3
View File
@@ -115,11 +115,11 @@ public final class LoginSession extends Session {
IsaacRandomPair randomPair = request.getRandomPair(); IsaacRandomPair randomPair = request.getRandomPair();
Release release = serverContext.getRelease(); Release release = serverContext.getRelease();
channel.pipeline().addFirst("eventEncoder", new GameMessageEncoder(release)); channel.pipeline().addFirst("messageEncoder", new GameMessageEncoder(release));
channel.pipeline().addBefore("eventEncoder", "gameEncoder", new GamePacketEncoder(randomPair.getEncodingRandom())); channel.pipeline().addBefore("messageEncoder", "gameEncoder", new GamePacketEncoder(randomPair.getEncodingRandom()));
channel.pipeline().addBefore("handler", "gameDecoder", new GamePacketDecoder(randomPair.getDecodingRandom(), serverContext.getRelease())); channel.pipeline().addBefore("handler", "gameDecoder", new GamePacketDecoder(randomPair.getDecodingRandom(), serverContext.getRelease()));
channel.pipeline().addAfter("gameDecoder", "eventDecoder", new GameMessageDecoder(release)); channel.pipeline().addAfter("gameDecoder", "messageDecoder", new GameMessageDecoder(release));
channel.pipeline().remove("loginDecoder"); channel.pipeline().remove("loginDecoder");
channel.pipeline().remove("loginEncoder"); channel.pipeline().remove("loginEncoder");
@@ -47,14 +47,11 @@ public final class OnDemandRequestWorker extends RequestWorker<OnDemandRequest,
int length = buffer.remaining(); int length = buffer.remaining();
for (int chunk = 0; buffer.remaining() > 0; chunk++) { for (int chunk = 0; buffer.remaining() > 0; chunk++) {
int chunkSize = buffer.remaining(); int chunkSize = Math.min(buffer.remaining(), CHUNK_LENGTH);
if (chunkSize > CHUNK_LENGTH) {
chunkSize = CHUNK_LENGTH;
}
byte[] tmp = new byte[chunkSize]; byte[] data = new byte[chunkSize];
buffer.get(tmp, 0, tmp.length); buffer.get(data, 0, data.length);
ByteBuf chunkData = Unpooled.wrappedBuffer(tmp, 0, chunkSize); ByteBuf chunkData = Unpooled.wrappedBuffer(data, 0, chunkSize);
OnDemandResponse response = new OnDemandResponse(desc, length, chunk, chunkData); OnDemandResponse response = new OnDemandResponse(desc, length, chunk, chunkData);
channel.writeAndFlush(response); channel.writeAndFlush(response);
+6 -2
View File
@@ -12,6 +12,7 @@ import java.util.logging.Logger;
import org.apollo.Service; import org.apollo.Service;
import org.apollo.fs.IndexedFileSystem; import org.apollo.fs.IndexedFileSystem;
import org.apollo.game.model.World;
/** /**
* A class which services file requests. * A class which services file requests.
@@ -51,9 +52,12 @@ public final class UpdateService extends Service {
private final List<RequestWorker<?, ?>> workers = new ArrayList<>(); private final List<RequestWorker<?, ?>> workers = new ArrayList<>();
/** /**
* Creates the update service. * Creates the UpdateService.
*
* @param world The {@link World} the update service is for.
*/ */
public UpdateService() { public UpdateService(World world) {
super(world);
int totalThreads = REQUEST_TYPES * THREADS_PER_REQUEST_TYPE; int totalThreads = REQUEST_TYPES * THREADS_PER_REQUEST_TYPE;
service = Executors.newFixedThreadPool(totalThreads); service = Executors.newFixedThreadPool(totalThreads);
} }
+3 -36
View File
@@ -2,15 +2,10 @@ package org.apollo.util.plugin;
import org.apollo.ServerContext; import org.apollo.ServerContext;
import org.apollo.game.GameService; import org.apollo.game.GameService;
import org.apollo.game.command.CommandListener;
import org.apollo.game.message.Message; import org.apollo.game.message.Message;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.handler.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerChain; import org.apollo.game.message.handler.MessageHandlerChain;
import org.apollo.game.message.handler.MessageHandlerChainGroup; import org.apollo.game.message.handler.MessageHandlerChainGroup;
import org.apollo.game.model.World;
import org.apollo.game.model.event.EventListener;
import org.apollo.game.model.event.impl.LoginEvent;
import org.apollo.game.model.event.impl.LogoutEvent;
/** /**
* The {@link PluginContext} contains methods a plugin can use to interface with the server, for example, by adding * The {@link PluginContext} contains methods a plugin can use to interface with the server, for example, by adding
@@ -22,42 +17,14 @@ import org.apollo.game.model.event.impl.LogoutEvent;
public final class PluginContext { public final class PluginContext {
/** /**
* Adds a {@link CommandListener}. * The ServerContext.
*
* @param name The name of the listener.
* @param listener The listener.
*/
public static void addCommandListener(String name, CommandListener listener) {
World.getWorld().getCommandDispatcher().register(name, listener);
}
/**
* Adds an {@link EventListener} for a {@link LoginEvent}.
*
* @param listener The listener.
*/
public static void addLoginListener(EventListener<LoginEvent> listener) {
World.getWorld().listenFor(LoginEvent.class, listener);
}
/**
* Adds an {@link EventListener} for a {@link LogoutEvent}.
*
* @param listener The listener.
*/
public static void addLogoutListener(EventListener<LogoutEvent> listener) {
World.getWorld().listenFor(LogoutEvent.class, listener);
}
/**
* The server context.
*/ */
private final ServerContext context; private final ServerContext context;
/** /**
* Creates the plugin context. * Creates the PluginContext.
* *
* @param context The server context. * @param context The {@link ServerContext}.
*/ */
public PluginContext(ServerContext context) { public PluginContext(ServerContext context) {
this.context = context; this.context = context;
+15 -6
View File
@@ -15,6 +15,7 @@ import java.util.TreeSet;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apollo.game.model.World;
import org.apollo.io.PluginMetaDataParser; import org.apollo.io.PluginMetaDataParser;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@@ -36,12 +37,19 @@ public final class PluginManager {
private final PluginContext context; private final PluginContext context;
/** /**
* Creates the plugin manager. * The World this PluginManager is for.
*
* @param context The plugin context.
*/ */
public PluginManager(PluginContext context) { private final World world;
/**
* Creates the PluginManager.
*
* @param world The {@link World} the PluginManager is for.
* @param context The PluginContext.
*/
public PluginManager(World world, PluginContext context) {
this.context = context; this.context = context;
this.world = world;
initAuthors(); initAuthors();
} }
@@ -138,7 +146,7 @@ public final class PluginManager {
Map<String, PluginMetaData> plugins = createMap(findPlugins()); Map<String, PluginMetaData> plugins = createMap(findPlugins());
Set<PluginMetaData> started = new HashSet<>(); Set<PluginMetaData> started = new HashSet<>();
PluginEnvironment env = new RubyPluginEnvironment(); // TODO isolate plugins if possible in the future! PluginEnvironment env = new RubyPluginEnvironment(world); // TODO isolate plugins if possible in the future!
env.setContext(context); env.setContext(context);
for (PluginMetaData plugin : plugins.values()) { for (PluginMetaData plugin : plugins.values()) {
@@ -156,7 +164,8 @@ public final class PluginManager {
* @throws DependencyException If a dependency error occurs. * @throws DependencyException If a dependency error occurs.
* @throws IOException If an I/O error occurs. * @throws IOException If an I/O error occurs.
*/ */
private void start(PluginEnvironment env, PluginMetaData plugin, Map<String, PluginMetaData> plugins, Set<PluginMetaData> started) throws DependencyException, IOException { private void start(PluginEnvironment env, PluginMetaData plugin, Map<String, PluginMetaData> plugins,
Set<PluginMetaData> started) throws DependencyException, IOException {
// TODO check for cyclic dependencies! this way just won't cut it, we need an exception // TODO check for cyclic dependencies! this way just won't cut it, we need an exception
if (started.contains(plugin)) { if (started.contains(plugin)) {
return; return;
@@ -20,12 +20,19 @@ public final class RubyPluginEnvironment implements PluginEnvironment {
*/ */
private final ScriptingContainer container = new ScriptingContainer(); private final ScriptingContainer container = new ScriptingContainer();
/**
* The World this RubyPluginEnvironment is for.
*/
private final World world;
/** /**
* Creates and bootstraps the Ruby plugin environment. * Creates and bootstraps the Ruby plugin environment.
* *
* @param world The {@link World} this RubyPluginEnvironment is for.
* @throws IOException If an I/O error occurs during bootstrapping. * @throws IOException If an I/O error occurs during bootstrapping.
*/ */
public RubyPluginEnvironment() throws IOException { public RubyPluginEnvironment(World world) throws IOException {
this.world = world;
parseBootstrapper(); parseBootstrapper();
} }
@@ -54,7 +61,7 @@ public final class RubyPluginEnvironment implements PluginEnvironment {
@Override @Override
public void setContext(PluginContext context) { public void setContext(PluginContext context) {
container.put("$ctx", context); container.put("$ctx", context);
container.put("$world", World.getWorld()); container.put("$world", world);
} }
} }