Rebase the MessageHandler, MessageHandlerChain and MessageHandlerChainSet

Rebased several other pieces of code
This commit is contained in:
atomicint
2015-03-29 12:52:55 -04:00
parent 7f345fffac
commit 654a1a6dfd
71 changed files with 452 additions and 457 deletions
+4 -4
View File
@@ -30,17 +30,17 @@ class BankAction < DistancedAction
end end
# Intercepts the object action message # Intercepts the object action message
on :message, :second_object_action do |ctx, player, message| on :message, :second_object_action do |player, message|
if message.id == BANK_BOOTH_ID if message.id == BANK_BOOTH_ID
player.start_action(BankAction.new(player, message.position)) player.start_action(BankAction.new(player, message.position))
ctx.break_handler_chain message.terminate
end end
end end
on :message, :second_npc_action do |ctx, player, message| on :message, :second_npc_action do |player, message|
npc = $world.npc_repository.get(message.index) npc = $world.npc_repository.get(message.index)
if BANKER_NPCS.include?(npc.id) if BANKER_NPCS.include?(npc.id)
player.start_action(BankAction.new(player, npc.position)) player.start_action(BankAction.new(player, npc.position))
ctx.break_handler_chain message.terminate
end end
end end
+7 -8
View File
@@ -15,7 +15,7 @@
require 'java' 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.MessageHandler'
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.event.EventListener'
@@ -75,11 +75,10 @@ class ProcEventListener
end end
# A MessageHandler which executes a Proc object with three arguments: the chain # A MessageHandler which executes a Proc object with two arguments: the player and the message.
# context, the player and the message.
class ProcMessageHandler < MessageHandler class ProcMessageHandler < MessageHandler
# Creates the ProcMessageListener. # Creates the ProcMessageHandler.
def initialize(block, option) def initialize(block, option)
super($world) super($world)
@block = block @block = block
@@ -87,8 +86,8 @@ class ProcMessageHandler < MessageHandler
end end
# Handles the message. # Handles the message.
def handle(ctx, player, message) def handle(player, message)
@block.call(ctx, player, message) if (@option == 0 || @option == message.option) @block.call(player, message) if (@option == 0 || @option == message.option)
end end
end end
@@ -166,7 +165,7 @@ def on_button(args, proc)
id = args[0].to_i id = args[0].to_i
on :message, :button do |ctx, player, message| on :message, :button do |player, message|
proc.call(player) if message.widget_id == id proc.call(player) if message.widget_id == id
end end
end end
@@ -192,7 +191,7 @@ def on_message(args, proc)
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}")
$ctx.add_last_message_handler(message, ProcMessageHandler.new(proc, option)) $ctx.add_message_handler(message, ProcMessageHandler.new(proc, option))
end end
# Defines an action to be taken upon a command. # Defines an action to be taken upon a command.
+1 -1
View File
@@ -3,7 +3,7 @@ require 'java'
java_import 'org.apollo.game.model.entity.setting.PrivacyState' java_import 'org.apollo.game.model.entity.setting.PrivacyState'
java_import 'org.apollo.game.message.impl.SendFriendMessage' java_import 'org.apollo.game.message.impl.SendFriendMessage'
on :message, :privacy_option do |ctx, player, message| on :message, :privacy_option do |player, message|
player.chat_privacy = message.chat_privacy player.chat_privacy = message.chat_privacy
player.friend_privacy = message.friend_privacy player.friend_privacy = message.friend_privacy
player.trade_privacy = message.trade_privacy player.trade_privacy = message.trade_privacy
@@ -11,7 +11,7 @@ java_import 'org.apollo.game.model.entity.Player'
# Processes an add friend message, updating the logged-in status of the player (and the person they added) if necessary. # Processes an add friend message, updating the logged-in status of the player (and the person they added) if necessary.
on :message, :add_friend do |ctx, player, message| on :message, :add_friend do |player, message|
friend_username = message.username friend_username = message.username
player_username = player.username player_username = player.username
@@ -30,7 +30,7 @@ on :message, :add_friend do |ctx, player, message|
end end
# Processes a remove friend message, updating the logged-in status of the player if necessary. # Processes a remove friend message, updating the logged-in status of the player if necessary.
on :message, :remove_friend do |ctx, player, message| on :message, :remove_friend do |player, message|
friend_username = message.username friend_username = message.username
player_username = player.username player_username = player.username
@@ -1,9 +1,9 @@
on :message, :add_ignore do |ctx, player, message| on :message, :add_ignore do |player, message|
username = message.username username = message.username
player.add_ignore(username) player.add_ignore(username)
end end
on :message, :remove_ignore do |ctx, player, message| on :message, :remove_ignore do |player, message|
username = message.username username = message.username
player.remove_ignore(username) player.remove_ignore(username)
end end
@@ -4,7 +4,7 @@ java_import 'org.apollo.game.message.impl.ForwardPrivateChatMessage'
java_import 'org.apollo.game.model.World' java_import 'org.apollo.game.model.World'
java_import 'org.apollo.game.model.entity.setting.PrivacyState' java_import 'org.apollo.game.model.entity.setting.PrivacyState'
on :message, :private_chat do |ctx, player, message| on :message, :private_chat do |player, message|
friend = $world.get_player(message.username) friend = $world.get_player(message.username)
friend.send(ForwardPrivateChatMessage.new(player.username, player.privilege_level, message.compressed_chat)) if interaction_permitted(player, friend) friend.send(ForwardPrivateChatMessage.new(player.username, player.privilege_level, message.compressed_chat)) if interaction_permitted(player, friend)
end end
+2 -2
View File
@@ -54,11 +54,11 @@ class ConsumeAction < Action
end end
# Intercepts the first item option message and consumes the consumable, if necessary. # Intercepts the first item option message and consumes the consumable, if necessary.
on :message, :first_item_option do |ctx, player, message| on :message, :first_item_option do |player, message|
consumable = CONSUMABLES[message.id] consumable = CONSUMABLES[message.id]
unless consumable.nil? unless consumable.nil?
player.start_action(ConsumeAction.new(player, message.slot, consumable)) player.start_action(ConsumeAction.new(player, message.slot, consumable))
ctx.break_handler_chain message.terminate
end end
end end
+3 -3
View File
@@ -71,13 +71,13 @@ class Conversation
raise 'Npc cannot be null when opening a dialogue.' if npc_index.nil? raise 'Npc cannot be null when opening a dialogue.' if npc_index.nil?
@starters << dialogue @starters << dialogue
on :message, :first_npc_action do |ctx, player, event| on :message, :first_npc_action do |player, message|
npc = $world.npc_repository.get(event.index) npc = $world.npc_repository.get(message.index)
if npc_index == npc.id if npc_index == npc.id
@starters.each do |start| @starters.each do |start|
if dialogue.precondition(player) if dialogue.precondition(player)
player.start_action(OpenDialogueAction.new(player, npc, dialogue)) player.start_action(OpenDialogueAction.new(player, npc, dialogue))
ctx.break_handler_chain() message.terminate
break break
end end
end end
+1 -1
View File
@@ -45,6 +45,6 @@ class DummyAction < DistancedAction
end end
end end
on :message, :second_object_action do |ctx, player, message| on :message, :second_object_action do |player, message|
player.start_action(DummyAction.new(player, message.position)) if message.id == DUMMY_ID player.start_action(DummyAction.new(player, message.position)) if message.id == DUMMY_ID
end end
+2 -2
View File
@@ -12,10 +12,10 @@ ANIMATIONS = {
} }
# Intercept the button message. # Intercept the button message.
on :message, :button do |ctx, player, message| on :message, :button do |player, message|
anim = ANIMATIONS[message.widget_id] anim = ANIMATIONS[message.widget_id]
unless anim == nil unless anim == nil
player.play_animation(anim) player.play_animation(anim)
ctx.break_handler_chain message.terminate
end end
end end
@@ -126,7 +126,7 @@ def add_survival_items(player)
end end
# Intercept the FirstObjectActionMessage to send tutorial-only events if the player is chopping down a tree. # Intercept the FirstObjectActionMessage to send tutorial-only events if the player is chopping down a tree.
on :message, :first_object_action do |ctx, player, message| on :message, :first_object_action do |player, message|
if (player.in_tutorial_island && message.id == SurvivalConstants::TREE_ID) if (player.in_tutorial_island && message.id == SurvivalConstants::TREE_ID)
progress = player.tutorial_island_progress progress = player.tutorial_island_progress
if (progress < :cut_tree) if (progress < :cut_tree)
@@ -138,9 +138,9 @@ on :message, :first_object_action do |ctx, player, message|
end end
# Intercept the FlashingTabClickedMessage to update the player's progress, if applicable. # Intercept the FlashingTabClickedMessage to update the player's progress, if applicable.
on :message, :flashing_tab_clicked do |ctx, player, message| on :message, :flashing_tab_clicked do |player, message|
if (player.in_tutorial_island && message.tab == SurvivalConstants::INVENTORY_TAB_INDEX && player.tutorial_island_progress == :given_axe) if (player.in_tutorial_island && message.tab == SurvivalConstants::INVENTORY_TAB_INDEX && player.tutorial_island_progress == :given_axe)
player.tutorial_island_progress = :cut_tree player.tutorial_island_progress = :cut_tree
ctx.break_handler_chain() message.terminate
end end
end end
+2 -2
View File
@@ -23,8 +23,8 @@ class OpenDoorAction < DistancedAction
end end
# Message handler for opening and closing doors. # MessageListener for opening and closing doors.
on :message, :first_object_action do |ctx, player, message| on :message, :first_object_action do |player, message|
if DoorUtil::is_door?(message.id) if DoorUtil::is_door?(message.id)
puts "Player: #{player.position}, door: #{message.position}" puts "Player: #{player.position}, door: #{message.position}"
door = DoorUtil::get_door_object(message.position, message.id) door = DoorUtil::get_door_object(message.position, message.id)
+2 -2
View File
@@ -100,12 +100,12 @@ class FishingAction < DistancedAction
end end
# Intercepts the NpcAction message to determine whether or not a clicked npc was a fishing spot. # Intercepts the NpcAction message to determine whether or not a clicked npc was a fishing spot.
on :message, :npc_action do |ctx, player, message| on :message, :npc_action do |player, message|
npc = $world.npc_repository.get(message.index) npc = $world.npc_repository.get(message.index)
spot = FISHING_SPOTS[npc.id] spot = FISHING_SPOTS[npc.id]
unless spot.nil? unless spot.nil?
player.start_action(FishingAction.new(player, npc.position, spot, message.option)) player.start_action(FishingAction.new(player, npc.position, spot, message.option))
ctx.break_handler_chain message.terminate
end end
end end
+7 -7
View File
@@ -25,8 +25,8 @@ module HerbloreMethod
end end
end end
# The ItemOnItemMessage handler for all Herblore-related functions. # The ItemOnItemMessage listener for all Herblore-related functions.
on :message, :item_on_item do |ctx, player, message| on :message, :item_on_item do |player, message|
primary = message.id primary = message.id
secondary = message.target_id secondary = message.target_id
hash = HERBLORE_ITEM_ON_ITEM[primary] hash = HERBLORE_ITEM_ON_ITEM[primary]
@@ -41,25 +41,25 @@ on :message, :item_on_item do |ctx, player, message|
method = hash[secondary] method = hash[secondary]
unless method.nil? unless method.nil?
method.invoke(player, primary, secondary) method.invoke(player, primary, secondary)
ctx.break_handler_chain message.terminate
end end
end end
end end
# The ItemOptionMessage handler for all Herblore-related functions. # The ItemOptionMessage listener for all Herblore-related functions.
on :message, :first_item_option do |ctx, player, message| on :message, :first_item_option do |player, message|
id = message.id id = message.id
method = HERBLORE_ITEM[id] method = HERBLORE_ITEM[id]
unless method.nil? unless method.nil?
method.invoke(player, id, message.slot) method.invoke(player, id, message.slot)
ctx.break_handler_chain message.terminate
end end
method = DRINK_ITEM[id] method = DRINK_ITEM[id]
unless method.nil? unless method.nil?
method.invoke(player, id, message.slot) method.invoke(player, id, message.slot)
ctx.break_handler_chain message.terminate
end end
end end
+1 -1
View File
@@ -223,7 +223,7 @@ class GrindingAction < Action
end end
end end
# Appends a ground ingredient to the ItemOnItemMessage handler interception. # Appends a ground ingredient to the ItemOnItemMessage listener interception.
def append_ground(id, raw) def append_ground(id, raw)
ground = GroundIngredient.new(id, raw) ground = GroundIngredient.new(id, raw)
append_herblore_item(ground, PESTLE_MORTAR, raw) append_herblore_item(ground, PESTLE_MORTAR, raw)
+6 -6
View File
@@ -118,7 +118,7 @@ class ItemSpellAction < SpellAction
end end
# Intercepts the magic on item message. # Intercepts the magic on item message.
on :message, :magic_on_item do |ctx, player, message| on :message, :magic_on_item do |player, message|
spell = message.spell_id spell = message.spell_id
alch = ALCHEMY_SPELLS[spell] alch = ALCHEMY_SPELLS[spell]
@@ -126,7 +126,7 @@ on :message, :magic_on_item do |ctx, player, message|
slot = message.slot slot = message.slot
item = player.inventory.get(slot) item = player.inventory.get(slot)
player.start_action(AlchemyAction.new(player, alch, slot, item)) player.start_action(AlchemyAction.new(player, alch, slot, item))
ctx.break_handler_chain message.terminate
return return
end end
@@ -135,18 +135,18 @@ on :message, :magic_on_item do |ctx, player, message|
slot = message.slot slot = message.slot
item = player.inventory.get(slot) item = player.inventory.get(slot)
player.start_action(EnchantAction.new(player, ench, slot, item, ENCHANT_ITEMS[item.id])) player.start_action(EnchantAction.new(player, ench, slot, item, ENCHANT_ITEMS[item.id]))
ctx.break_handler_chain message.terminate
end end
end end
# Intercepts the button message # Intercepts the button message
on :message, :button do |ctx, player, message| on :message, :button do |player, message|
button = message.widget_id button = message.widget_id
tele = TELEPORT_SPELLS[button] tele = TELEPORT_SPELLS[button]
unless tele.nil? unless tele.nil?
player.start_action(TeleportingAction.new(player, tele)) player.start_action(TeleportingAction.new(player, tele))
ctx.break_handler_chain message.terminate
return return
end end
@@ -155,6 +155,6 @@ on :message, :button do |ctx, player, message|
slots = bone_slots player slots = bone_slots player
if slots.length == 0 then player.send_message("You can't convert these bones!") else player.start_action(ConvertingAction.new(player, conv, slots)) end if slots.length == 0 then player.send_message("You can't convert these bones!") else player.start_action(ConvertingAction.new(player, conv, slots)) end
ctx.break_handler_chain message.terminate
end end
end end
+2 -2
View File
@@ -134,7 +134,7 @@ class ProspectingAction < DistancedAction
end end
on :message, :first_object_action do |ctx, mob, message| on :message, :first_object_action do |mob, message|
ore = ORES[message.id] ore = ORES[message.id]
unless ore.nil? unless ore.nil?
@@ -142,7 +142,7 @@ on :message, :first_object_action do |ctx, mob, message|
end end
end end
on :message, :second_object_action do |ctx, mob, message| on :message, :second_object_action do |mob, message|
ore = ORES[message.id] ore = ORES[message.id]
if !ore.nil? if !ore.nil?
+2 -2
View File
@@ -51,11 +51,11 @@ class BuryBoneAction < Action
end end
# Intercepts the first item option message. # Intercepts the first item option message.
on :message, :first_item_option do |ctx, player, message| on :message, :first_item_option do |player, message|
bone = BONES[message.id] bone = BONES[message.id]
unless bone == nil unless bone == nil
player.start_action(BuryBoneAction.new(player, message.slot, bone)) player.start_action(BuryBoneAction.new(player, message.slot, bone))
ctx.break_handler_chain message.terminate
end end
end end
+1 -1
View File
@@ -9,7 +9,7 @@ declare_attribute(:active_prayer, -1, :persistent)
PRAYERS = {} PRAYERS = {}
# Intercept the ButtonMessage to toggle a prayer. # Intercept the ButtonMessage to toggle a prayer.
on :message, :button do |ctx, player, message| on :message, :button do |player, message|
button = message.widget_id button = message.widget_id
prayer = PRAYERS[button] prayer = PRAYERS[button]
+5 -5
View File
@@ -24,26 +24,26 @@ end
# Intercepts the item on object message. # Intercepts the item on object message.
on :message, :item_on_object do |ctx, player, message| on :message, :item_on_object do |player, message|
talisman = TALISMANS[message.id]; altar = ENTRANCE_ALTARS[message.object_id] talisman = TALISMANS[message.id]; altar = ENTRANCE_ALTARS[message.object_id]
unless (talisman.nil? || altar.nil?) unless (talisman.nil? || altar.nil?)
player.start_action(TeleportAction.new(player, message.position, 2, altar.entrance_position)) player.start_action(TeleportAction.new(player, message.position, 2, altar.entrance_position))
ctx.break_handler_chain message.terminate
end end
end end
# Intercepts the first object action message. # Intercepts the first object action message.
on :message, :object_action do |ctx, player, message| on :message, :object_action do |player, message|
if (message.option == 1) if (message.option == 1)
object_id = message.id object_id = message.id
if (altar = PORTALS[object_id]) != nil # Get the altar associated with this exit portal. if (altar = PORTALS[object_id]) != nil # Get the altar associated with this exit portal.
player.start_action(TeleportAction.new(player, altar.entrance_position, 1, altar.exit_position)) player.start_action(TeleportAction.new(player, altar.entrance_position, 1, altar.exit_position))
ctx.break_handler_chain message.terminate
elsif (rune = RUNES[object_id]) != nil # Get the rune associated with this altar. elsif (rune = RUNES[object_id]) != nil # Get the rune associated with this altar.
altar = CRAFTING_ALTARS[object_id] altar = CRAFTING_ALTARS[object_id]
player.start_action(RunecraftingAction.new(player, rune, altar.crafting_centre)) player.start_action(RunecraftingAction.new(player, rune, altar.crafting_centre))
ctx.break_handler_chain message.terminate
end end
end end
end end
+2 -2
View File
@@ -30,11 +30,11 @@ def append_talisman(hash)
end end
# Intercepts the item option message. # Intercepts the item option message.
on :message, :fourth_item_option do |ctx, player, message| on :message, :fourth_item_option do |player, message|
talisman = TALISMANS[message.id] talisman = TALISMANS[message.id]
if (talisman != nil) if (talisman != nil)
player.send_message(talisman.get_message(player.position)) player.send_message(talisman.get_message(player.position))
ctx.break_handler_chain message.terminate
end end
end end
+8 -8
View File
@@ -62,7 +62,7 @@ on :login do |event, player|
end end
# Intercepts the SecondObjectAction message to support left-click access to the altar when wielding the correct tiara. # Intercepts the SecondObjectAction message to support left-click access to the altar when wielding the correct tiara.
on :message, :second_object_action do |ctx, player, message| on :message, :second_object_action do |player, message|
object_id = message.id object_id = message.id
tiara = TIARAS_BY_ALTAR[object_id] tiara = TIARAS_BY_ALTAR[object_id]
next if tiara.nil? next if tiara.nil?
@@ -73,37 +73,37 @@ on :message, :second_object_action do |ctx, player, message|
altar = ENTRANCE_ALTARS[tiara.altar] altar = ENTRANCE_ALTARS[tiara.altar]
player.start_action(TeleportAction.new(player, message.position, 2, altar.entrance_position)) unless altar.nil? player.start_action(TeleportAction.new(player, message.position, 2, altar.entrance_position)) unless altar.nil?
ctx.break_handler_chain message.terminate
end end
end end
# Intercepts the SecondItemAction message to allow for config sending. # Intercepts the SecondItemAction message to allow for config sending.
on :message, :second_item_option do |ctx, player, message| on :message, :second_item_option do |player, message|
tiara = TIARAS_BY_ID[message.id] tiara = TIARAS_BY_ID[message.id]
unless tiara.nil? unless tiara.nil?
tiara.send_config(player) tiara.send_config(player)
ctx.break_handler_chain message.terminate
end end
end end
# Intercepts the FirstItemAction message to allow for config sending. # Intercepts the FirstItemAction message to allow for config sending.
on :message, :first_item_action do |ctx, player, message| on :message, :first_item_action do |player, message|
tiara = TIARAS_BY_ID[message.id] tiara = TIARAS_BY_ID[message.id]
unless tiara.nil? unless tiara.nil?
send_empty_config(player) send_empty_config(player)
ctx.break_handler_chain message.terminate
end end
end end
# Intercepts the ItemOnObject message to create the tiara. # Intercepts the ItemOnObject message to create the tiara.
on :message, :item_on_object do |ctx, player, message| on :message, :item_on_object do |player, message|
tiara= TIARAS_BY_TALISMAN[message.id]; altar = CRAFTING_ALTARS[message.object_id] tiara= TIARAS_BY_TALISMAN[message.id]; altar = CRAFTING_ALTARS[message.object_id]
return if (tiara.nil? || altar.nil?) return if (tiara.nil? || altar.nil?)
player.start_action(CreateTiaraAction.new(player, message.position, tiara, altar)) player.start_action(CreateTiaraAction.new(player, message.position, tiara, altar))
ctx.break_handler_chain message.terminate
end end
# An action lets the player create a tiara when it comes within the specified distance of a specified position. # An action lets the player create a tiara when it comes within the specified distance of a specified position.
+1 -1
View File
@@ -5,7 +5,7 @@
# #
# If you only wish to intercept a message, use the intercept method, e.g. # If you only wish to intercept a message, use the intercept method, e.g.
# #
# intercept :item_on_item, used_id, target_id, :irreversible do |ctx, player, message| # intercept :item_on_item, used_id, target_id, :irreversible do |player, message|
# # code here # # code here
# end # end
+3 -3
View File
@@ -36,11 +36,11 @@ class ItemOnItemPair
end end
# Adds a message handler to the item on item message. # Adds a message listener to the item on item message.
on :message, :item_on_item do |ctx, player, message| on :message, :item_on_item do |player, message|
used, target = message.id, message.target_id used, target = message.id, message.target_id
pair = ItemOnItemPair.new(used, target) pair = ItemOnItemPair.new(used, target)
block = ITEM_PAIRS[pair] block = ITEM_PAIRS[pair]
block.call(ctx, player, message) unless block == nil block.call(player, message) unless block == nil
end end
@@ -35,8 +35,6 @@ public final class GamePulseHandler implements Runnable {
service.pulse(); service.pulse();
} catch (Throwable reason) { } catch (Throwable reason) {
logger.log(Level.SEVERE, "Exception occured during pulse!", reason); logger.log(Level.SEVERE, "Exception occured during pulse!", reason);
} finally {
service.shutdown(false);
} }
} }
+13 -15
View File
@@ -10,13 +10,13 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apollo.Service; import org.apollo.Service;
import org.apollo.game.message.handler.MessageHandlerChainGroup; import org.apollo.game.message.MessageHandlerChainSet;
import org.apollo.game.model.World; import org.apollo.game.model.World;
import org.apollo.game.model.World.RegistrationStatus; import org.apollo.game.model.World.RegistrationStatus;
import org.apollo.game.model.area.Region; import org.apollo.game.model.area.Region;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.game.sync.ClientSynchronizer; import org.apollo.game.sync.ClientSynchronizer;
import org.apollo.io.MessageHandlerChainParser; import org.apollo.io.MessageHandlerChainSetParser;
import org.apollo.login.LoginService; import org.apollo.login.LoginService;
import org.apollo.net.session.GameSession; import org.apollo.net.session.GameSession;
import org.apollo.util.MobRepository; import org.apollo.util.MobRepository;
@@ -39,9 +39,9 @@ public final class GameService extends Service {
private static final int UNREGISTERS_PER_CYCLE = 50; private static final int UNREGISTERS_PER_CYCLE = 50;
/** /**
* The {@link MessageHandlerChainGroup}. * The {@link MessageHandlerChainSet}.
*/ */
private MessageHandlerChainGroup chainGroup; private MessageHandlerChainSet messageHandlerChainSet;
/** /**
* A queue of players to remove. * A queue of players to remove.
@@ -51,8 +51,7 @@ public final class GameService extends Service {
/** /**
* The scheduled executor service. * The scheduled executor service.
*/ */
private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory( private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("GameService"));
"GameService"));
/** /**
* The {@link ClientSynchronizer}. * The {@link ClientSynchronizer}.
@@ -82,12 +81,12 @@ public final class GameService extends Service {
} }
/** /**
* Gets the message handler chains. * Gets the MessageHandlerChainSet
* *
* @return The message handler chains. * @return The set of MessageHandlerChain's.
*/ */
public MessageHandlerChainGroup getMessageHandlerChains() { public MessageHandlerChainSet getMessageHandlerChainSet() {
return chainGroup; return messageHandlerChainSet;
} }
/** /**
@@ -101,7 +100,7 @@ public final class GameService extends Service {
for (Player player : players) { for (Player player : players) {
GameSession session = player.getSession(); GameSession session = player.getSession();
if (session != null) { if (session != null) {
session.handlePendingMessages(chainGroup); session.handlePendingMessages(messageHandlerChainSet);
} }
} }
@@ -143,8 +142,7 @@ public final class GameService extends Service {
@Override @Override
public void start() { public void start() {
scheduledExecutor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY, GameConstants.PULSE_DELAY, scheduledExecutor.scheduleAtFixedRate(new GamePulseHandler(this), GameConstants.PULSE_DELAY, GameConstants.PULSE_DELAY, TimeUnit.MILLISECONDS);
TimeUnit.MILLISECONDS);
} }
/** /**
@@ -181,8 +179,8 @@ public final class GameService extends Service {
*/ */
private void init() throws IOException, SAXException, ReflectiveOperationException { private void init() throws IOException, SAXException, ReflectiveOperationException {
try (InputStream input = new FileInputStream("data/messages.xml")) { try (InputStream input = new FileInputStream("data/messages.xml")) {
MessageHandlerChainParser chainGroupParser = new MessageHandlerChainParser(input); MessageHandlerChainSetParser chainSetParser = new MessageHandlerChainSetParser(input);
chainGroup = chainGroupParser.parse(world); messageHandlerChainSet = chainSetParser.parse(world);
} }
try (InputStream input = new FileInputStream("data/synchronizer.xml")) { try (InputStream input = new FileInputStream("data/synchronizer.xml")) {
+22
View File
@@ -4,7 +4,29 @@ package org.apollo.game.message;
* A message sent by the client that can be intercepted. * A message sent by the client that can be intercepted.
* *
* @author Graham * @author Graham
* @author Major
*/ */
public abstract class Message { public abstract class Message {
/**
* Indicates whether or not the Message chain has been terminated.
*/
private boolean terminated;
/**
* Terminates the Message chain.
*/
public final void terminate() {
terminated = true;
}
/**
* Returns whether or not the Message chain has been terminated.
*
* @return {@code true} if the Message chain has been terminated, otherwise {@code false}.
*/
public final boolean terminated() {
return terminated;
}
} }
@@ -1,14 +1,14 @@
package org.apollo.game.message.handler; package org.apollo.game.message;
import org.apollo.game.message.Message;
import org.apollo.game.model.World; import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
/** /**
* Handles messages received from the client. * Listens for {@link Message}s received from the client.
* *
* @author Graham * @author Graham
* @param <M> The type of message handled by this class. * @author Ryley
* @param <M> The type of Message this class is listening for.
*/ */
public abstract class MessageHandler<M extends Message> { public abstract class MessageHandler<M extends Message> {
@@ -18,7 +18,7 @@ public abstract class MessageHandler<M extends Message> {
protected final World world; protected final World world;
/** /**
* Creates the MessageHandler. * Creates the MessageListener.
* *
* @param world The {@link World} the {@link Message} occurred in. * @param world The {@link World} the {@link Message} occurred in.
*/ */
@@ -27,12 +27,11 @@ public abstract class MessageHandler<M extends Message> {
} }
/** /**
* Handles a message. * Handles the Message that was received.
* *
* @param ctx The context. * @param player The player to handle the Message for.
* @param player The player. * @param message The Message.
* @param message The message.
*/ */
public abstract void handle(MessageHandlerContext ctx, Player player, M message); public abstract void handle(Player player, M message);
} }
@@ -0,0 +1,72 @@
package org.apollo.game.message;
import java.util.ArrayList;
import java.util.List;
import org.apollo.game.model.entity.Player;
import com.google.common.base.MoreObjects;
/**
* A chain of {@link MessageHandler}s
*
* @author Graham
* @author Ryley
* @param <M> The Message type this chain represents.
*/
public final class MessageHandlerChain<M extends Message> {
/**
* The handlers.
*/
private final List<MessageHandler<M>> handlers = new ArrayList<>();
/**
* The Class type of this chain.
*/
private final Class<M> type;
/**
* Constructs a new {@link MessageHandlerChain}.
*
* @param type The Class type of this chain.
*/
public MessageHandlerChain(Class<M> type) {
this.type = type;
}
/**
* Adds the specified {@link MessageHandler} to this chain.
*
* @param handler The MessageHandler.
*/
public void addHandler(MessageHandler<M> handler) {
handlers.add(handler);
}
/**
* Notifies each {@link MessageHandler} in this chain that a {@link Message} has been received.
*
* @param player The Player to handle this message for.
* @param message The Message.
* @return {@code true} if and only if the Message propagated down the chain without being terminated, otherwise
* {@code false}.
*/
public boolean notify(Player player, M message) {
for (MessageHandler<M> handler : handlers) {
handler.handle(player, message);
if (message.terminated()) {
return false;
}
}
return true;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).add("type", type).add("handlers", handlers).toString();
}
}
@@ -0,0 +1,47 @@
package org.apollo.game.message;
import java.util.HashMap;
import java.util.Map;
import org.apollo.game.model.entity.Player;
/**
* A group of {@link MessageHandlerChain}s classified by the {@link Message} type.
*
* @author Graham
* @author Ryley
* @author Major
*/
public final class MessageHandlerChainSet {
/**
* The {@link Map} of Message types to {@link MessageHandlerChain}s
*/
private final Map<Class<? extends Message>, MessageHandlerChain<? extends Message>> chains = new HashMap<>();
/**
* Notifies the appropriate {@link MessageHandlerChain} that a {@link Message} has been received.
*
* @param message The Message.
* @return {@code true} if the Message propagated down the chain without being terminated or if the chain for the
* Message was not found, otherwise {@code false}.
*/
public <M extends Message> boolean notify(Player player, M message) {
@SuppressWarnings("unchecked")
MessageHandlerChain<M> chain = (MessageHandlerChain<M>) chains.get(message.getClass());
return (chain == null) || chain.notify(player, message);
}
/**
* Places the {@link MessageHandlerChain} into this set.
*
* @param clazz The {@link Class} to associate the MessageHandlerChain with.
* @param handler The MessageHandlerChain.
*/
@SuppressWarnings("unchecked")
public <M extends Message> void putHandler(Class<M> clazz, MessageHandler<? extends Message> handler) {
MessageHandlerChain<M> chain = (MessageHandlerChain<M>) chains.computeIfAbsent(clazz, MessageHandlerChain::new);
chain.addHandler((MessageHandler<M>) handler);
}
}
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -33,7 +32,7 @@ public final class BankButtonMessageHandler extends MessageHandler<ButtonMessage
private static final int WITHDRAW_AS_NOTE = 5386; private static final int WITHDRAW_AS_NOTE = 5386;
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ButtonMessage message) { public void handle(Player player, ButtonMessage message) {
if (message.getWidgetId() == WITHDRAW_AS_ITEM) { if (message.getWidgetId() == WITHDRAW_AS_ITEM) {
player.setWithdrawingNotes(false); player.setWithdrawingNotes(false);
} else if (message.getWidgetId() == WITHDRAW_AS_NOTE) { } else if (message.getWidgetId() == WITHDRAW_AS_NOTE) {
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -52,12 +51,12 @@ public final class BankMessageHandler extends MessageHandler<ItemActionMessage>
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemActionMessage message) { public void handle(Player player, ItemActionMessage message) {
if (player.getInterfaceSet().contains(BankConstants.BANK_WINDOW_ID)) { if (player.getInterfaceSet().contains(BankConstants.BANK_WINDOW_ID)) {
if (message.getInterfaceId() == BankConstants.SIDEBAR_INVENTORY_ID) { if (message.getInterfaceId() == BankConstants.SIDEBAR_INVENTORY_ID) {
deposit(ctx, player, message); deposit(player, message);
} else if (message.getInterfaceId() == BankConstants.BANK_INVENTORY_ID) { } else if (message.getInterfaceId() == BankConstants.BANK_INVENTORY_ID) {
withdraw(ctx, player, message); withdraw(player, message);
} }
} }
} }
@@ -65,36 +64,34 @@ public final class BankMessageHandler extends MessageHandler<ItemActionMessage>
/** /**
* Handles a deposit action. * Handles a deposit action.
* *
* @param ctx The message handler context.
* @param player The player. * @param player The player.
* @param message The message. * @param message The message.
*/ */
private void deposit(MessageHandlerContext ctx, Player player, ItemActionMessage message) { private void deposit(Player player, ItemActionMessage message) {
int amount = optionToAmount(message.getOption()); int amount = optionToAmount(message.getOption());
if (amount == -1) { if (amount == -1) {
EnterAmountListener listener = new BankDepositEnterAmountListener(player, message.getSlot(), message.getId()); EnterAmountListener listener = new BankDepositEnterAmountListener(player, message.getSlot(), message.getId());
player.getInterfaceSet().openEnterAmountDialogue(listener); player.getInterfaceSet().openEnterAmountDialogue(listener);
} else if (!BankUtils.deposit(player, message.getSlot(), message.getId(), amount)) { } else if (!BankUtils.deposit(player, message.getSlot(), message.getId(), amount)) {
ctx.breakHandlerChain(); message.terminate();
} }
} }
/** /**
* Handles a withdraw action. * Handles a withdraw action.
* *
* @param ctx The message handler context.
* @param player The player. * @param player The player.
* @param message The message. * @param message The message.
*/ */
private void withdraw(MessageHandlerContext ctx, Player player, ItemActionMessage message) { private void withdraw(Player player, ItemActionMessage message) {
int amount = optionToAmount(message.getOption()); int amount = optionToAmount(message.getOption());
if (amount == -1) { if (amount == -1) {
EnterAmountListener listener = new BankWithdrawEnterAmountListener(player, message.getSlot(), message.getId()); EnterAmountListener listener = new BankWithdrawEnterAmountListener(player, message.getSlot(), message.getId());
player.getInterfaceSet().openEnterAmountDialogue(listener); player.getInterfaceSet().openEnterAmountDialogue(listener);
} else if (!BankUtils.withdraw(player, message.getSlot(), message.getId(), amount)) { } else if (!BankUtils.withdraw(player, message.getSlot(), message.getId(), amount)) {
ctx.breakHandlerChain(); message.terminate();
} }
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -24,7 +23,7 @@ public final class ChatMessageHandler extends MessageHandler<ChatMessage> {
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ChatMessage message) { public void handle(Player player, ChatMessage message) {
player.getBlockSet().add(SynchronizationBlock.createChatBlock(player, message)); player.getBlockSet().add(SynchronizationBlock.createChatBlock(player, message));
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -23,11 +22,11 @@ public final class ChatVerificationHandler extends MessageHandler<ChatMessage> {
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ChatMessage message) { public void handle(Player player, ChatMessage message) {
int color = message.getTextColor(); int color = message.getTextColor();
int effects = message.getTextEffects(); int effects = message.getTextEffects();
if (color < 0 || color > 11 || effects < 0 || effects > 5) { if (color < 0 || color > 11 || effects < 0 || effects > 5) {
ctx.breakHandlerChain(); message.terminate();
} }
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -23,7 +22,7 @@ public final class ClosedInterfaceMessageHandler extends MessageHandler<ClosedIn
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ClosedInterfaceMessage message) { public void handle(Player player, ClosedInterfaceMessage message) {
player.getInterfaceSet().interfaceClosed(); player.getInterfaceSet().interfaceClosed();
} }
@@ -1,9 +1,8 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.command.Command; import org.apollo.game.command.Command;
import org.apollo.game.message.Message; import org.apollo.game.message.Message;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.CommandMessage; import org.apollo.game.message.impl.CommandMessage;
import org.apollo.game.model.World; import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -25,7 +24,7 @@ public final class CommandMessageHandler extends MessageHandler<CommandMessage>
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, CommandMessage message) { public void handle(Player player, CommandMessage message) {
String[] components = message.getCommand().split(" "); String[] components = message.getCommand().split(" ");
String name = components[0]; String name = components[0];
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -25,12 +24,12 @@ public final class DialogueButtonHandler extends MessageHandler<ButtonMessage> {
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ButtonMessage message) { public void handle(Player player, ButtonMessage message) {
if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) { if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) {
boolean terminate = player.getInterfaceSet().buttonClicked(message.getWidgetId()); boolean terminate = player.getInterfaceSet().buttonClicked(message.getWidgetId());
if (terminate) { if (terminate) {
ctx.breakHandlerChain(); message.terminate();
} }
} }
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -24,7 +23,7 @@ public final class DialogueContinueMessageHandler extends MessageHandler<Dialogu
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, DialogueContinueMessage message) { public void handle(Player player, DialogueContinueMessage message) {
if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) { if (player.getInterfaceSet().contains(InterfaceType.DIALOGUE)) {
player.getInterfaceSet().continueRequested(); player.getInterfaceSet().continueRequested();
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -23,7 +22,7 @@ public final class EnteredAmountMessageHandler extends MessageHandler<EnteredAmo
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, EnteredAmountMessage message) { public void handle(Player player, EnteredAmountMessage message) {
player.getInterfaceSet().enteredAmount(message.getAmount()); player.getInterfaceSet().enteredAmount(message.getAmount());
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -37,7 +36,7 @@ public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> {
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemOptionMessage message) { public void handle(Player player, ItemOptionMessage message) {
if (message.getOption() != EQUIP_OPTION || message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID) { if (message.getOption() != EQUIP_OPTION || message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID) {
return; return;
} }
@@ -60,7 +59,7 @@ public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> {
String article = LanguageUtil.getIndefiniteArticle(name); String article = LanguageUtil.getIndefiniteArticle(name);
player.sendMessage("You need " + article + " " + name + " level of " + requirement + " to equip this item."); player.sendMessage("You need " + article + " " + name + " level of " + requirement + " to equip this item.");
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
} }
@@ -78,7 +77,7 @@ public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> {
if (definition.isTwoHanded()) { if (definition.isTwoHanded()) {
int slotsRequired = weapon != null && shield != null ? 1 : 0; int slotsRequired = weapon != null && shield != null ? 1 : 0;
if (inventory.freeSlots() < slotsRequired) { if (inventory.freeSlots() < slotsRequired) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -27,7 +26,7 @@ public final class ItemOnItemVerificationHandler extends MessageHandler<ItemOnIt
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemOnItemMessage message) { public void handle(Player player, ItemOnItemMessage message) {
Inventory inventory; Inventory inventory;
switch (message.getInterfaceId()) { switch (message.getInterfaceId()) {
@@ -42,19 +41,19 @@ public final class ItemOnItemVerificationHandler extends MessageHandler<ItemOnIt
inventory = player.getBank(); inventory = player.getBank();
break; break;
default: default:
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
int slot = message.getTargetSlot(); int slot = message.getTargetSlot();
if (slot < 0 || slot >= inventory.capacity()) { if (slot < 0 || slot >= inventory.capacity()) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
Item item = inventory.get(slot); Item item = inventory.get(slot);
if (item == null || item.getId() != message.getTargetId()) { if (item == null || item.getId() != message.getTargetId()) {
ctx.breakHandlerChain(); message.terminate();
} }
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -27,10 +26,10 @@ public final class ItemOnObjectVerificationHandler extends MessageHandler<ItemOn
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemOnObjectMessage message) { public void handle(Player player, ItemOnObjectMessage message) {
if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID if (message.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID
&& message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) { && message.getInterfaceId() != BankConstants.SIDEBAR_INVENTORY_ID) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
@@ -38,13 +37,13 @@ public final class ItemOnObjectVerificationHandler extends MessageHandler<ItemOn
int slot = message.getSlot(); int slot = message.getSlot();
if (slot < 0 || slot >= inventory.capacity()) { if (slot < 0 || slot >= inventory.capacity()) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
Item item = inventory.get(slot); Item item = inventory.get(slot);
if (item == null || item.getId() != message.getId()) { if (item == null || item.getId() != message.getId()) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
} }
@@ -1,10 +1,9 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -72,10 +71,10 @@ public final class ItemVerificationHandler extends MessageHandler<InventoryItemM
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, InventoryItemMessage message) { public void handle(Player player, InventoryItemMessage message) {
InventorySupplier supplier = inventories.get(message.getInterfaceId()); InventorySupplier supplier = inventories.get(message.getInterfaceId());
if (supplier == null) { if (supplier == null) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
@@ -83,13 +82,13 @@ public final class ItemVerificationHandler extends MessageHandler<InventoryItemM
int slot = message.getSlot(); int slot = message.getSlot();
if (slot < 0 || slot >= inventory.capacity()) { if (slot < 0 || slot >= inventory.capacity()) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
Item item = inventory.get(slot); Item item = inventory.get(slot);
if (item == null || item.getId() != message.getId()) { if (item == null || item.getId() != message.getId()) {
ctx.breakHandlerChain(); message.terminate();
} }
} }
@@ -1,62 +0,0 @@
package org.apollo.game.message.handler;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import org.apollo.game.message.Message;
import org.apollo.game.model.entity.Player;
/**
* A chain of message handlers.
*
* @author Graham
* @author Ryley
* @param <M> The type of message handled by this chain.
*/
public final class MessageHandlerChain<M extends Message> {
/**
* The handlers.
*/
private final Deque<MessageHandler<M>> handlers;
/**
* Creates the message handler chain.
*
* @param handlers The handlers.
*/
@SafeVarargs
public MessageHandlerChain(MessageHandler<M>... handlers) {
this.handlers = new ArrayDeque<>(Arrays.asList(handlers));
}
/**
* Dynamically adds a message handler to the end of the chain.
*
* @param handler The handler.
*/
public void addLast(MessageHandler<M> handler) {
handlers.addLast(handler);
}
/**
* Handles the message, passing it down the chain until the chain is broken or the message reaches the end of the
* chain.
*
* @param player The player.
* @param message The message.
*/
public void handle(Player player, M message) {
MessageHandlerContext context = new MessageHandlerContext();
for (MessageHandler<M> handler : handlers) {
handler.handle(context, player, message);
if (context.isBroken()) {
break;
}
}
}
}
@@ -1,49 +0,0 @@
package org.apollo.game.message.handler;
import java.util.Map;
import org.apollo.game.message.Message;
/**
* A group of {@link MessageHandlerChain}s classified by the {@link Message} type.
*
* @author Graham
*/
public final class MessageHandlerChainGroup {
/**
* The map of message classes to message handler chains.
*/
private final Map<Class<? extends Message>, MessageHandlerChain<?>> chains;
/**
* Creates the message handler chain group.
*
* @param chains The chains map.
*/
public MessageHandlerChainGroup(Map<Class<? extends Message>, MessageHandlerChain<?>> chains) {
this.chains = chains;
}
/**
* Gets a {@link MessageHandlerChain} from this group.
*
* @param clazz The message class.
* @return The {@link MessageHandlerChain} if one was found, {@code null} otherwise.
*/
@SuppressWarnings("unchecked")
public <M extends Message> MessageHandlerChain<M> getChain(Class<M> clazz) {
return (MessageHandlerChain<M>) chains.get(clazz);
}
/**
* Registers a {@link MessageHandlerChain} associated with the specified {@link Class} to this group.
*
* @param clazz The message class.
* @param chain The message handler chain.
*/
public <M extends Message> void register(Class<M> clazz, MessageHandlerChain<M> chain) {
chains.put(clazz, chain);
}
}
@@ -1,32 +0,0 @@
package org.apollo.game.message.handler;
/**
* Provides operations specific to a {@link MessageHandler} in a {@link MessageHandlerChain}.
*
* @author Graham
* @author Ryley
*/
public final class MessageHandlerContext {
/**
* Denotes whether or not this handler chain is broken.
*/
private boolean broken;
/**
* Breaks the handler chain.
*/
public void breakHandlerChain() {
broken = true;
}
/**
* Returns whether or not this handler chain is broken.
*
* @return {@code true} if this handler chain is broken, otherwise {@code false}.
*/
public boolean isBroken() {
return broken;
}
}
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.NpcActionMessage; import org.apollo.game.message.impl.NpcActionMessage;
import org.apollo.game.model.World; import org.apollo.game.model.World;
import org.apollo.game.model.def.NpcDefinition; import org.apollo.game.model.def.NpcDefinition;
@@ -27,12 +26,12 @@ public final class NpcActionVerificationHandler extends MessageHandler<NpcAction
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, NpcActionMessage message) { public void handle(Player player, NpcActionMessage message) {
int index = message.getIndex(); int index = message.getIndex();
MobRepository<Npc> repository = world.getNpcRepository(); MobRepository<Npc> repository = world.getNpcRepository();
if (index < 0 || index >= repository.capacity()) { if (index < 0 || index >= repository.capacity()) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
@@ -40,13 +39,13 @@ public final class NpcActionVerificationHandler extends MessageHandler<NpcAction
if (npc == null || !player.getPosition().isWithinDistance(npc.getPosition(), player.getViewingDistance() + 1)) { if (npc == null || !player.getPosition().isWithinDistance(npc.getPosition(), player.getViewingDistance() + 1)) {
// +1 in case it was decremented after the player clicked the action. // +1 in case it was decremented after the player clicked the action.
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
NpcDefinition definition = npc.getDefinition(); NpcDefinition definition = npc.getDefinition();
if (message.getOption() >= definition.getInteractions().length) { if (message.getOption() >= definition.getInteractions().length) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
} }
@@ -1,10 +1,9 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.ObjectActionMessage; 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;
@@ -42,10 +41,10 @@ public final class ObjectActionVerificationHandler extends MessageHandler<Object
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ObjectActionMessage message) { public void handle(Player player, ObjectActionMessage message) {
int id = message.getId(); int id = message.getId();
if (id < 0 || id >= ObjectDefinition.count()) { if (id < 0 || id >= ObjectDefinition.count()) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
@@ -54,13 +53,13 @@ public final class ObjectActionVerificationHandler extends MessageHandler<Object
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)) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
ObjectDefinition definition = ObjectDefinition.lookup(id); ObjectDefinition definition = ObjectDefinition.lookup(id);
if (message.getOption() >= definition.getMenuActions().length) { if (message.getOption() >= definition.getMenuActions().length) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerContext;
import org.apollo.game.message.impl.PlayerActionMessage; import org.apollo.game.message.impl.PlayerActionMessage;
import org.apollo.game.model.World; import org.apollo.game.model.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -24,19 +23,19 @@ public final class PlayerActionVerificationHandler extends MessageHandler<Player
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, PlayerActionMessage message) { public void handle(Player player, PlayerActionMessage message) {
int index = message.getIndex(); int index = message.getIndex();
MobRepository<Player> repository = world.getPlayerRepository(); MobRepository<Player> repository = world.getPlayerRepository();
if (index < 0 || index >= repository.capacity()) { if (index < 0 || index >= repository.capacity()) {
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
Player other = repository.get(index); Player other = repository.get(index);
if (other == null || !player.getPosition().isWithinDistance(other.getPosition(), player.getViewingDistance() + 1)) { if (other == null || !player.getPosition().isWithinDistance(other.getPosition(), player.getViewingDistance() + 1)) {
// +1 in case it was decremented after the player clicked the action. // +1 in case it was decremented after the player clicked the action.
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -24,7 +23,7 @@ public final class PlayerDesignMessageHandler extends MessageHandler<PlayerDesig
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, PlayerDesignMessage message) { public void handle(Player player, PlayerDesignMessage message) {
player.setAppearance(message.getAppearance()); player.setAppearance(message.getAppearance());
player.send(new CloseInterfaceMessage()); player.send(new CloseInterfaceMessage());
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -25,9 +24,9 @@ public final class PlayerDesignVerificationHandler extends MessageHandler<Player
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, PlayerDesignMessage message) { public void handle(Player player, PlayerDesignMessage message) {
if (!valid(message.getAppearance())) { if (!valid(message.getAppearance())) {
ctx.breakHandlerChain(); message.terminate();
} }
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -27,7 +26,7 @@ public final class RemoveEquippedItemHandler extends MessageHandler<ItemActionMe
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, ItemActionMessage message) { public void handle(Player player, ItemActionMessage message) {
if (message.getOption() == 1 && message.getInterfaceId() == SynchronizationInventoryListener.EQUIPMENT_ID) { if (message.getOption() == 1 && message.getInterfaceId() == SynchronizationInventoryListener.EQUIPMENT_ID) {
Inventory inventory = player.getInventory(); Inventory inventory = player.getInventory();
Inventory equipment = player.getEquipment(); Inventory equipment = player.getEquipment();
@@ -38,7 +37,7 @@ public final class RemoveEquippedItemHandler extends MessageHandler<ItemActionMe
if (inventory.freeSlots() == 0 && !item.getDefinition().isStackable()) { if (inventory.freeSlots() == 0 && !item.getDefinition().isStackable()) {
inventory.forceCapacityExceeded(); inventory.forceCapacityExceeded();
ctx.breakHandlerChain(); message.terminate();
return; return;
} }
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
@@ -27,7 +26,7 @@ public final class SwitchItemMessageHandler extends MessageHandler<SwitchItemMes
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, SwitchItemMessage message) { public void handle(Player player, SwitchItemMessage message) {
Inventory inventory; Inventory inventory;
boolean insertPermitted = false; boolean insertPermitted = false;
@@ -1,7 +1,6 @@
package org.apollo.game.message.handler.impl; package org.apollo.game.message.handler;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
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.World;
@@ -25,7 +24,7 @@ public final class WalkMessageHandler extends MessageHandler<WalkMessage> {
} }
@Override @Override
public void handle(MessageHandlerContext ctx, Player player, WalkMessage message) { public void handle(Player player, WalkMessage message) {
WalkingQueue queue = player.getWalkingQueue(); WalkingQueue queue = player.getWalkingQueue();
Position[] steps = message.getSteps(); Position[] steps = message.getSteps();
@@ -1,4 +0,0 @@
/**
* Contains message handler implementations.
*/
package org.apollo.game.message.handler.impl;
@@ -1,4 +1,4 @@
/** /**
* Contains the base classes for message handling. * Contains message handler implementations.
*/ */
package org.apollo.game.message.handler; package org.apollo.game.message.handler;
+9 -9
View File
@@ -46,6 +46,7 @@ import org.apollo.game.model.skill.SynchronizationSkillListener;
import org.apollo.game.sync.block.SynchronizationBlock; import org.apollo.game.sync.block.SynchronizationBlock;
import org.apollo.net.session.GameSession; import org.apollo.net.session.GameSession;
import org.apollo.security.PlayerCredentials; import org.apollo.security.PlayerCredentials;
import org.apollo.util.CollectionUtil;
import org.apollo.util.Point; import org.apollo.util.Point;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
@@ -668,17 +669,16 @@ public final class Player extends Mob {
* @param message The message.. * @param message The message..
*/ */
public void send(Message message) { public void send(Message message) {
if (isActive()) { if (!isActive()) {
if (!queuedMessages.isEmpty()) {
for (Message queuedMessage : queuedMessages) {
session.dispatchMessage(queuedMessage);
}
queuedMessages.clear();
}
session.dispatchMessage(message);
} else {
queuedMessages.add(message); queuedMessages.add(message);
return;
} }
if (!queuedMessages.isEmpty()) {
CollectionUtil.pollAll(queuedMessages, session::dispatchMessage);
}
session.dispatchMessage(message);
} }
/** /**
@@ -63,4 +63,5 @@ final class EventListenerChain<E extends Event> {
public String toString() { public String toString() {
return MoreObjects.toStringHelper(this).add("type", type).add("listeners", listeners).toString(); return MoreObjects.toStringHelper(this).add("type", type).add("listeners", listeners).toString();
} }
} }
@@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.apollo.game.message.MessageHandlerChain;
import org.apollo.game.message.impl.CloseInterfaceMessage; import org.apollo.game.message.impl.CloseInterfaceMessage;
import org.apollo.game.message.impl.EnterAmountMessage; import org.apollo.game.message.impl.EnterAmountMessage;
import org.apollo.game.message.impl.OpenDialogueInterfaceMessage; import org.apollo.game.message.impl.OpenDialogueInterfaceMessage;
@@ -75,7 +76,7 @@ public final class InterfaceSet {
* Called when the player has clicked the specified button. Notifies the current dialogue listener. * Called when the player has clicked the specified button. Notifies the current dialogue listener.
* *
* @param button The button. * @param button The button.
* @return {@code true} if the message handler chain should be broken. * @return {@code true} if the {@link MessageHandlerChain} should be broken.
*/ */
public boolean buttonClicked(int button) { public boolean buttonClicked(int button) {
return dialogueListener.isPresent() && dialogueListener.get().buttonClicked(button); return dialogueListener.isPresent() && dialogueListener.get().buttonClicked(button);
@@ -1,5 +1,6 @@
package org.apollo.game.model.inter.dialogue; package org.apollo.game.model.inter.dialogue;
import org.apollo.game.message.MessageHandlerChain;
import org.apollo.game.model.inter.InterfaceListener; import org.apollo.game.model.inter.InterfaceListener;
/** /**
@@ -17,7 +18,7 @@ public interface DialogueListener extends InterfaceListener {
* </p> * </p>
* *
* @param button The button interface id. * @param button The button interface id.
* @return {@code true} if the message handler chain should be broken, {@code false} if it should be continued. * @return {@code true} if the {@link MessageHandlerChain} should be broken, {@code false} if it should be continued.
*/ */
public boolean buttonClicked(int button); public boolean buttonClicked(int button);
+12 -13
View File
@@ -6,6 +6,8 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import org.apollo.util.CollectionUtil;
/** /**
* A class which manages {@link ScheduledTask}s. * A class which manages {@link ScheduledTask}s.
* *
@@ -14,29 +16,26 @@ import java.util.Queue;
public final class Scheduler { public final class Scheduler {
/** /**
* A queue of new tasks that should be added. * An {@link ArrayDeque} of tasks that are pending execution.
*/ */
private Queue<ScheduledTask> newTasks = new ArrayDeque<>(); private final Queue<ScheduledTask> pendingTasks = new ArrayDeque<>();
/** /**
* A list of currently active tasks. * An {@link ArrayList} of currently active tasks.
*/ */
private List<ScheduledTask> tasks = new ArrayList<>(); private final List<ScheduledTask> tasks = new ArrayList<>();
/** /**
* Called every pulse: executes tasks that are still pending, adds new tasks and stops old tasks. * Called every pulse: executes tasks that are still pending, adds new tasks and stops old tasks.
*/ */
public void pulse() { public void pulse() {
ScheduledTask task; CollectionUtil.pollAll(pendingTasks, tasks::add);
while ((task = newTasks.poll()) != null) {
tasks.add(task);
}
for (Iterator<ScheduledTask> it = tasks.iterator(); it.hasNext();) { for (Iterator<ScheduledTask> iterator = tasks.iterator(); iterator.hasNext();) {
task = it.next(); ScheduledTask task = iterator.next();
task.pulse(); task.pulse();
if (!task.isRunning()) { if (task.isRunning()) {
it.remove(); iterator.remove();
} }
} }
} }
@@ -48,7 +47,7 @@ public final class Scheduler {
* @return {@code true} if the task was added successfully. * @return {@code true} if the task was added successfully.
*/ */
public boolean schedule(ScheduledTask task) { public boolean schedule(ScheduledTask task) {
return newTasks.add(task); return pendingTasks.add(task);
} }
} }
@@ -2,26 +2,22 @@ package org.apollo.io;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apollo.game.message.Message; import org.apollo.game.message.Message;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerChain; import org.apollo.game.message.MessageHandlerChain;
import org.apollo.game.message.handler.MessageHandlerChainGroup; import org.apollo.game.message.MessageHandlerChainSet;
import org.apollo.game.model.World; 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;
/** /**
* A class that parses the {@code messages.xml} file to produce {@link MessageHandlerChainGroup}s. * A class that parses the {@code messages.xml} file to produce {@link MessageHandlerChainSet}s.
* *
* @author Graham * @author Graham
*/ */
public final class MessageHandlerChainParser { public final class MessageHandlerChainSetParser {
/** /**
* The source {@link InputStream}. * The source {@link InputStream}.
@@ -39,7 +35,7 @@ public final class MessageHandlerChainParser {
* @param is The source {@link InputStream}. * @param is The source {@link InputStream}.
* @throws SAXException If a SAX error occurs. * @throws SAXException If a SAX error occurs.
*/ */
public MessageHandlerChainParser(InputStream is) throws SAXException { public MessageHandlerChainSetParser(InputStream is) throws SAXException {
this.is = is; this.is = is;
} }
@@ -47,18 +43,18 @@ 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. * @param world The {@link World} this MessageHandlerChainGroup is for.
* @return A {@link MessageHandlerChainGroup}. * @return A {@link MessageHandlerChainSet}.
* @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 ReflectiveOperationException If a reflection error occurs. * @throws ReflectiveOperationException If a reflection error occurs.
*/ */
public MessageHandlerChainGroup parse(World world) throws IOException, SAXException, ReflectiveOperationException { public MessageHandlerChainSet parse(World world) throws IOException, SAXException, ReflectiveOperationException {
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'.");
} }
Map<Class<? extends Message>, MessageHandlerChain<?>> chains = new HashMap<>(); MessageHandlerChainSet chainSet = new MessageHandlerChainSet();
for (XmlNode message : messages) { for (XmlNode message : messages) {
if (!message.getName().equals("message")) { if (!message.getName().equals("message")) {
@@ -81,7 +77,6 @@ public final class MessageHandlerChainParser {
@SuppressWarnings("unchecked") @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<>();
for (XmlNode handlerNode : chainNode) { for (XmlNode handlerNode : chainNode) {
if (!handlerNode.getName().equals("handler")) { if (!handlerNode.getName().equals("handler")) {
@@ -94,20 +89,13 @@ public final class MessageHandlerChainParser {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Class<? extends MessageHandler<?>> handlerClass = (Class<? extends MessageHandler<?>>) Class Class<? extends MessageHandler<? extends Message>> handlerClass = (Class<? extends MessageHandler<? extends Message>>) Class.forName(handlerClassName);
.forName(handlerClassName); MessageHandler<? extends Message> handler = handlerClass.getConstructor(World.class).newInstance(world);
MessageHandler<?> handler = handlerClass.getConstructor(World.class).newInstance(world); chainSet.putHandler(messageClass, handler);
handlers.add(handler);
} }
MessageHandler<?>[] handlersArray = handlers.toArray(new MessageHandler<?>[handlers.size()]);
@SuppressWarnings({ "rawtypes", "unchecked" })
MessageHandlerChain<?> chain = new MessageHandlerChain(handlersArray);
chains.put(messageClass, chain);
} }
return new MessageHandlerChainGroup(chains); return chainSet;
} }
} }
@@ -1,7 +1,10 @@
package org.apollo.net.release.r317; package org.apollo.net.release.r317;
import org.apollo.game.message.impl.FirstNpcActionMessage; import org.apollo.game.message.impl.FirstNpcActionMessage;
import org.apollo.net.codec.game.*; import org.apollo.net.codec.game.DataOrder;
import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketReader;
import org.apollo.net.release.MessageDecoder; import org.apollo.net.release.MessageDecoder;
/** /**
@@ -1,7 +1,10 @@
package org.apollo.net.release.r317; package org.apollo.net.release.r317;
import org.apollo.game.message.impl.SecondNpcActionMessage; import org.apollo.game.message.impl.SecondNpcActionMessage;
import org.apollo.net.codec.game.*; import org.apollo.net.codec.game.DataTransformation;
import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketReader;
import org.apollo.net.release.MessageDecoder; import org.apollo.net.release.MessageDecoder;
/** /**
@@ -1,7 +1,11 @@
package org.apollo.net.release.r317; package org.apollo.net.release.r317;
import org.apollo.game.message.impl.ThirdNpcActionMessage; import org.apollo.game.message.impl.ThirdNpcActionMessage;
import org.apollo.net.codec.game.*; import org.apollo.net.codec.game.DataOrder;
import org.apollo.net.codec.game.DataTransformation;
import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketReader;
import org.apollo.net.release.MessageDecoder; import org.apollo.net.release.MessageDecoder;
/** /**
@@ -1,7 +1,10 @@
package org.apollo.net.release.r377; package org.apollo.net.release.r377;
import org.apollo.game.message.impl.FirstNpcActionMessage; import org.apollo.game.message.impl.FirstNpcActionMessage;
import org.apollo.net.codec.game.*; import org.apollo.net.codec.game.DataOrder;
import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketReader;
import org.apollo.net.release.MessageDecoder; import org.apollo.net.release.MessageDecoder;
/** /**
@@ -1,7 +1,10 @@
package org.apollo.net.release.r377; package org.apollo.net.release.r377;
import org.apollo.game.message.impl.SecondNpcActionMessage; import org.apollo.game.message.impl.SecondNpcActionMessage;
import org.apollo.net.codec.game.*; import org.apollo.net.codec.game.DataTransformation;
import org.apollo.net.codec.game.DataType;
import org.apollo.net.codec.game.GamePacket;
import org.apollo.net.codec.game.GamePacketReader;
import org.apollo.net.release.MessageDecoder; import org.apollo.net.release.MessageDecoder;
/** /**
+10 -28
View File
@@ -13,10 +13,10 @@ import org.apollo.ServerContext;
import org.apollo.game.GameConstants; import org.apollo.game.GameConstants;
import org.apollo.game.GameService; import org.apollo.game.GameService;
import org.apollo.game.message.Message; import org.apollo.game.message.Message;
import org.apollo.game.message.handler.MessageHandlerChain; import org.apollo.game.message.MessageHandlerChainSet;
import org.apollo.game.message.handler.MessageHandlerChainGroup;
import org.apollo.game.message.impl.LogoutMessage; import org.apollo.game.message.impl.LogoutMessage;
import org.apollo.game.model.entity.Player; import org.apollo.game.model.entity.Player;
import org.apollo.util.CollectionUtil;
/** /**
* A game session. * A game session.
@@ -81,34 +81,16 @@ public final class GameSession extends Session {
/** /**
* Handles pending messages for this session. * Handles pending messages for this session.
* *
* @param chainGroup The message chain group. * @param chainSet The {@link MessageHandlerChainSet}
*/ */
@SuppressWarnings("unchecked") public void handlePendingMessages(MessageHandlerChainSet chainSet) {
public void handlePendingMessages(MessageHandlerChainGroup chainGroup) { CollectionUtil.pollAll(messageQueue, message -> {
Message message; try {
while ((message = messageQueue.poll()) != null) { chainSet.notify(player, message);
// this lookup code really sucks! } catch (Exception reason) {
// TODO improve it! logger.log(Level.SEVERE, "Uncaught exception thrown while handling message: " + message, reason);
Class<? extends Message> messageType = message.getClass();
MessageHandlerChain<Message> chain = (MessageHandlerChain<Message>) chainGroup.getChain(messageType);
while (chain == null && messageType != null) {
messageType = (Class<? extends Message>) messageType.getSuperclass();
if (messageType == Message.class) {
messageType = null;
} else {
chain = (MessageHandlerChain<Message>) chainGroup.getChain(messageType);
}
} }
});
if (chain != null) {
try {
chain.handle(player, message);
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error handling message: ", ex);
}
}
}
} }
/** /**
+40
View File
@@ -0,0 +1,40 @@
package org.apollo.util;
import java.util.Collection;
import java.util.Queue;
import java.util.function.Consumer;
import com.google.common.base.Preconditions;
/**
* A utility class containing helper methods for various {@link Collection} objects.
*
* @author Ryley
*/
public final class CollectionUtil {
/**
* Polls every element within the specified {@link Queue} and performs the specified {@link Consumer} event for each
* element.
*
* @param queue The Queue to poll each element for, may not be {@code null}.
* @param consumer The Consumer event to execute for each polled element, may not be {@code null}.
*/
public static <T> void pollAll(Queue<T> queue, Consumer<T> consumer) {
Preconditions.checkNotNull(queue, "Queue may not be null");
Preconditions.checkNotNull(consumer, "Consumer may not be null");
T element;
while ((element = queue.poll()) != null) {
consumer.accept(element);
}
}
/**
* Suppresses the default public constructor to discourage normal instantiation outside of this class.
*/
private CollectionUtil() {
}
}
+7 -13
View File
@@ -3,9 +3,9 @@ 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.message.Message; import org.apollo.game.message.Message;
import org.apollo.game.message.handler.MessageHandler; import org.apollo.game.message.MessageHandler;
import org.apollo.game.message.handler.MessageHandlerChain; import org.apollo.game.message.MessageHandlerChain;
import org.apollo.game.message.handler.MessageHandlerChainGroup; import org.apollo.game.message.MessageHandlerChainSet;
/** /**
* 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
@@ -31,20 +31,14 @@ public final class PluginContext {
} }
/** /**
* Adds a {@link MessageHandler} to the end of the chain. * Adds a {@link MessageHandler} to the {@link MessageHandlerChainSet}.
* *
* @param message The message. * @param message The message.
* @param handler The handler. * @param handler The handler.
*/ */
public <M extends Message> void addLastMessageHandler(Class<M> message, MessageHandler<M> handler) { public <M extends Message> void addMessageHandler(Class<M> message, MessageHandler<M> handler) {
MessageHandlerChainGroup chains = context.getService(GameService.class).getMessageHandlerChains(); MessageHandlerChainSet chains = context.getService(GameService.class).getMessageHandlerChainSet();
MessageHandlerChain<M> chain = chains.getChain(message); chains.putHandler(message, handler);
if (chain == null) {
chain = new MessageHandlerChain<>(handler);
chains.register(message, chain);
} else {
chain.addLast(handler);
}
} }
} }
+9 -1
View File
@@ -1,6 +1,14 @@
package org.apollo.util.xml; package org.apollo.util.xml;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/** /**
* A class which represents a single node in the DOM tree, maintaining information about its children, attributes, value * A class which represents a single node in the DOM tree, maintaining information about its children, attributes, value