Move login and logout listening to the new Event system and update plugins to reflect this move, remove previous listening system, fix minor bug in EventListenerChainSet.

This commit is contained in:
Major-
2015-02-27 04:11:08 +00:00
parent 3e4ecb5c73
commit 06b6f5fb74
23 changed files with 174 additions and 220 deletions
+26 -31
View File
@@ -16,10 +16,9 @@ require 'java'
java_import 'org.apollo.game.command.CommandListener' java_import 'org.apollo.game.command.CommandListener'
java_import 'org.apollo.game.message.handler.MessageHandler' java_import 'org.apollo.game.message.handler.MessageHandler'
java_import 'org.apollo.game.login.LoginListener'
java_import 'org.apollo.game.login.LogoutListener'
java_import 'org.apollo.game.model.World' java_import 'org.apollo.game.model.World'
java_import 'org.apollo.game.model.entity.Player' java_import 'org.apollo.game.model.entity.Player'
java_import 'org.apollo.game.model.event.EventListener'
java_import 'org.apollo.game.model.setting.PrivilegeLevel' java_import 'org.apollo.game.model.setting.PrivilegeLevel'
java_import 'org.apollo.game.scheduling.ScheduledTask' java_import 'org.apollo.game.scheduling.ScheduledTask'
java_import 'org.apollo.util.plugin.PluginContext' java_import 'org.apollo.util.plugin.PluginContext'
@@ -32,50 +31,43 @@ RIGHTS_STANDARD = PrivilegeLevel::STANDARD
# Extends the (Ruby) String class with a method to convert a lower case, # Extends the (Ruby) String class with a method to convert a lower case,
# underscore delimited string to camel-case. # underscore delimited string to camel-case.
class String class String
def camelize
# Converts a ruby snake_case string to camel-case.
def camelize()
gsub(/(?:^|_)(.)/) { $1.upcase } gsub(/(?:^|_)(.)/) { $1.upcase }
end end
end end
# A CommandListener that executes a Proc object with two arguments: the player and the command. # A CommandListener that executes a Proc object with two arguments: the player and the command.
class ProcCommandListener < CommandListener class ProcCommandListener < CommandListener
# Creates the ProcCommandListener.
def initialize(rights, block) def initialize(rights, block)
super(rights) super(rights)
@block = block @block = block
end end
# Executes the block listening for the command.
def execute(player, command) def execute(player, command)
@block.call(player, command) @block.call(player, command)
end end
end end
# A LoginListener that executes a Proc object with the player argument.
class ProcLoginListener
java_implements LoginListener
def initialize(block)
super()
@block = block
end
def execute(player)
@block.call(player)
end
end
# A LogoutListener that executes a Proc object with the player argument. # A LogoutListener that executes a Proc object with the player argument.
class ProcLogoutListener class ProcEventListener
java_implements LogoutListener java_implements EventListener
# Creates the ProcEventListener.
def initialize(block) def initialize(block)
super() super()
@block = block @block = block
end end
def execute(player) # Executes the block handling the Event.
@block.call(player) def handle(event, context)
@block.call(event, context)
end end
end end
@@ -84,12 +76,14 @@ end
# context, the player and the message. # context, the player and the message.
class ProcMessageHandler < MessageHandler class ProcMessageHandler < MessageHandler
# Creates the ProcMessageListener.
def initialize(block, option) def initialize(block, option)
super() # required (with brackets!), see http://jira.codehaus.org/browse/JRUBY-679 super()
@block = block @block = block
@option = option @option = option
end end
# Handles the message.
def handle(ctx, player, message) def handle(ctx, player, message)
@block.call(ctx, player, message) if (@option == 0 || @option == message.option) @block.call(ctx, player, message) if (@option == 0 || @option == message.option)
end end
@@ -99,11 +93,13 @@ end
# A ScheduledTask which executes a Proc object with one argument (itself). # A ScheduledTask which executes a Proc object with one argument (itself).
class ProcScheduledTask < ScheduledTask class ProcScheduledTask < ScheduledTask
# Creates the ProcScheduledTask.
def initialize(delay, immediate, block) def initialize(delay, immediate, block)
super(delay, immediate) super(delay, immediate)
@block = block @block = block
end end
# Executes the block.
def execute def execute
@block.call(self) @block.call(self)
end end
@@ -138,8 +134,7 @@ end
# * :command # * :command
# * :message # * :message
# * :button # * :button
# * :login # * Any valid Event, as a symbol in ruby snake_case form.
# * :logout
# #
# A command takes one or two arguments (the command name and optionally the # A command takes one or two arguments (the command name and optionally the
# minimum rights level to use it). The minimum rights level defaults to # minimum rights level to use it). The minimum rights level defaults to
@@ -155,9 +150,10 @@ def on(type, *args, &block)
when :command then on_command(args, block) when :command then on_command(args, block)
when :message then on_message(args, block) when :message then on_message(args, block)
when :button then on_button(args, block) when :button then on_button(args, block)
when :login then on_login(block) else
when :logout then on_logout(block) class_name = type.to_s.camelize.concat('Event')
else raise 'Unknown message type.' type = Java::JavaClass.for_name("org.apollo.game.model.event.impl.#{class_name}")
$world.listen_for(type, ProcEventListener.new(block))
end end
end end
@@ -189,10 +185,9 @@ def on_message(args, proc)
end end
end end
if message.is_a?(Symbol)
class_name = message.to_s.camelize.concat('Message') class_name = message.to_s.camelize.concat('Message')
message = Java::JavaClass.for_name("org.apollo.game.message.impl.#{class_name}") message = Java::JavaClass.for_name("org.apollo.game.message.impl.#{class_name}")
end
$ctx.add_last_message_handler(message, ProcMessageHandler.new(proc, option)) $ctx.add_last_message_handler(message, ProcMessageHandler.new(proc, option))
end end
@@ -42,7 +42,8 @@ on :message, :remove_friend do |ctx, player, message|
end end
# Update the friend server status and send the friend/ignore lists of the player logging in. # Update the friend server status and send the friend/ignore lists of the player logging in.
on :login do |player| on :login do |event, context|
player = event.player
player.send(FriendServerStatusMessage.new(ServerStatus::CONNECTING)) player.send(FriendServerStatusMessage.new(ServerStatus::CONNECTING))
player.send(IgnoreListMessage.new(player.ignored_usernames)) if player.ignored_usernames.size > 0 player.send(IgnoreListMessage.new(player.ignored_usernames)) if player.ignored_usernames.size > 0
@@ -62,8 +63,8 @@ on :login do |player|
end end
# Notifies the player's friends that the player has logged out. # Notifies the player's friends that the player has logged out.
on :logout do |player| on :logout do |event, context|
update_friends(player, 0) update_friends(event.player, 0)
end end
+6 -8
View File
@@ -51,15 +51,13 @@ def append_tiara(hash)
end end
# Sets the correct config upon login, if the player is wearing a tiara. # Sets the correct config upon login, if the player is wearing a tiara.
on :login do |player| on :login do |event, context|
player = event.player
hat = player.equipment.get(EquipmentConstants::HAT) hat = player.equipment.get(EquipmentConstants::HAT)
next if hat.nil?
tiara = TIARAS_BY_ID[hat] unless hat.nil?
unless tiara.nil? tiara = TIARAS_BY_ID[hat]
tiara.send_config if tiara.nil? then send_empty_config(player) else tiara.send_config end
else
send_empty_config(player)
end end
end end
@@ -67,7 +65,7 @@ end
on :message, :second_object_action do |ctx, player, message| on :message, :second_object_action do |ctx, player, message|
object_id = message.id object_id = message.id
tiara = TIARAS_BY_ALTAR[object_id] tiara = TIARAS_BY_ALTAR[object_id]
return if tiara.nil? next if tiara.nil?
hat = player.equipment.get(EquipmentConstants::HAT) hat = player.equipment.get(EquipmentConstants::HAT)
@@ -1,38 +0,0 @@
package org.apollo.game.login;
import java.util.ArrayList;
import java.util.List;
import org.apollo.game.model.entity.Player;
/**
* A class that dispatches {@link Player}s to {@link LoginListener}s.
*
* @author Major
*/
public final class LoginDispatcher {
/**
* A {@link List} of login listeners.
*/
private final List<LoginListener> listeners = new ArrayList<>();
/**
* Dispatches a player to the appropriate login listener.
*
* @param player The player.
*/
public void dispatch(Player player) {
listeners.forEach(listener -> listener.execute(player));
}
/**
* Registers a listener with this dispatcher.
*
* @param listener The listener.
*/
public void register(LoginListener listener) {
listeners.add(listener);
}
}
@@ -1,20 +0,0 @@
package org.apollo.game.login;
import org.apollo.game.model.entity.Player;
/**
* A class that should be extended for actions that should be executed when the player logs in.
*
* @author Major
*/
@FunctionalInterface
public interface LoginListener {
/**
* Executes the action for this listener.
*
* @param player The player.
*/
public void execute(Player player);
}
@@ -1,38 +0,0 @@
package org.apollo.game.login;
import java.util.ArrayList;
import java.util.List;
import org.apollo.game.model.entity.Player;
/**
* A class that dispatches {@link Player}s to {@link LogoutListener}s.
*
* @author Major
*/
public final class LogoutDispatcher {
/**
* A {@link List} of logout listeners.
*/
private final List<LogoutListener> listeners = new ArrayList<>();
/**
* Dispatches a player to the appropriate logout listener.
*
* @param player The player.
*/
public void dispatch(Player player) {
listeners.forEach(listener -> listener.execute(player));
}
/**
* Registers a listener with this dispatcher.
*
* @param listener The listener.
*/
public void register(LogoutListener listener) {
listeners.add(listener);
}
}
@@ -1,20 +0,0 @@
package org.apollo.game.login;
import org.apollo.game.model.entity.Player;
/**
* An interface that should be implemented for actions that should be executed when the player logs out.
*
* @author Major
*/
@FunctionalInterface
public interface LogoutListener {
/**
* Executes the action for this listener.
*
* @param player The player.
*/
public void execute(Player player);
}
@@ -1,4 +0,0 @@
/**
* Contains login and logout listeners.
*/
package org.apollo.game.login;
+3 -35
View File
@@ -15,8 +15,6 @@ import org.apollo.fs.decoder.ItemDefinitionDecoder;
import org.apollo.fs.decoder.NpcDefinitionDecoder; import org.apollo.fs.decoder.NpcDefinitionDecoder;
import org.apollo.fs.decoder.ObjectDefinitionDecoder; import org.apollo.fs.decoder.ObjectDefinitionDecoder;
import org.apollo.game.command.CommandDispatcher; import org.apollo.game.command.CommandDispatcher;
import org.apollo.game.login.LoginDispatcher;
import org.apollo.game.login.LogoutDispatcher;
import org.apollo.game.model.area.Sector; import org.apollo.game.model.area.Sector;
import org.apollo.game.model.area.SectorRepository; import org.apollo.game.model.area.SectorRepository;
import org.apollo.game.model.def.EquipmentDefinition; import org.apollo.game.model.def.EquipmentDefinition;
@@ -27,9 +25,9 @@ import org.apollo.game.model.entity.Entity;
import org.apollo.game.model.entity.GameObject; import org.apollo.game.model.entity.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.event.Event; import org.apollo.game.model.event.Event;
import org.apollo.game.model.entity.event.EventListener; import org.apollo.game.model.event.EventListener;
import org.apollo.game.model.entity.event.EventListenerChainSet; import org.apollo.game.model.event.EventListenerChainSet;
import org.apollo.game.scheduling.ScheduledTask; import org.apollo.game.scheduling.ScheduledTask;
import org.apollo.game.scheduling.Scheduler; import org.apollo.game.scheduling.Scheduler;
import org.apollo.io.EquipmentDefinitionParser; import org.apollo.io.EquipmentDefinitionParser;
@@ -99,16 +97,6 @@ public final class World {
*/ */
private final EventListenerChainSet events = new EventListenerChainSet(); private final EventListenerChainSet events = new EventListenerChainSet();
/**
* The login dispatcher.
*/
private final LoginDispatcher loginDispatcher = new LoginDispatcher();
/**
* The logout dispatcher.
*/
private final LogoutDispatcher logoutDispatcher = new LogoutDispatcher();
/** /**
* The {@link MobRepository} of {@link Npc}s. * The {@link MobRepository} of {@link Npc}s.
*/ */
@@ -160,24 +148,6 @@ public final class World {
return commandDispatcher; return commandDispatcher;
} }
/**
* Gets the {@link LoginDispatcher}.
*
* @return The dispatcher.
*/
public LoginDispatcher getLoginDispatcher() {
return loginDispatcher;
}
/**
* Gets the {@link LogoutDispatcher}.
*
* @return The dispatcher.
*/
public LogoutDispatcher getLogoutDispatcher() {
return logoutDispatcher;
}
/** /**
* Gets the npc repository. * Gets the npc repository.
* *
@@ -394,8 +364,6 @@ public final class World {
Sector sector = sectors.fromPosition(player.getPosition()); Sector sector = sectors.fromPosition(player.getPosition());
sector.removeEntity(player); sector.removeEntity(player);
logoutDispatcher.dispatch(player);
} else { } else {
logger.warning("Could not find player " + player + " to unregister!"); logger.warning("Could not find player " + player + " to unregister!");
} }
+2 -1
View File
@@ -19,6 +19,7 @@ import org.apollo.game.model.Appearance;
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.Sector; import org.apollo.game.model.area.Sector;
import org.apollo.game.model.event.impl.LoginEvent;
import org.apollo.game.model.inter.InterfaceConstants; import org.apollo.game.model.inter.InterfaceConstants;
import org.apollo.game.model.inter.InterfaceListener; import org.apollo.game.model.inter.InterfaceListener;
import org.apollo.game.model.inter.InterfaceSet; import org.apollo.game.model.inter.InterfaceSet;
@@ -701,7 +702,7 @@ public final class Player extends Mob {
bank.forceRefresh(); bank.forceRefresh();
skillSet.forceRefresh(); skillSet.forceRefresh();
World.getWorld().getLoginDispatcher().dispatch(this); World.getWorld().submit(new LoginEvent(this));
} }
/** /**
@@ -1,4 +1,4 @@
package org.apollo.game.model.entity.event; package org.apollo.game.model.event;
/** /**
* A type of event that may occur in the game world. * A type of event that may occur in the game world.
@@ -1,4 +1,4 @@
package org.apollo.game.model.entity.event; package org.apollo.game.model.event;
/** /**
* The context of an {@link Event}. * The context of an {@link Event}.
@@ -15,7 +15,7 @@ final class EventContext {
/** /**
* Terminates the Event chain. * Terminates the Event chain.
*/ */
public void terminate() { public void terminateEvent() {
terminated = true; terminated = true;
} }
@@ -1,4 +1,4 @@
package org.apollo.game.model.entity.event; package org.apollo.game.model.event;
/** /**
* A listener for an {@link Event} that may occur in the game world. * A listener for an {@link Event} that may occur in the game world.
@@ -1,4 +1,4 @@
package org.apollo.game.model.entity.event; package org.apollo.game.model.event;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -1,4 +1,4 @@
package org.apollo.game.model.entity.event; package org.apollo.game.model.event;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -23,8 +23,8 @@ public final class EventListenerChainSet {
*/ */
public <E extends Event> boolean notify(E event) { public <E extends Event> boolean notify(E event) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
EventListenerChain<E> chain = (EventListenerChain<E>) chains.get(event); EventListenerChain<E> chain = (EventListenerChain<E>) chains.get(event.getClass());
return chain.notify(event); return (chain == null) ? true : chain.notify(event);
} }
/** /**
@@ -0,0 +1,35 @@
package org.apollo.game.model.event;
import org.apollo.game.model.entity.Player;
/**
* An {@link Event} involving a {@link Player}.
*
* @author Major
*/
public abstract class PlayerEvent extends Event {
/**
* The Player.
*/
private final Player player;
/**
* Creates the PlayerEvent.
*
* @param player The {@link Player}.
*/
public PlayerEvent(Player player) {
this.player = player;
}
/**
* Gets the {@link Player}.
*
* @return The Player.
*/
public Player getPlayer() {
return player;
}
}
@@ -0,0 +1,23 @@
package org.apollo.game.model.event.impl;
import org.apollo.game.model.entity.Player;
import org.apollo.game.model.event.Event;
import org.apollo.game.model.event.PlayerEvent;
/**
* An {@link Event} indicating that a player's open interfaces are about to be closed.
*
* @author Major
*/
public final class CloseInterfacesEvent extends PlayerEvent {
/**
* Creates the CloseInterfacesEvent.
*
* @param player The {@link Player} whose interfaces are being closed.
*/
public CloseInterfacesEvent(Player player) {
super(player);
}
}
@@ -0,0 +1,22 @@
package org.apollo.game.model.event.impl;
import org.apollo.game.model.entity.Player;
import org.apollo.game.model.event.PlayerEvent;
/**
* A {@link PlayerEvent} that is fired when a {@link Player} logs in.
*
* @author Major
*/
public final class LoginEvent extends PlayerEvent {
/**
* Creates the LoginEvent.
*
* @param player The {@link Player} logging in.
*/
public LoginEvent(Player player) {
super(player);
}
}
@@ -0,0 +1,22 @@
package org.apollo.game.model.event.impl;
import org.apollo.game.model.entity.Player;
import org.apollo.game.model.event.PlayerEvent;
/**
* A {@link PlayerEvent} that is fired when a {@link Player} logs out.
*
* @author Major
*/
public final class LogoutEvent extends PlayerEvent {
/**
* Creates the LogoutEvent.
*
* @param player The {@link Player} logging out.
*/
public LogoutEvent(Player player) {
super(player);
}
}
@@ -0,0 +1,4 @@
/**
* Contains Event implementations.
*/
package org.apollo.game.model.event.impl;
@@ -1,4 +1,4 @@
/** /**
* Contains event-related classes. * Contains event-related classes.
*/ */
package org.apollo.game.model.entity.event; package org.apollo.game.model.event;
@@ -11,7 +11,9 @@ 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.inter.dialogue.DialogueListener; import org.apollo.game.model.inter.dialogue.DialogueListener;
import org.apollo.game.model.inv.InventoryListener; import org.apollo.game.model.inv.InventoryListener;
@@ -86,8 +88,11 @@ public final class InterfaceSet {
* Closes the current open interface(s). * Closes the current open interface(s).
*/ */
public void close() { public void close() {
closeAndNotify(); CloseInterfacesEvent event = new CloseInterfacesEvent(player);
player.send(new CloseInterfaceMessage()); if (World.getWorld().submit(event)) {
closeAndNotify();
player.send(new CloseInterfaceMessage());
}
} }
/** /**
+10 -10
View File
@@ -3,24 +3,24 @@ 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.command.CommandListener;
import org.apollo.game.login.LoginListener;
import org.apollo.game.login.LogoutListener;
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.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
* {@link MessageHandler}s to {@link MessageHandlerChain}s. * {@link MessageHandler}s to {@link MessageHandlerChain}s.
* *
* @author Graham * @author Graham
* @author Major
*/ */
public final class PluginContext { public final class PluginContext {
// TODO move listeners to world?
/** /**
* Adds a {@link CommandListener}. * Adds a {@link CommandListener}.
* *
@@ -32,21 +32,21 @@ public final class PluginContext {
} }
/** /**
* Adds a {@link LoginListener}. * Adds an {@link EventListener} for a {@link LoginEvent}.
* *
* @param listener The listener. * @param listener The listener.
*/ */
public static void addLoginListener(LoginListener listener) { public static void addLoginListener(EventListener<LoginEvent> listener) {
World.getWorld().getLoginDispatcher().register(listener); World.getWorld().listenFor(LoginEvent.class, listener);
} }
/** /**
* Adds a {@link LogoutListener}. * Adds an {@link EventListener} for a {@link LogoutEvent}.
* *
* @param listener The listener. * @param listener The listener.
*/ */
public static void addLogoutListener(LogoutListener listener) { public static void addLogoutListener(EventListener<LogoutEvent> listener) {
World.getWorld().getLogoutDispatcher().register(listener); World.getWorld().listenFor(LogoutEvent.class, listener);
} }
/** /**