diff --git a/data/events.xml b/data/events.xml index fb5d7c63..5113379b 100644 --- a/data/events.xml +++ b/data/events.xml @@ -1,10 +1,4 @@ - - org.apollo.game.event.impl.PrivacyOptionEvent - - org.apollo.game.event.handler.impl.PrivacyOptionEventHandler - - org.apollo.game.event.impl.PlayerDesignEvent diff --git a/data/plugins/bootstrap.rb b/data/plugins/bootstrap.rb index a6df5f29..204ffce4 100644 --- a/data/plugins/bootstrap.rb +++ b/data/plugins/bootstrap.rb @@ -13,11 +13,14 @@ # ***************************************************************************** require 'java' -java_import 'org.apollo.game.event.handler.EventHandler' + java_import 'org.apollo.game.command.CommandListener' +java_import 'org.apollo.game.event.handler.EventHandler' +java_import 'org.apollo.game.login.LoginListener' +java_import 'org.apollo.game.login.LogoutListener' java_import 'org.apollo.game.model.Player' -java_import 'org.apollo.game.model.settings.PrivilegeLevel' java_import 'org.apollo.game.model.World' +java_import 'org.apollo.game.model.settings.PrivilegeLevel' java_import 'org.apollo.game.scheduling.ScheduledTask' # Alias the privilege levels. @@ -33,7 +36,7 @@ class String end end -# A CommandListener which executes a Proc object with two arguments: the player +# A CommandListener that executes a Proc object with two arguments: the player # and the command. class ProcCommandListener < CommandListener def initialize(rights, block) @@ -46,6 +49,30 @@ class ProcCommandListener < CommandListener end end +# A LoginListener that executes a Proc object with the player argument. +class ProcLoginListener < 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. +class ProcLogoutListener < LogoutListener + def initialize(block) + super() + @block = block + end + + def execute(player) + @block.call player + end +end + # An EventHandler which executes a Proc object with three arguments: the chain # context, the player and the event. class ProcEventHandler < EventHandler @@ -114,6 +141,8 @@ def on(type, *args, &block) when :command then on_command(args, block) when :event then on_event(args, block) when :button then on_button(args, block) + when :login then on_login(args, block) + when :logout then on_logout(args, block) else raise "unknown event type" end end @@ -125,7 +154,7 @@ def on_button(args, proc) id = args[0].to_i on :event, :button do |ctx, player, event| - proc.call(player) if event.widget_id == id + proc.call player if event.widget_id == id end end @@ -151,4 +180,14 @@ def on_command(args, proc) rights = args.length == 2 ? args[1] : RIGHTS_STANDARD $ctx.add_command_listener(args[0].to_s, ProcCommandListener.new(rights, proc)) +end + +# Defines an action to be taken upon login. +def on_login(args, proc) + $ctx.add_login_listener ProcLoginListener.new(proc) +end + +# Defines an action to be taken upon logout. +def on_logout(args, proc) + $ctx.add_logout_listener ProcLogoutListener.new(proc) end \ No newline at end of file diff --git a/data/plugins/chat-privacy/plugin.xml b/data/plugins/chat-privacy/plugin.xml new file mode 100644 index 00000000..1df608af --- /dev/null +++ b/data/plugins/chat-privacy/plugin.xml @@ -0,0 +1,16 @@ + + + chat-privacy + 1 + Chat privacy + Adds chat privacy support. + + Major + + + + + + private-messaging + + \ No newline at end of file diff --git a/data/plugins/chat-privacy/privacy.rb b/data/plugins/chat-privacy/privacy.rb new file mode 100644 index 00000000..9f56b94a --- /dev/null +++ b/data/plugins/chat-privacy/privacy.rb @@ -0,0 +1,11 @@ +require 'java' + +java_import 'org.apollo.game.model.settings.PrivacyState' + +on :event, :privacy_option do |ctx, player, event| + player.chat_privacy = event.chat_privacy + player.friend_privacy = event.friend_privacy + player.trade_privacy = event.trade_privacy + + update_friends(player, event.friend_privacy == PrivacyState::OFF ? 0 : player.world_id) +end \ No newline at end of file diff --git a/data/plugins/private-messaging/friend.rb b/data/plugins/private-messaging/friend.rb new file mode 100644 index 00000000..12b164f7 --- /dev/null +++ b/data/plugins/private-messaging/friend.rb @@ -0,0 +1,82 @@ +require 'java' + +java_import 'org.apollo.game.event.impl.FriendServerStatusEvent' +java_import 'org.apollo.game.event.impl.SendFriendEvent' +java_import 'org.apollo.game.model.Player' +java_import 'org.apollo.game.model.World' +java_import 'org.apollo.game.model.settings.ServerStatus' +java_import 'org.apollo.game.model.settings.PrivacyState' + + +# Processes an add friend event, updating the logged-in status of the player (and the person they added) if necessary. +on :event, :add_friend do |ctx, player, event| + friend_username = event.username + player_username = player.username + + player.add_friend(friend_username) + friend = World.world.get_player(friend_username) + + if (friend == nil) # the friend the player added is offline + player.send(SendFriendEvent.new(friend_username, 0)) + elsif (friend.friends_with(player_username)) # new friend already has the player added + unless (player.friend_privacy == PrivacyState::OFF) # player's private chat state is not off + friend.send(SendFriendEvent.new(player_username, player.world_id)) # ... so we can tell the friend what world they're on + end + + unless (friend.friend_privacy == PrivacyState::OFF) # new friend's private chat state is not off + player.send(SendFriendEvent.new(friend_username, friend.world_id)) # ... so we can let the player know what world they're on + end + elsif (friend.friend_privacy == PrivacyState::ON) # new friend doesn't have the player added but their private chat state is online + player.send(SendFriendEvent.new(friend_username, friend.world_id)) # ... so we can let the player know what world they're on + end +end + +# Processes a remove friend event, updating the logged-in status of the player if necessary. +on :event, :remove_friend do |ctx, player, event| + friend_username = event.username + player_username = player.username + + player.remove_friend(friend_username) + friend = World.world.get_player(friend_username) + next if friend == nil + + friend.send(SendFriendEvent.new(player_username, 0)) if (friend.friends_with(player_username) && player.friend_privacy != PrivacyState::ON) +end + +# Update the friend server status and send the friend/ignore lists of the player logging in. +on :login do |player| + player.send(FriendServerStatusEvent.new(ServerStatus::CONNECTING)) + + player.send(IgnoreListEvent.new(player.ignored_usernames)) if player.ignored_usernames.size > 0 + + world = World.world + iterator = player.friend_usernames.iterator + while iterator.has_next + username = iterator.next + world_id = world.is_player_online(username) ? world.get_player(username).world_id : 0; + player.send(SendFriendEvent.new(username, world_id)) + end + + player.send(FriendServerStatusEvent.new(ServerStatus::ONLINE)) + update_friends(player, player.world_id) +end + +on :logout do |player| + update_friends(player, 0) +end + + +# Notifies the currently logged in players that the specified player has logged into the specified world, unless the +# newly logged-in player has their friend privacy state set to 'off'. +def update_friends(player, world=0) + privacy = player.friend_privacy + + iterator = World.world.player_repository.iterator + username = player.username + + while iterator.has_next + other = iterator.next + next if other == player + other.send(SendFriendEvent.new(username, world)) if (player.friends_with(other.username) || player.private_chat_privacy == PrivacyState::ON) + end +end \ No newline at end of file diff --git a/data/plugins/private-messaging/ignore.rb b/data/plugins/private-messaging/ignore.rb new file mode 100644 index 00000000..119f3783 --- /dev/null +++ b/data/plugins/private-messaging/ignore.rb @@ -0,0 +1,9 @@ +on :event, :add_ignore do |ctx, player, event| + username = event.username + player.add_ignore(username) +end + +on :event, :remove_ignore do |ctx, player, event| + username = event.username + player.remove_ignore(username) +end \ No newline at end of file diff --git a/data/plugins/private-messaging/messaging.rb b/data/plugins/private-messaging/messaging.rb new file mode 100644 index 00000000..826a3fe2 --- /dev/null +++ b/data/plugins/private-messaging/messaging.rb @@ -0,0 +1,21 @@ +require 'java' + +java_import 'org.apollo.game.event.impl.ForwardPrivateMessageEvent' +java_import 'org.apollo.game.model.World' +java_import 'org.apollo.game.model.settings.PrivacyState' + +on :event, :send_private_message do |ctx, player, event| + friend = World.world.get_player(event.username) + return unless interaction_permitted(player, friend) + + friend.send(ForwardPrivateMessageEvent.new(player.username, player.privilege_level, event.compressed_message)) +end + +# Checks if the sender is permitted to interact with the friend they have added: +def interaction_permitted(sender, friend) + if friend == nil || friend.has_ignored(sender.username) + return false + end + + return friend.friends_with(sender.username) ? friend.friend_privacy != PrivacyState::OFF : friend.friend_privacy == PrivacyState::ON +end \ No newline at end of file diff --git a/data/plugins/private-messaging/plugin.xml b/data/plugins/private-messaging/plugin.xml new file mode 100644 index 00000000..a327a2dc --- /dev/null +++ b/data/plugins/private-messaging/plugin.xml @@ -0,0 +1,16 @@ + + + private-messaging + 1 + Private Messaging + Adds friend and ignore list support, and private messaging. + + Major + + + + + + + + \ No newline at end of file diff --git a/src/org/apollo/ServerContext.java b/src/org/apollo/ServerContext.java index 42b0bee1..821943c1 100644 --- a/src/org/apollo/ServerContext.java +++ b/src/org/apollo/ServerContext.java @@ -5,9 +5,7 @@ import org.apollo.net.release.Release; /** * A {@link ServerContext} is created along with the {@link Server} object. The primary difference is that a reference * to the current context should be passed around within the server. The {@link Server} should not be as it allows - * access to some methods such as - * {@link Server#bind(java.net.SocketAddress, java.net.SocketAddress, java.net.SocketAddress)} which user scripts/code - * should not be able to access. + * access to some methods such as {@link Server#bind} which user scripts/code should not be able to access. * * @author Graham */ diff --git a/src/org/apollo/game/command/CommandDispatcher.java b/src/org/apollo/game/command/CommandDispatcher.java index 044dfabb..621ce7b0 100644 --- a/src/org/apollo/game/command/CommandDispatcher.java +++ b/src/org/apollo/game/command/CommandDispatcher.java @@ -6,7 +6,7 @@ import java.util.Map; import org.apollo.game.model.Player; /** - * A class which dispatches {@link Command}s to {@link CommandListener}s. + * A class that dispatches {@link Command}s to {@link CommandListener}s. * * @author Graham */ diff --git a/src/org/apollo/game/command/CommandListener.java b/src/org/apollo/game/command/CommandListener.java index 365bc05b..3d2c486e 100644 --- a/src/org/apollo/game/command/CommandListener.java +++ b/src/org/apollo/game/command/CommandListener.java @@ -4,7 +4,7 @@ import org.apollo.game.model.Player; import org.apollo.game.model.settings.PrivilegeLevel; /** - * An interface which should be implemented by classes to listen to {@link Command}s. + * An interface which should be implemented to listen to {@link Command}s. * * @author Graham * @author Major diff --git a/src/org/apollo/game/event/handler/chain/EventHandlerChainGroup.java b/src/org/apollo/game/event/handler/chain/EventHandlerChainGroup.java index 5c5daa8a..f3a8bf5e 100644 --- a/src/org/apollo/game/event/handler/chain/EventHandlerChainGroup.java +++ b/src/org/apollo/game/event/handler/chain/EventHandlerChainGroup.java @@ -3,7 +3,6 @@ package org.apollo.game.event.handler.chain; import java.util.Map; import org.apollo.game.event.Event; -import org.apollo.game.event.handler.EventHandler; /** * A group of {@link EventHandlerChain}s classified by the {@link Event} type. @@ -35,11 +34,17 @@ public final class EventHandlerChainGroup { */ @SuppressWarnings("unchecked") public EventHandlerChain getChain(Class clazz) { - EventHandlerChain chain = (EventHandlerChain) chains.get(clazz); - if (chain == null) { - chains.put(clazz, chain = new EventHandlerChain(new EventHandler[0])); - } - return chain; + return (EventHandlerChain) chains.get(clazz); + } + + /** + * Registers an {@link EventHandlerChain} associated with the specified {@link Class} to this group. + * + * @param clazz The event class. + * @param chain The event handler chain. + */ + public void register(Class clazz, EventHandlerChain chain) { + chains.put(clazz, chain); } } \ No newline at end of file diff --git a/src/org/apollo/game/event/handler/impl/BankEventHandler.java b/src/org/apollo/game/event/handler/impl/BankEventHandler.java index 228ff907..9d2f1c65 100644 --- a/src/org/apollo/game/event/handler/impl/BankEventHandler.java +++ b/src/org/apollo/game/event/handler/impl/BankEventHandler.java @@ -36,7 +36,7 @@ public final class BankEventHandler extends EventHandler { case 5: return -1; } - throw new IllegalArgumentException("option out of bounds"); + throw new IllegalArgumentException("Invalid option supplied."); } /** diff --git a/src/org/apollo/game/event/handler/impl/EquipEventHandler.java b/src/org/apollo/game/event/handler/impl/EquipEventHandler.java index 26d3e9eb..68d1401a 100644 --- a/src/org/apollo/game/event/handler/impl/EquipEventHandler.java +++ b/src/org/apollo/game/event/handler/impl/EquipEventHandler.java @@ -22,73 +22,73 @@ public final class EquipEventHandler extends EventHandler { @Override public void handle(EventHandlerContext ctx, Player player, ItemOptionEvent event) { - if (event.getOption() == 2 && event.getInterfaceId() == SynchronizationInventoryListener.INVENTORY_ID) { - int inventorySlot = event.getSlot(); - Item equipping = player.getInventory().get(inventorySlot); - int equippingId = equipping.getId(); - EquipmentDefinition definition = EquipmentDefinition.lookup(equippingId); + if (event.getOption() != 2 || event.getInterfaceId() != SynchronizationInventoryListener.INVENTORY_ID) { + ctx.breakHandlerChain(); + } - if (definition == null) { + int inventorySlot = event.getSlot(); + Item equipping = player.getInventory().get(inventorySlot); + int equippingId = equipping.getId(); + EquipmentDefinition definition = EquipmentDefinition.lookup(equippingId); + + if (definition == null) { + ctx.breakHandlerChain(); + return; + } + + for (int id = 0; id < 5; id++) { + int requirement = definition.getLevel(id); + + if (player.getSkillSet().getSkill(id).getMaximumLevel() < requirement) { + String skillName = Skill.getName(id); + String article = LanguageUtil.getIndefiniteArticle(skillName); + + player.sendMessage("You need " + article + " " + skillName + " level of " + requirement + + " to equip this item."); + ctx.breakHandlerChain(); + return; + } + } + + Inventory inventory = player.getInventory(); + Inventory equipment = player.getEquipment(); + + int equipmentSlot = definition.getSlot(); + Item currentlyEquipped = equipment.get(equipmentSlot); + + if (equipping.getDefinition().isStackable() + && (currentlyEquipped == null || currentlyEquipped.getId() == equippingId)) { + equipment.set(definition.getSlot(), equipping); + inventory.reset(inventorySlot); + ctx.breakHandlerChain(); + return; + } + + Item weapon = equipment.get(EquipmentConstants.WEAPON); + Item shield = equipment.get(EquipmentConstants.SHIELD); + + if (definition.isTwoHanded()) { + int slotsRequired = weapon != null ? shield != null ? 1 : 0 : 0; + if (inventory.freeSlots() < slotsRequired) { ctx.breakHandlerChain(); return; } - for (int id = 0; id < 5; id++) { - int requirement = definition.getLevel(id); + equipment.reset(EquipmentConstants.WEAPON); + equipment.reset(EquipmentConstants.SHIELD); + equipment.set(EquipmentConstants.WEAPON, inventory.reset(inventorySlot)); - if (player.getSkillSet().getSkill(id).getMaximumLevel() < requirement) { - String skillName = Skill.getName(id); - String article = LanguageUtil.getIndefiniteArticle(skillName); - - player.sendMessage("You need " + article + " " + skillName + " level of " + requirement - + " to equip this item."); - ctx.breakHandlerChain(); - return; - } + if (shield != null) { + inventory.add(shield); } - - Inventory inventory = player.getInventory(); - Inventory equipment = player.getEquipment(); - - int equipmentSlot = definition.getSlot(); - Item currentlyEquipped = equipment.get(equipmentSlot); - - if (equipping.getDefinition().isStackable() - && (currentlyEquipped == null || currentlyEquipped.getId() == equippingId)) { - equipment.set(definition.getSlot(), equipping); - inventory.reset(inventorySlot); - ctx.breakHandlerChain(); - return; + if (weapon != null) { + inventory.add(weapon); } - - Item weapon = equipment.get(EquipmentConstants.WEAPON); - Item shield = equipment.get(EquipmentConstants.SHIELD); - - if (definition.isTwoHanded()) { - int slotsRequired = weapon != null ? shield != null ? 1 : 0 : 0; - if (inventory.freeSlots() < slotsRequired) { - ctx.breakHandlerChain(); - return; - } - - equipment.reset(EquipmentConstants.WEAPON); - equipment.reset(EquipmentConstants.SHIELD); - equipment.set(EquipmentConstants.WEAPON, inventory.reset(inventorySlot)); - - if (shield != null) { - inventory.add(shield); - } - if (weapon != null) { - inventory.add(weapon); - } - return; - } else if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null - && EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) { - equipment.set(EquipmentConstants.SHIELD, inventory.reset(inventorySlot)); - inventory.add(equipment.reset(EquipmentConstants.WEAPON)); - return; - } - + } else if (definition.getSlot() == EquipmentConstants.SHIELD && weapon != null + && EquipmentDefinition.lookup(weapon.getId()).isTwoHanded()) { + equipment.set(EquipmentConstants.SHIELD, inventory.reset(inventorySlot)); + inventory.add(equipment.reset(EquipmentConstants.WEAPON)); + } else { Item previous = equipment.reset(equipmentSlot); inventory.remove(equipping); // no need for fancy stuff here as we know the item isn't stackable. equipment.set(equipmentSlot, equipping); diff --git a/src/org/apollo/game/event/handler/impl/ItemOnItemVerificationHandler.java b/src/org/apollo/game/event/handler/impl/ItemOnItemVerificationHandler.java index 86dfa76f..bee84129 100644 --- a/src/org/apollo/game/event/handler/impl/ItemOnItemVerificationHandler.java +++ b/src/org/apollo/game/event/handler/impl/ItemOnItemVerificationHandler.java @@ -6,6 +6,8 @@ import org.apollo.game.event.impl.ItemOnItemEvent; import org.apollo.game.model.Inventory; import org.apollo.game.model.Item; import org.apollo.game.model.Player; +import org.apollo.game.model.inter.bank.BankConstants; +import org.apollo.game.model.inv.SynchronizationInventoryListener; /** * An {@link EventHandler} which verifies the target item in {@link ItemOnItemEvent}s. @@ -16,7 +18,22 @@ public final class ItemOnItemVerificationHandler extends EventHandler= inventory.capacity()) { diff --git a/src/org/apollo/game/event/handler/impl/ItemVerificationHandler.java b/src/org/apollo/game/event/handler/impl/ItemVerificationHandler.java index 5c8bd9f9..c586612b 100644 --- a/src/org/apollo/game/event/handler/impl/ItemVerificationHandler.java +++ b/src/org/apollo/game/event/handler/impl/ItemVerificationHandler.java @@ -16,34 +16,27 @@ import org.apollo.game.model.inv.SynchronizationInventoryListener; */ public final class ItemVerificationHandler extends EventHandler { - /** - * Gets the inventory based on the interface id. - * - * @param interfaceId The interface id. - * @return The proper inventory. - * @throws IllegalArgumentException If the interface id is not legal. - */ - public static Inventory interfaceToInventory(Player player, int interfaceId) { - switch (interfaceId) { - - case SynchronizationInventoryListener.INVENTORY_ID: - case BankConstants.SIDEBAR_INVENTORY_ID: - return player.getInventory(); - case SynchronizationInventoryListener.EQUIPMENT_ID: - return player.getEquipment(); - case BankConstants.BANK_INVENTORY_ID: - return player.getBank(); - default: - throw new IllegalArgumentException("unknown interface id: " + interfaceId); - } - } - /** * Checks if the information provided by the event is valid, breaking the handler chain if it isn't. */ @Override public void handle(EventHandlerContext ctx, Player player, InventoryItemEvent event) { - Inventory inventory = interfaceToInventory(player, event.getInterfaceId()); + Inventory inventory; + + switch (event.getInterfaceId()) { + case SynchronizationInventoryListener.INVENTORY_ID: + case BankConstants.SIDEBAR_INVENTORY_ID: + inventory = player.getInventory(); + break; + case SynchronizationInventoryListener.EQUIPMENT_ID: + inventory = player.getEquipment(); + break; + case BankConstants.BANK_INVENTORY_ID: + inventory = player.getBank(); + break; + default: + return; + } int slot = event.getSlot(); if (slot < 0 || slot >= inventory.capacity()) { diff --git a/src/org/apollo/game/event/handler/impl/PrivacyOptionEventHandler.java b/src/org/apollo/game/event/handler/impl/PrivacyOptionEventHandler.java deleted file mode 100644 index 98bec28c..00000000 --- a/src/org/apollo/game/event/handler/impl/PrivacyOptionEventHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.apollo.game.event.handler.impl; - -import org.apollo.game.event.handler.EventHandler; -import org.apollo.game.event.handler.EventHandlerContext; -import org.apollo.game.event.impl.PrivacyOptionEvent; -import org.apollo.game.model.Player; - -/** - * Handles {@link PrivacyOptionEvent}s from the client. - * - * @author Kyle Stevenson - */ -public class PrivacyOptionEventHandler extends EventHandler { - - @Override - public void handle(EventHandlerContext ctx, Player player, PrivacyOptionEvent event) { - player.setPublicChatPrivacy(event.getPublicChatPrivacy()); - player.setPrivateChatPrivacy(event.getPrivateChatPrivacy()); - player.setTradeChatPrivacy(event.getTradeChatPrivacy()); - } - -} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/AddFriendEvent.java b/src/org/apollo/game/event/impl/AddFriendEvent.java new file mode 100644 index 00000000..8a832588 --- /dev/null +++ b/src/org/apollo/game/event/impl/AddFriendEvent.java @@ -0,0 +1,35 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; + +/** + * An {@link Event} sent by the client when a player is befriended. + * + * @author Major + */ +public final class AddFriendEvent extends Event { + + /** + * The username of the befriended player. + */ + private final String username; + + /** + * Creates a new befriend user event. + * + * @param username The befriended player's username. + */ + public AddFriendEvent(String username) { + this.username = username; + } + + /** + * Gets the username of the befriended player. + * + * @return The username. + */ + public String getUsername() { + return username; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/AddIgnoreEvent.java b/src/org/apollo/game/event/impl/AddIgnoreEvent.java new file mode 100644 index 00000000..61d2a303 --- /dev/null +++ b/src/org/apollo/game/event/impl/AddIgnoreEvent.java @@ -0,0 +1,35 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; + +/** + * An {@link Event} sent by the client when a player is ignored. + * + * @author Major + */ +public final class AddIgnoreEvent extends Event { + + /** + * The username of the ignored player. + */ + private final String username; + + /** + * Creates a new ignore player event. + * + * @param username The ignored player's username. + */ + public AddIgnoreEvent(String username) { + this.username = username; + } + + /** + * Gets the username of the ignored player. + * + * @return The username. + */ + public String getUsername() { + return username; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/ForwardPrivateMessageEvent.java b/src/org/apollo/game/event/impl/ForwardPrivateMessageEvent.java new file mode 100644 index 00000000..163238eb --- /dev/null +++ b/src/org/apollo/game/event/impl/ForwardPrivateMessageEvent.java @@ -0,0 +1,67 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; +import org.apollo.game.model.settings.PrivilegeLevel; + +/** + * An {@link Event} that forwards a private message to a client. + * + * @author Major + */ +public final class ForwardPrivateMessageEvent extends Event { + + /** + * The username of the player sending the message. + */ + private final String username; + + /** + * The privilege level of the player. + */ + private final PrivilegeLevel privilege; + + /** + * The message. + */ + private final byte[] message; + + /** + * Creates a new forward private message event. + * + * @param sender The player sending the message. + * @param message The compressed message. + */ + public ForwardPrivateMessageEvent(String username, PrivilegeLevel level, byte[] message) { + this.username = username; + this.privilege = level; + this.message = message; + } + + /** + * Gets the username of the sender. + * + * @return The username. + */ + public String getSenderUsername() { + return username; + } + + /** + * Gets the {@link PrivilegeLevel} of the sender. + * + * @return The privilege level. + */ + public PrivilegeLevel getSenderPrivilege() { + return privilege; + } + + /** + * Gets the compressed message. + * + * @return The message. + */ + public byte[] getMessage() { + return message; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/FriendServerStatusEvent.java b/src/org/apollo/game/event/impl/FriendServerStatusEvent.java new file mode 100644 index 00000000..8bf12a32 --- /dev/null +++ b/src/org/apollo/game/event/impl/FriendServerStatusEvent.java @@ -0,0 +1,36 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; +import org.apollo.game.model.settings.ServerStatus; + +/** + * An {@link Event} sent by the server to update the friend server status. + * + * @author Major + */ +public final class FriendServerStatusEvent extends Event { + + /** + * The status code of the friend server. + */ + private final int status; + + /** + * Creates a new friend server status event. + * + * @param status The status. + */ + public FriendServerStatusEvent(ServerStatus status) { + this.status = status.getCode(); + } + + /** + * Gets the status code of the friend server. + * + * @return The status code. + */ + public int getStatusCode() { + return status; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/IgnoreListEvent.java b/src/org/apollo/game/event/impl/IgnoreListEvent.java new file mode 100644 index 00000000..6cb56455 --- /dev/null +++ b/src/org/apollo/game/event/impl/IgnoreListEvent.java @@ -0,0 +1,37 @@ +package org.apollo.game.event.impl; + +import java.util.List; + +import org.apollo.game.event.Event; + +/** + * An {@link Event} which is sent to the client that updates the ignored user list. + * + * @author Major + */ +public final class IgnoreListEvent extends Event { + + /** + * The list of ignored player usernames. + */ + private final List usernames; + + /** + * Creates a new ignore list event. + * + * @param player The player. + */ + public IgnoreListEvent(List usernames) { + this.usernames = usernames; + } + + /** + * Gets the list of ignored usernames. + * + * @return The usernames. + */ + public List getUsernames() { + return usernames; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/PrivacyOptionEvent.java b/src/org/apollo/game/event/impl/PrivacyOptionEvent.java index 68f972d9..295d4c9d 100644 --- a/src/org/apollo/game/event/impl/PrivacyOptionEvent.java +++ b/src/org/apollo/game/event/impl/PrivacyOptionEvent.java @@ -7,62 +7,63 @@ import org.apollo.game.model.settings.PrivacyState; * An {@link Event} sent by the client or server to update the chat and trade privacy state. * * @author Kyle Stevenson + * @author Major */ -public class PrivacyOptionEvent extends Event { +public final class PrivacyOptionEvent extends Event { /** - * The privacy state of the player's public chat. + * The privacy state of the player's chat. */ - private final PrivacyState publicChatState; + private final PrivacyState chatPrivacy; /** - * The privacy state of the player's private chat. + * The privacy state of the player's friend chat. */ - private final PrivacyState privateChatState; + private final PrivacyState friendPrivacy; /** * The privacy state of the player's trade chat. */ - private final PrivacyState tradeChatState; + private final PrivacyState tradePrivacy; /** * Creates a privacy option event. * - * @param publicChatState The privacy state of the player's public chat. - * @param privateChatState The privacy state of the player's private chat. - * @param tradeChatState The privacy state of the player's trade chat. + * @param chatPrivacy The privacy state of the player's chat. + * @param friendPrivacy The privacy state of the player's friend chat. + * @param tradePrivacy The privacy state of the player's trade chat. */ - public PrivacyOptionEvent(int publicChatState, int privateChatState, int tradeChatState) { - this.publicChatState = PrivacyState.valueOf(publicChatState); - this.privateChatState = PrivacyState.valueOf(privateChatState); - this.tradeChatState = PrivacyState.valueOf(tradeChatState); + public PrivacyOptionEvent(int chatPrivacy, int friendPrivacy, int tradePrivacy) { + this.chatPrivacy = PrivacyState.valueOf(chatPrivacy); + this.friendPrivacy = PrivacyState.valueOf(friendPrivacy); + this.tradePrivacy = PrivacyState.valueOf(tradePrivacy); } /** - * Gets the public chat {@link PrivacyState}. + * Gets the chat {@link PrivacyState}. * - * @return The privacy option. + * @return The privacy state. */ - public PrivacyState getPublicChatPrivacy() { - return publicChatState; + public PrivacyState getChatPrivacy() { + return chatPrivacy; } /** - * Gets the private chat {@link PrivacyState}. + * Gets the friend {@link PrivacyState}. * - * @return The privacy option. + * @return The privacy state. */ - public PrivacyState getPrivateChatPrivacy() { - return privateChatState; + public PrivacyState getFriendPrivacy() { + return friendPrivacy; } /** - * Gets the trade chat {@link PrivacyState}. + * Gets the trade {@link PrivacyState}. * - * @return The privacy option. + * @return The privacy state. */ - public PrivacyState getTradeChatPrivacy() { - return tradeChatState; + public PrivacyState getTradePrivacy() { + return tradePrivacy; } } \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/RemoveFriendEvent.java b/src/org/apollo/game/event/impl/RemoveFriendEvent.java new file mode 100644 index 00000000..07061f2f --- /dev/null +++ b/src/org/apollo/game/event/impl/RemoveFriendEvent.java @@ -0,0 +1,35 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; + +/** + * An {@link Event} sent by the client when a player is removed from a friends list. + * + * @author Major + */ +public final class RemoveFriendEvent extends Event { + + /** + * The username of the defriended player. + */ + private final String username; + + /** + * Creates a new defriend user event. + * + * @param username The defriended player's username. + */ + public RemoveFriendEvent(String username) { + this.username = username; + } + + /** + * Gets the username of the defriended player. + * + * @return The username. + */ + public String getUsername() { + return username; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/RemoveIgnoreEvent.java b/src/org/apollo/game/event/impl/RemoveIgnoreEvent.java new file mode 100644 index 00000000..cb9ae680 --- /dev/null +++ b/src/org/apollo/game/event/impl/RemoveIgnoreEvent.java @@ -0,0 +1,35 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; + +/** + * An {@link Event} sent by the client when a player is removed from a ignore list. + * + * @author Major + */ +public final class RemoveIgnoreEvent extends Event { + + /** + * The username of the unignored player. + */ + private final String username; + + /** + * Creates a new unignore player event. + * + * @param username The unignored player's username. + */ + public RemoveIgnoreEvent(String username) { + this.username = username; + } + + /** + * Gets the username of the unignored player. + * + * @return The username. + */ + public String getUsername() { + return username; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/SendFriendEvent.java b/src/org/apollo/game/event/impl/SendFriendEvent.java new file mode 100644 index 00000000..8eb886c3 --- /dev/null +++ b/src/org/apollo/game/event/impl/SendFriendEvent.java @@ -0,0 +1,51 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; + +/** + * An {@link Event} sent to the client to add a player to the friend list. + * + * @author Major + */ +public final class SendFriendEvent extends Event { + + /** + * The username of the friend. + */ + private final String username; + + /** + * The world id the friend is in. + */ + private final int world; + + /** + * Creates a new send friend event. + * + * @param username The username of the friend. + * @param world The world the friend is in. + */ + public SendFriendEvent(String username, int world) { + this.username = username; + this.world = world == 0 ? 0 : world + 9; + } + + /** + * Gets the username of the friend. + * + * @return The username. + */ + public String getUsername() { + return username; + } + + /** + * Gets the world id the friend is in. + * + * @return The world id. + */ + public int getWorld() { + return world; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/event/impl/SendPrivateMessageEvent.java b/src/org/apollo/game/event/impl/SendPrivateMessageEvent.java new file mode 100644 index 00000000..52f67625 --- /dev/null +++ b/src/org/apollo/game/event/impl/SendPrivateMessageEvent.java @@ -0,0 +1,67 @@ +package org.apollo.game.event.impl; + +import org.apollo.game.event.Event; + +/** + * An {@link Event} sent by the client to send a private message to another player. + * + * @author Major + */ +public final class SendPrivateMessageEvent extends Event { + + /** + * The username this message is being sent to. + */ + private final String username; + + /** + * The message being sent. + */ + private final String message; + + /** + * The compressed message. + */ + private final byte[] compressedMessage; + + /** + * Creates a new private message event. + * + * @param username The username of the player the message is being sent to. + * @param message The message. + * @param compressedMessage The message, in a compressed form. + */ + public SendPrivateMessageEvent(String username, String message, byte[] compressedMessage) { + this.username = username; + this.message = message; + this.compressedMessage = compressedMessage; + } + + /** + * Gets the username of the player the message is being sent to. + * + * @return The username. + */ + public String getUsername() { + return username; + } + + /** + * Gets the message being sent. + * + * @return The message. + */ + public String getMessage() { + return message; + } + + /** + * Gets the compressed message. + * + * @return The compressed message. + */ + public byte[] getCompressedMessage() { + return compressedMessage; + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/login/LoginDispatcher.java b/src/org/apollo/game/login/LoginDispatcher.java new file mode 100644 index 00000000..2e3363c2 --- /dev/null +++ b/src/org/apollo/game/login/LoginDispatcher.java @@ -0,0 +1,40 @@ +package org.apollo.game.login; + +import java.util.ArrayList; +import java.util.List; + +import org.apollo.game.model.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 List listeners = new ArrayList<>(); + + /** + * Dispatches a player to the appropriate login listener. + * + * @param player The player. + */ + public void dispatch(Player player) { + for (LoginListener listener : listeners) { + listener.execute(player); + } + } + + /** + * Registers a listener with this dispatcher. + * + * @param listener The listener. + */ + public void register(LoginListener listener) { + listeners.add(listener); + } + +} \ No newline at end of file diff --git a/src/org/apollo/game/login/LoginListener.java b/src/org/apollo/game/login/LoginListener.java new file mode 100644 index 00000000..bdb9d3a6 --- /dev/null +++ b/src/org/apollo/game/login/LoginListener.java @@ -0,0 +1,19 @@ +package org.apollo.game.login; + +import org.apollo.game.model.Player; + +/** + * An interface that should be implemented for actions that should be executed when the player logs in. + * + * @author Major + */ +public abstract class LoginListener { + + /** + * Executes the action for this listener. + * + * @param player The player. + */ + public abstract void execute(Player player); + +} \ No newline at end of file diff --git a/src/org/apollo/game/login/LogoutDispatcher.java b/src/org/apollo/game/login/LogoutDispatcher.java new file mode 100644 index 00000000..b595cabd --- /dev/null +++ b/src/org/apollo/game/login/LogoutDispatcher.java @@ -0,0 +1,40 @@ +package org.apollo.game.login; + +import java.util.ArrayList; +import java.util.List; + +import org.apollo.game.model.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 List listeners = new ArrayList<>(); + + /** + * Dispatches a player to the appropriate logout listener. + * + * @param player The player. + */ + public void dispatch(Player player) { + for (LogoutListener listen : listeners) { + listen.execute(player); + } + } + + /** + * Registers a listener with this dispatcher. + * + * @param listener The listener. + */ + public void register(LogoutListener listener) { + listeners.add(listener); + } + +} diff --git a/src/org/apollo/game/login/LogoutListener.java b/src/org/apollo/game/login/LogoutListener.java new file mode 100644 index 00000000..22076340 --- /dev/null +++ b/src/org/apollo/game/login/LogoutListener.java @@ -0,0 +1,19 @@ +package org.apollo.game.login; + +import org.apollo.game.model.Player; + +/** + * An interface that should be implemented for actions that should be executed when the player logs out. + * + * @author Major + */ +public abstract class LogoutListener { + + /** + * Executes the action for this listener. + * + * @param player The player. + */ + public abstract void execute(Player player); + +} \ No newline at end of file diff --git a/src/org/apollo/game/login/package-info.java b/src/org/apollo/game/login/package-info.java new file mode 100644 index 00000000..d5e85dc2 --- /dev/null +++ b/src/org/apollo/game/login/package-info.java @@ -0,0 +1,4 @@ +/** + * Contains login listeners. + */ +package org.apollo.game.login; \ No newline at end of file diff --git a/src/org/apollo/game/model/Entity.java b/src/org/apollo/game/model/Entity.java index c12949c5..e4c97864 100644 --- a/src/org/apollo/game/model/Entity.java +++ b/src/org/apollo/game/model/Entity.java @@ -1,11 +1,18 @@ package org.apollo.game.model; +import java.io.Serializable; + /** * Represents an in-game entity, such as a mob, object, projectile etc. * * @author Major */ -public abstract class Entity { +public abstract class Entity implements Serializable { + + /** + * The generated serial UID. + */ + private static final long serialVersionUID = 5968243763380631014L; /** * The position of this entity. diff --git a/src/org/apollo/game/model/Mob.java b/src/org/apollo/game/model/Mob.java index b6228aa5..3b28741b 100644 --- a/src/org/apollo/game/model/Mob.java +++ b/src/org/apollo/game/model/Mob.java @@ -18,15 +18,20 @@ import org.apollo.util.MobRepository; */ public abstract class Mob extends Entity { + /** + * The generated serial uid. + */ + private static final long serialVersionUID = 8342608309450355638L; + /** * This mob's current action. */ - private Action action; + private transient Action action; /** * This mob's set of {@link SynchronizationBlock}s. */ - protected SynchronizationBlockSet blockSet = new SynchronizationBlockSet(); + protected transient SynchronizationBlockSet blockSet = new SynchronizationBlockSet(); /** * This mob's {@link NpcDefinition). A {@link Player} only uses this if they are appearing as an npc in-game. @@ -36,52 +41,52 @@ public abstract class Mob extends Entity { /** * This mob's equipment. */ - private final Inventory equipment = new Inventory(InventoryConstants.EQUIPMENT_CAPACITY, StackMode.STACK_ALWAYS); + protected final Inventory equipment = new Inventory(InventoryConstants.EQUIPMENT_CAPACITY, StackMode.STACK_ALWAYS); /** * This mob's first movement {@link Direction}. */ - private Direction firstDirection = Direction.NONE; + private transient Direction firstDirection = Direction.NONE; /** * The index of this mob in the {@link MobRepository} it belongs to. */ - private int index = -1; + protected int index = -1; /** * This mob's inventory. */ - private final Inventory inventory = new Inventory(InventoryConstants.INVENTORY_CAPACITY); + protected final Inventory inventory = new Inventory(InventoryConstants.INVENTORY_CAPACITY); /** * This mob's {@link List} of local npcs. */ - private final List localNpcs = new ArrayList(); + private final transient List localNpcs = new ArrayList(); /** * This mob's {@link List} of local players. */ - private final List localPlayers = new ArrayList(); + private final transient List localPlayers = new ArrayList(); /** * This mob's second movement direction. */ - private Direction secondDirection = Direction.NONE; + private transient Direction secondDirection = Direction.NONE; /** * This mob's skill set. */ - private final SkillSet skillSet = new SkillSet(); + protected final SkillSet skillSet = new SkillSet(); /** * Indicates whether this mob is currently teleporting or not. */ - private boolean teleporting = false; + private transient boolean teleporting = false; /** * This mob's walking queue. */ - private final WalkingQueue walkingQueue = new WalkingQueue(this); + protected final transient WalkingQueue walkingQueue = new WalkingQueue(this); /** * Creates a new mob with the specified initial {@link Position}. diff --git a/src/org/apollo/game/model/Npc.java b/src/org/apollo/game/model/Npc.java index d7cbe253..cbff9323 100644 --- a/src/org/apollo/game/model/Npc.java +++ b/src/org/apollo/game/model/Npc.java @@ -8,6 +8,7 @@ import org.apollo.game.sync.block.SynchronizationBlock; * * @author Major */ +@SuppressWarnings("serial") public final class Npc extends Mob { /** diff --git a/src/org/apollo/game/model/Player.java b/src/org/apollo/game/model/Player.java index 832e075b..2184227f 100644 --- a/src/org/apollo/game/model/Player.java +++ b/src/org/apollo/game/model/Player.java @@ -1,13 +1,16 @@ package org.apollo.game.model; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Deque; import java.util.List; import org.apollo.game.event.Event; import org.apollo.game.event.impl.ConfigEvent; import org.apollo.game.event.impl.IdAssignmentEvent; +import org.apollo.game.event.impl.IgnoreListEvent; import org.apollo.game.event.impl.LogoutEvent; +import org.apollo.game.event.impl.SendFriendEvent; import org.apollo.game.event.impl.ServerMessageEvent; import org.apollo.game.event.impl.SetWidgetTextEvent; import org.apollo.game.event.impl.SwitchTabInterfaceEvent; @@ -38,6 +41,11 @@ import org.apollo.util.Point; */ public final class Player extends Mob { + /** + * The generated serial uid. + */ + private static final long serialVersionUID = -5865532568677077237L; + /** * The player's appearance. */ @@ -49,9 +57,14 @@ public final class Player extends Mob { private final Inventory bank = new Inventory(InventoryConstants.BANK_CAPACITY, StackMode.STACK_ALWAYS); /** - * A {@link List} of this player's mouse clicks. + * The privacy state of this player's public chat. */ - private Deque clicks = new ArrayDeque(); + private PrivacyState chatPrivacy = PrivacyState.ON; + + /** + * A deque of this player's mouse clicks. + */ + private transient Deque clicks = new ArrayDeque(); /** * This player's credentials. @@ -66,67 +79,72 @@ public final class Player extends Mob { /** * A flag which indicates there are npcs that couldn't be added. */ - private boolean excessiveNpcs = false; + private transient boolean excessiveNpcs = false; /** * A flag which indicates there are players that couldn't be added. */ - private boolean excessivePlayers = false; + private transient boolean excessivePlayers = false; + + /** + * The privacy state of this player's private chat. + */ + private PrivacyState friendPrivacy = PrivacyState.ON; + + /** + * The list of usernames of players this player has befriended. + */ + private List friends = new ArrayList<>(); /** * This player's head icon. */ private int headIcon = -1; + /** + * The list of usernames of players this player has ignored. + */ + private List ignores = new ArrayList<>(); + /** * This player's interface set. */ - private final InterfaceSet interfaceSet = new InterfaceSet(this); + private final transient InterfaceSet interfaceSet = new InterfaceSet(this); /** * The centre of the last region the client has loaded. */ - private Position lastKnownRegion; + private transient Position lastKnownRegion; /** * The membership flag. */ - private boolean members = false; + private transient boolean members = false; /** * This player's prayer icon. */ private int prayerIcon = 0; - /** - * The privacy state of this player's private chat. - */ - private PrivacyState privateChatPrivacy = PrivacyState.ON; - /** * The privilege level. */ private PrivilegeLevel privilegeLevel = PrivilegeLevel.STANDARD; - /** - * The privacy state of this player's public chat. - */ - private PrivacyState publicChatPrivacy = PrivacyState.ON; - /** * A temporary queue of events sent during the login process. */ - private final Deque queuedEvents = new ArrayDeque(); + private final transient Deque queuedEvents = new ArrayDeque(); /** * A flag indicating if the region changed in the last cycle. */ - private boolean regionChanged = false; + private transient boolean regionChanged = false; /** * The player's run energy. */ - private int runEnergy = 0; + private int runEnergy = 100; /** * A flag indicating if this player is running. @@ -136,17 +154,17 @@ public final class Player extends Mob { /** * The brightness of this player's screen. */ - private ScreenBrightness screenBrightness; + private ScreenBrightness screenBrightness = ScreenBrightness.NORMAL; /** * The {@link GameSession} currently attached to this {@link Player}. */ - private GameSession session; + private transient GameSession session; /** * The privacy state of this player's trade chat. */ - private PrivacyState tradeChatPrivacy = PrivacyState.ON; + private PrivacyState tradePrivacy = PrivacyState.ON; /** * The current maximum viewing distance of this player. @@ -158,6 +176,11 @@ public final class Player extends Mob { */ private boolean withdrawingNotes = false; + /** + * The id of the world this player is in. + */ + private transient int worldId = 1; + /** * Creates the {@link Player}. * @@ -180,6 +203,24 @@ public final class Player extends Mob { return clicks.add(point); } + /** + * Adds the specified username to this player's friend list. + * + * @param username The username. + */ + public boolean addFriend(String username) { + return friends.add(username.toLowerCase()); + } + + /** + * Adds the specified username to this player's ignore list. + * + * @param username The username. + */ + public boolean addIgnore(String username) { + return ignores.add(username.toLowerCase()); + } + /** * Decrements this player's viewing distance if it is greater than 1. */ @@ -203,6 +244,16 @@ public final class Player extends Mob { excessivePlayers = true; } + /** + * Indicates whether this player is friends with the player with the specified username or not. + * + * @param username The username of the other player. + * @return {@code true} if the specified username is on this player's friend list, otherwise {@code false}. + */ + public boolean friendsWith(String username) { + return friends.contains(username.toLowerCase()); + } + /** * Gets the player's appearance. * @@ -221,6 +272,15 @@ public final class Player extends Mob { return bank; } + /** + * Gets this player's public chat privacy state. + * + * @return The privacy state. + */ + public PrivacyState getChatPrivacy() { + return chatPrivacy; + } + /** * Gets the {@link Deque} of clicks. * @@ -253,6 +313,24 @@ public final class Player extends Mob { return EntityType.PLAYER; } + /** + * Gets this player's friend chat {@link PrivacyState}. + * + * @return The privacy state. + */ + public PrivacyState getFriendPrivacy() { + return friendPrivacy; + } + + /** + * Gets the {@link List} of this player's friends. + * + * @return The list. + */ + public List getFriendUsernames() { + return friends; + } + /** * Gets the player's head icon. * @@ -262,6 +340,15 @@ public final class Player extends Mob { return headIcon; } + /** + * Gets the {@link List} of usernames of ignored players. + * + * @return The list. + */ + public List getIgnoredUsernames() { + return ignores; + } + /** * Gets this player's interface set. * @@ -289,15 +376,6 @@ public final class Player extends Mob { return lastKnownRegion; } - /** - * Gets the player's name. - * - * @return The player's name. - */ - public String getName() { - return credentials.getUsername(); - } - /** * Gets the player's prayer icon. * @@ -307,15 +385,6 @@ public final class Player extends Mob { return prayerIcon; } - /** - * Gets this player's private chat privacy state. - * - * @return The privacy state. - */ - public PrivacyState getPrivateChatPrivacy() { - return privateChatPrivacy; - } - /** * Gets the privilege level. * @@ -325,15 +394,6 @@ public final class Player extends Mob { return privilegeLevel; } - /** - * Gets this player's public chat privacy state. - * - * @return The privacy state. - */ - public PrivacyState getPublicChatPrivacy() { - return publicChatPrivacy; - } - /** * Gets the player's run energy. * @@ -362,12 +422,21 @@ public final class Player extends Mob { } /** - * Gets this player's trade chat privacy state. + * Gets this player's trade {@link PrivacyState}. * * @return The privacy state. */ - public PrivacyState getTradeChatPrivacy() { - return tradeChatPrivacy; + public PrivacyState getTradePrivacy() { + return tradePrivacy; + } + + /** + * Gets the player's name. + * + * @return The player's name. + */ + public String getUsername() { + return credentials.getUsername(); } /** @@ -379,6 +448,15 @@ public final class Player extends Mob { return viewingDistance; } + /** + * Gets the id of the world this player is in. + * + * @return The id. + */ + public int getWorldId() { + return worldId; + } + /** * Checks if the player has designed their avatar. * @@ -388,6 +466,16 @@ public final class Player extends Mob { return designedAvatar; } + /** + * Indicates whether or not the player with the specified username is on this player's ignore list. + * + * @param username The username of the player. + * @return {@code true} if the player is ignored, {@code false} if not. + */ + public boolean hasIgnored(String username) { + return ignores.contains(username.toLowerCase()); + } + /** * Checks if this player has ever known a region. * @@ -427,10 +515,6 @@ public final class Player extends Mob { * Initialises the player's inventories. */ private void initInventories() { - Inventory inventory = getInventory(); - Inventory bank = getBank(); - Inventory equipment = getEquipment(); - // inventory full listeners InventoryListener fullInventoryListener = new FullInventoryListener(this, FullInventoryListener.FULL_INVENTORY_MESSAGE); @@ -524,6 +608,24 @@ public final class Player extends Mob { send(new LogoutEvent()); } + /** + * Removes the specified username from this player's friend list. + * + * @param username The username. + */ + public boolean removeFriend(String username) { + return friends.remove(username.toLowerCase()); + } + + /** + * Removes the specified username from this player's ignore list. + * + * @param username The username. + */ + public boolean removeIgnore(String username) { + return ignores.remove(username.toLowerCase()); + } + /** * Resets the excessive players flag. */ @@ -561,7 +663,7 @@ public final class Player extends Mob { * Sends the initial events. */ private void sendInitialEvents() { - send(new IdAssignmentEvent(getIndex(), members)); // TODO should this be sent when we reconnect? + send(new IdAssignmentEvent(index, members)); // TODO should this be sent when we reconnect? sendMessage("Welcome to RuneScape."); if (!designedAvatar) { @@ -569,15 +671,16 @@ public final class Player extends Mob { } int[] tabs = InterfaceConstants.DEFAULT_INVENTORY_TABS; - for (int i = 0; i < tabs.length; i++) { - send(new SwitchTabInterfaceEvent(i, tabs[i])); + for (int tab = 0; tab < tabs.length; tab++) { + send(new SwitchTabInterfaceEvent(tab, tabs[tab])); } - getInventory().forceRefresh(); - getEquipment().forceRefresh(); - getBank().forceRefresh(); + inventory.forceRefresh(); + equipment.forceRefresh(); + bank.forceRefresh(); + skillSet.forceRefresh(); - getSkillSet().forceRefresh(); + World.getWorld().getLoginDispatcher().dispatch(this); } /** @@ -597,7 +700,7 @@ public final class Player extends Mob { public void sendQuestInterface(List text) { int size = text.size(), lines = InterfaceConstants.QUEST_TEXT.length; if (size > lines) { - throw new IllegalArgumentException("list contains too much text for this interface."); + throw new IllegalArgumentException("List contains too much text for this interface."); } for (int pos = 0; pos < lines; pos++) { @@ -606,6 +709,21 @@ public final class Player extends Mob { interfaceSet.openWindow(InterfaceConstants.QUEST_INTERFACE); } + /** + * Sends the friend and ignore user lists. + */ + public void sendUserLists() { + if (ignores.size() > 0) { + send(new IgnoreListEvent(ignores)); + } + + World world = World.getWorld(); + for (String username : friends) { + int worldId = world.isPlayerOnline(username) ? world.getPlayer(username).worldId : 0; + send(new SendFriendEvent(username, worldId)); + } + } + /** * Sets the player's appearance. * @@ -613,7 +731,16 @@ public final class Player extends Mob { */ public void setAppearance(Appearance appearance) { this.appearance = appearance; - getBlockSet().add(SynchronizationBlock.createAppearanceBlock(this)); + blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); + } + + /** + * Sets the chat {@link PrivacyState}. + * + * @param chatPrivacy The privacy state. + */ + public void setChatPrivacy(PrivacyState chatPrivacy) { + this.chatPrivacy = chatPrivacy; } /** @@ -625,6 +752,24 @@ public final class Player extends Mob { this.designedAvatar = designedAvatar; } + /** + * Sets the friend {@link PrivacyState}. + * + * @param friendPrivacy The privacy state. + */ + public void setFriendPrivacy(PrivacyState friendPrivacy) { + this.friendPrivacy = friendPrivacy; + } + + /** + * Sets the {@link List} of this player's friends. + * + * @param friends The friends. + */ + public void setFriendUsernames(List friends) { + this.friends = friends; + } + /** * Sets the player's head icon. * @@ -634,6 +779,15 @@ public final class Player extends Mob { this.headIcon = headIcon; } + /** + * Sets the {@link List} of this player's ignored players. + * + * @param ignores The ignored player list. + */ + public void setIgnoredUsernames(List ignores) { + this.ignores = ignores; + } + /** * Sets the last known region. * @@ -661,15 +815,6 @@ public final class Player extends Mob { this.prayerIcon = prayerIcon; } - /** - * Sets the private chat {@link PrivacyState}. - * - * @param privateChatPrivacy The privacy state. - */ - public void setPrivateChatPrivacy(PrivacyState privateChatPrivacy) { - this.privateChatPrivacy = privateChatPrivacy; - } - /** * Sets the privilege level. * @@ -679,15 +824,6 @@ public final class Player extends Mob { this.privilegeLevel = privilegeLevel; } - /** - * Sets the public chat {@link PrivacyState}. - * - * @param publicChatPrivacy The privacy state. - */ - public void setPublicChatPrivacy(PrivacyState publicChatPrivacy) { - this.publicChatPrivacy = publicChatPrivacy; - } - /** * Sets the region changed flag. * @@ -727,16 +863,16 @@ public final class Player extends Mob { if (!reconnecting) { sendInitialEvents(); } - getBlockSet().add(SynchronizationBlock.createAppearanceBlock(this)); + blockSet.add(SynchronizationBlock.createAppearanceBlock(this)); } /** - * Sets the trade chat {@link PrivacyState}. + * Sets the trade {@link PrivacyState}. * - * @param tradeChatPrivacy The privacy state. + * @param tradePrivacy The privacy state. */ - public void setTradeChatPrivacy(PrivacyState tradeChatPrivacy) { - this.tradeChatPrivacy = tradeChatPrivacy; + public void setTradePrivacy(PrivacyState tradePrivacy) { + this.tradePrivacy = tradePrivacy; } /** @@ -766,7 +902,7 @@ public final class Player extends Mob { */ public void toggleRunning() { running = !running; - getWalkingQueue().setRunningQueue(running); + walkingQueue.setRunningQueue(running); send(new ConfigEvent(173, running ? 1 : 0)); } diff --git a/src/org/apollo/game/model/Position.java b/src/org/apollo/game/model/Position.java index a1199f5e..537946f0 100644 --- a/src/org/apollo/game/model/Position.java +++ b/src/org/apollo/game/model/Position.java @@ -51,7 +51,7 @@ public final class Position { */ public Position(int x, int y, int height) { if (height < 0 || height >= HEIGHT_LEVELS) { - throw new IllegalArgumentException("Height out of bounds"); + throw new IllegalArgumentException("Height level out of bounds."); } this.x = x; this.y = y; diff --git a/src/org/apollo/game/model/Skill.java b/src/org/apollo/game/model/Skill.java index b0971f23..a0d0ad3e 100644 --- a/src/org/apollo/game/model/Skill.java +++ b/src/org/apollo/game/model/Skill.java @@ -7,55 +7,20 @@ package org.apollo.game.model; */ public final class Skill { - /** - * The agility id. - */ - public static final int AGILITY = 16; - /** * The attack id. */ public static final int ATTACK = 0; - /** - * The cooking id. - */ - public static final int COOKING = 7; - - /** - * The crafting id. - */ - public static final int CRAFTING = 12; - /** * The defence id. */ public static final int DEFENCE = 1; /** - * The farming id. + * The strength id. */ - public static final int FARMING = 19; - - /** - * The firemaking id. - */ - public static final int FIREMAKING = 11; - - /** - * The fishing id. - */ - public static final int FISHING = 10; - - /** - * The fletching id. - */ - public static final int FLETCHING = 9; - - /** - * The herblore id. - */ - public static final int HERBLORE = 15; + public static final int STRENGTH = 2; /** * The hitpoints id. @@ -63,14 +28,9 @@ public final class Skill { public static final int HITPOINTS = 3; /** - * The magic id. + * The ranged id. */ - public static final int MAGIC = 6; - - /** - * The mining id.rivate - */ - public static final int MINING = 14; + public static final int RANGED = 4; /** * The prayer id. @@ -78,9 +38,74 @@ public final class Skill { public static final int PRAYER = 5; /** - * The ranged id. + * The magic id. */ - public static final int RANGED = 4; + public static final int MAGIC = 6; + + /** + * The cooking id. + */ + public static final int COOKING = 7; + + /** + * The woodcutting id. + */ + public static final int WOODCUTTING = 8; + + /** + * The fletching id. + */ + public static final int FLETCHING = 9; + + /** + * The fishing id. + */ + public static final int FISHING = 10; + + /** + * The firemaking id. + */ + public static final int FIREMAKING = 11; + + /** + * The crafting id. + */ + public static final int CRAFTING = 12; + + /** + * The smithing id. + */ + public static final int SMITHING = 13; + + /** + * The mining id.rivate + */ + public static final int MINING = 14; + + /** + * The herblore id. + */ + public static final int HERBLORE = 15; + + /** + * The agility id. + */ + public static final int AGILITY = 16; + + /** + * The thieving id. + */ + public static final int THIEVING = 17; + + /** + * The slayer id. + */ + public static final int SLAYER = 18; + + /** + * The farming id. + */ + public static final int FARMING = 19; /** * The runecrafting id. @@ -94,31 +119,6 @@ public final class Skill { "Magic", "Cooking", "Woodcutting", "Fletching", "Fishing", "Firemaking", "Crafting", "Smithing", "Mining", "Herblore", "Agility", "Thieving", "Slayer", "Farming", "Runecraft" }; - /** - * The slayer id. - */ - public static final int SLAYER = 18; - - /** - * The smithing id. - */ - public static final int SMITHING = 13; - - /** - * The strength id. - */ - public static final int STRENGTH = 2; - - /** - * The thieving id. - */ - public static final int THIEVING = 17; - - /** - * The woodcutting id. - */ - public static final int WOODCUTTING = 8; - /** * Gets the name of a skill. * diff --git a/src/org/apollo/game/model/World.java b/src/org/apollo/game/model/World.java index bf641575..37b58dc2 100644 --- a/src/org/apollo/game/model/World.java +++ b/src/org/apollo/game/model/World.java @@ -15,6 +15,8 @@ import org.apollo.fs.decoder.NpcDefinitionDecoder; import org.apollo.fs.decoder.ObjectDefinitionDecoder; import org.apollo.fs.decoder.StaticObjectDecoder; import org.apollo.game.command.CommandDispatcher; +import org.apollo.game.login.LoginDispatcher; +import org.apollo.game.login.LogoutDispatcher; import org.apollo.game.model.def.EquipmentDefinition; import org.apollo.game.model.def.ItemDefinition; import org.apollo.game.model.def.NpcDefinition; @@ -27,6 +29,7 @@ import org.apollo.game.scheduling.ScheduledTask; import org.apollo.game.scheduling.Scheduler; import org.apollo.io.EquipmentDefinitionParser; import org.apollo.util.MobRepository; +import org.apollo.util.NameUtil; import org.apollo.util.plugin.PluginManager; /** @@ -83,22 +86,32 @@ public final class World { /** * The command dispatcher. */ - private final CommandDispatcher dispatcher = new CommandDispatcher(); + private final CommandDispatcher commandDispatcher = new CommandDispatcher(); + + /** + * 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. */ - private final MobRepository npcRepository = new MobRepository(WorldConstants.MAXIMUM_NPCS); + private final MobRepository npcRepository = new MobRepository<>(WorldConstants.MAXIMUM_NPCS); /** * The {@link MobRepository} of {@link Player}s. */ - private final MobRepository playerRepository = new MobRepository(WorldConstants.MAXIMUM_PLAYERS); + private final MobRepository playerRepository = new MobRepository<>(WorldConstants.MAXIMUM_PLAYERS); /** * A {@link Map} of player usernames and the player objects. */ - private final Map players = new HashMap(); + private final Map players = new HashMap<>(); /** * The {@link PluginManager}. TODO: better place than here!! @@ -133,7 +146,25 @@ public final class World { * @return The command dispatcher. */ public CommandDispatcher getCommandDispatcher() { - return dispatcher; + 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; } /** @@ -146,13 +177,14 @@ public final class World { } /** - * Gets the {@link Player} with the specified username. + * Gets the {@link Player} with the specified username. Note that this will return {@code null} if the player is + * offline. * * @param username The username. * @return The player. */ public Player getPlayer(String username) { - return players.get(username); + return players.get(NameUtil.encodeBase37(username.toLowerCase())); } /** @@ -229,11 +261,11 @@ public final class World { /** * Checks if the {@link Player} with the specified name is online. * - * @param name The name. + * @param username The name. * @return {@code true} if the player is online, otherwise {@code false}. */ - public boolean isPlayerOnline(String name) { - return getPlayer(name) != null; + public boolean isPlayerOnline(String username) { + return players.get(NameUtil.encodeBase37(username.toLowerCase())) != null; } /** @@ -242,8 +274,9 @@ public final class World { * @param entities The entities. * @return {@code true} if all entities were added successfully, otherwise {@code false}. */ - private boolean placeEntities(Entity[] entities) { + private boolean placeEntities(Entity... entities) { boolean success = true; + for (Entity entity : entities) { Sector sector = repository.get(SectorCoordinates.fromPosition(entity.getPosition())); success &= sector.addEntity(entity); @@ -266,6 +299,7 @@ public final class World { */ public boolean register(final Npc npc) { boolean success = npcRepository.add(npc); + if (success) { logger.info("Registered npc: " + npc + " [count=" + npcRepository.size() + "]"); } else { @@ -281,15 +315,17 @@ public final class World { * @return A {@link RegistrationStatus}. */ public RegistrationStatus register(final Player player) { - if (isPlayerOnline(player.getName())) { + if (isPlayerOnline(player.getUsername())) { return RegistrationStatus.ALREADY_ONLINE; } - boolean success = playerRepository.add(player) & players.put(player.getName(), player) == null; + boolean success = playerRepository.add(player); if (success) { + players.put(NameUtil.encodeBase37(player.getUsername().toLowerCase()), player); logger.info("Registered player: " + player + " [count=" + playerRepository.size() + "]"); return RegistrationStatus.OK; } + logger.warning("Failed to register player (server full): " + player + " [count=" + playerRepository.size() + "]"); return RegistrationStatus.WORLD_FULL; @@ -309,7 +345,7 @@ public final class World { * * @param npc The npc. */ - public void unregister(Npc npc) { + public void unregister(final Npc npc) { if (npcRepository.remove(npc)) { logger.info("Unregistered npc: " + npc + " [count=" + npcRepository.size() + "]"); } else { @@ -322,9 +358,10 @@ public final class World { * * @param player The player. */ - public void unregister(Player player) { - if (playerRepository.remove(player) & players.remove(player.getName()) == player) { + public void unregister(final Player player) { + if (playerRepository.remove(player) & players.remove(NameUtil.encodeBase37(player.getUsername().toLowerCase())) == player) { logger.info("Unregistered player: " + player + " [count=" + playerRepository.size() + "]"); + logoutDispatcher.dispatch(player); } else { logger.warning("Could not find player " + player + " to unregister!"); } diff --git a/src/org/apollo/game/model/obj/GameObject.java b/src/org/apollo/game/model/obj/GameObject.java index 52428931..8a01387f 100644 --- a/src/org/apollo/game/model/obj/GameObject.java +++ b/src/org/apollo/game/model/obj/GameObject.java @@ -9,6 +9,7 @@ import org.apollo.game.model.def.ObjectDefinition; * * @author Major */ +@SuppressWarnings("serial") public final class GameObject extends Entity { /** diff --git a/src/org/apollo/game/model/obj/StaticObject.java b/src/org/apollo/game/model/obj/StaticObject.java index c336b1a8..b196e5fd 100644 --- a/src/org/apollo/game/model/obj/StaticObject.java +++ b/src/org/apollo/game/model/obj/StaticObject.java @@ -10,6 +10,7 @@ import org.apollo.game.model.def.ObjectDefinition; * @author Chris Fletcher * @author Major */ +@SuppressWarnings("serial") public final class StaticObject extends Entity { /** diff --git a/src/org/apollo/game/model/settings/PrivacyState.java b/src/org/apollo/game/model/settings/PrivacyState.java index fda23129..1608d9b9 100644 --- a/src/org/apollo/game/model/settings/PrivacyState.java +++ b/src/org/apollo/game/model/settings/PrivacyState.java @@ -38,7 +38,7 @@ public enum PrivacyState { public static PrivacyState valueOf(int value) { PrivacyState[] values = values(); if (value < 0 || value >= values.length) { - throw new IllegalArgumentException("Invalid privacy option integer value specified"); + throw new IllegalArgumentException("Invalid privacy option integer value specified: " + value); } return values[value]; } diff --git a/src/org/apollo/game/model/settings/PrivilegeLevel.java b/src/org/apollo/game/model/settings/PrivilegeLevel.java index fe525034..6ec06efd 100644 --- a/src/org/apollo/game/model/settings/PrivilegeLevel.java +++ b/src/org/apollo/game/model/settings/PrivilegeLevel.java @@ -8,9 +8,9 @@ package org.apollo.game.model.settings; public enum PrivilegeLevel { /** - * An administrator (rights 2) account. + * A standard (rights 0) account. */ - ADMINISTRATOR(2), + STANDARD(0), /** * A player moderator (rights 1) account. @@ -18,9 +18,9 @@ public enum PrivilegeLevel { MODERATOR(1), /** - * A standard (rights 0) account. + * An administrator (rights 2) account. */ - STANDARD(0); + ADMINISTRATOR(2); /** * Gets the privilege level for the specified numerical level. diff --git a/src/org/apollo/game/model/settings/ServerStatus.java b/src/org/apollo/game/model/settings/ServerStatus.java new file mode 100644 index 00000000..905d0a71 --- /dev/null +++ b/src/org/apollo/game/model/settings/ServerStatus.java @@ -0,0 +1,48 @@ +package org.apollo.game.model.settings; + +/** + * Represents the status of the friend server. + * + * @author Major + */ +public enum ServerStatus { + + /** + * Indicates the friend server is offline. + */ + OFFLINE(0), + + /** + * Indicates the friend server is being connected to. + */ + CONNECTING(1), + + /** + * Indicates the friend server is online and connected. + */ + ONLINE(2); + + /** + * The code of the server status. + */ + private final int code; + + /** + * Creates a new server status. + * + * @param code The code. + */ + private ServerStatus(int code) { + this.code = code; + } + + /** + * Gets the code of this server status. + * + * @return The code. + */ + public int getCode() { + return code; + } + +} \ No newline at end of file diff --git a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java index aee51934..03153f04 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerLoader.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerLoader.java @@ -4,6 +4,8 @@ import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import org.apollo.game.model.Appearance; import org.apollo.game.model.Inventory; @@ -20,6 +22,7 @@ import org.apollo.io.player.PlayerLoader; import org.apollo.io.player.PlayerLoaderResponse; import org.apollo.net.codec.login.LoginConstants; import org.apollo.security.PlayerCredentials; +import org.apollo.util.NameUtil; import org.apollo.util.StreamUtil; /** @@ -82,9 +85,9 @@ public final class BinaryPlayerLoader implements PlayerLoader { Player player = new Player(credentials, new Position(x, y, height)); player.setPrivilegeLevel(privilegeLevel); player.setMembers(members); - player.setPublicChatPrivacy(privacyPublicChat); - player.setPrivateChatPrivacy(privacyPrivateChat); - player.setTradeChatPrivacy(privacyTradeCompete); + player.setChatPrivacy(privacyPublicChat); + player.setFriendPrivacy(privacyPrivateChat); + player.setTradePrivacy(privacyTradeCompete); player.setRunEnergy(runEnergy); player.setScreenBrightness(brightness); @@ -111,6 +114,20 @@ public final class BinaryPlayerLoader implements PlayerLoader { skills.startFiringEvents(); } + int friendCount = in.readByte(); + List friends = new ArrayList(friendCount); + for (int i = 0; i < friendCount; i++) { + friends.add(NameUtil.decodeBase37(in.readLong())); + } + player.setFriendUsernames(friends); + + int ignoreCount = in.readByte(); + List ignores = new ArrayList(ignoreCount); + for (int i = 0; i < ignoreCount; i++) { + ignores.add(NameUtil.decodeBase37(in.readLong())); + } + player.setIgnoredUsernames(ignores); + return new PlayerLoaderResponse(LoginConstants.STATUS_OK, player); } } diff --git a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java b/src/org/apollo/io/player/impl/BinaryPlayerSaver.java index 7bb0d726..be680c22 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerSaver.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerSaver.java @@ -4,6 +4,7 @@ import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.List; import org.apollo.game.model.Appearance; import org.apollo.game.model.Inventory; @@ -13,6 +14,7 @@ import org.apollo.game.model.Position; import org.apollo.game.model.Skill; import org.apollo.game.model.SkillSet; import org.apollo.io.player.PlayerSaver; +import org.apollo.util.NameUtil; import org.apollo.util.StreamUtil; /** @@ -24,19 +26,19 @@ public final class BinaryPlayerSaver implements PlayerSaver { @Override public void savePlayer(Player player) throws IOException { - File file = BinaryPlayerUtil.getFile(player.getName()); + File file = BinaryPlayerUtil.getFile(player.getUsername()); try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) { // write credentials and privileges - StreamUtil.writeString(out, player.getName()); + StreamUtil.writeString(out, player.getUsername()); StreamUtil.writeString(out, player.getCredentials().getPassword()); out.writeByte(player.getPrivilegeLevel().toInteger()); out.writeBoolean(player.isMembers()); // write settings - out.writeByte(player.getPublicChatPrivacy().toInteger()); - out.writeByte(player.getPrivateChatPrivacy().toInteger()); - out.writeByte(player.getTradeChatPrivacy().toInteger()); + out.writeByte(player.getChatPrivacy().toInteger()); + out.writeByte(player.getFriendPrivacy().toInteger()); + out.writeByte(player.getTradePrivacy().toInteger()); out.writeByte(player.getRunEnergy()); out.writeByte(player.getScreenBrightness().toInteger()); @@ -73,6 +75,18 @@ public final class BinaryPlayerSaver implements PlayerSaver { out.writeByte(skill.getCurrentLevel()); out.writeDouble(skill.getExperience()); } + + List usernames = player.getFriendUsernames(); + out.writeByte(usernames.size()); + for (String username : usernames) { + out.writeLong(NameUtil.encodeBase37(username)); + } + + usernames = player.getIgnoredUsernames(); + out.writeByte(usernames.size()); + for (String username : usernames) { + out.writeLong(NameUtil.encodeBase37(username)); + } } } diff --git a/src/org/apollo/io/player/impl/BinaryPlayerUtil.java b/src/org/apollo/io/player/impl/BinaryPlayerUtil.java index b0ca7722..85ce31b5 100644 --- a/src/org/apollo/io/player/impl/BinaryPlayerUtil.java +++ b/src/org/apollo/io/player/impl/BinaryPlayerUtil.java @@ -40,6 +40,7 @@ public final class BinaryPlayerUtil { * Default private constructor to prevent instantiation. */ private BinaryPlayerUtil() { + } } \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/AddFriendEventDecoder.java b/src/org/apollo/net/release/r317/AddFriendEventDecoder.java new file mode 100644 index 00000000..43106bd7 --- /dev/null +++ b/src/org/apollo/net/release/r317/AddFriendEventDecoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.event.impl.AddFriendEvent; +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.EventDecoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventDecoder} for the {@link AddFriendEvent}. + * + * @author Major + */ +public final class AddFriendEventDecoder extends EventDecoder { + + @Override + public AddFriendEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new AddFriendEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/AddIgnoreEventDecoder.java b/src/org/apollo/net/release/r317/AddIgnoreEventDecoder.java new file mode 100644 index 00000000..3b78d133 --- /dev/null +++ b/src/org/apollo/net/release/r317/AddIgnoreEventDecoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.event.impl.AddIgnoreEvent; +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.EventDecoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventDecoder} for the {@link AddIgnoreEvent}. + * + * @author Major + */ +public final class AddIgnoreEventDecoder extends EventDecoder { + + @Override + public AddIgnoreEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new AddIgnoreEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/ForwardPrivateMessageEventEncoder.java b/src/org/apollo/net/release/r317/ForwardPrivateMessageEventEncoder.java new file mode 100644 index 00000000..ec50a8ee --- /dev/null +++ b/src/org/apollo/net/release/r317/ForwardPrivateMessageEventEncoder.java @@ -0,0 +1,34 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.event.impl.ForwardPrivateMessageEvent; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.meta.PacketType; +import org.apollo.net.release.EventEncoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventEncoder} for the {@link ForwardPrivateMessageEvent}. + * + * @author Major + */ +public final class ForwardPrivateMessageEventEncoder extends EventEncoder { + + /** + * The amount of messages sent globally, offset by a random variable x, {@code 0 <= x < 100000000}. + */ + private static int messageCount = (int) (Math.random() * 100000000); + + @Override + public GamePacket encode(ForwardPrivateMessageEvent event) { + GamePacketBuilder builder = new GamePacketBuilder(196, PacketType.VARIABLE_BYTE); + + builder.put(DataType.LONG, NameUtil.encodeBase37(event.getSenderUsername())); + builder.put(DataType.INT, messageCount++); + builder.put(DataType.BYTE, event.getSenderPrivilege().toInteger()); + builder.putBytes(event.getMessage()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/FriendServerStatusEventEncoder.java b/src/org/apollo/net/release/r317/FriendServerStatusEventEncoder.java new file mode 100644 index 00000000..73ec2fdc --- /dev/null +++ b/src/org/apollo/net/release/r317/FriendServerStatusEventEncoder.java @@ -0,0 +1,23 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.event.impl.FriendServerStatusEvent; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.EventEncoder; + +/** + * An {@link EventEncoder} for the {@link FriendServerStatusEvent}. + * + * @author Major + */ +public final class FriendServerStatusEventEncoder extends EventEncoder { + + @Override + public GamePacket encode(FriendServerStatusEvent event) { + GamePacketBuilder builder = new GamePacketBuilder(221); + builder.put(DataType.BYTE, event.getStatusCode()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/IgnoreListEventEncoder.java b/src/org/apollo/net/release/r317/IgnoreListEventEncoder.java new file mode 100644 index 00000000..445a08c6 --- /dev/null +++ b/src/org/apollo/net/release/r317/IgnoreListEventEncoder.java @@ -0,0 +1,32 @@ +package org.apollo.net.release.r317; + +import java.util.List; + +import org.apollo.game.event.impl.IgnoreListEvent; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.meta.PacketType; +import org.apollo.net.release.EventEncoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventEncoder} for the {@link IgnoreListEvent}. + * + * @author Major + */ +public final class IgnoreListEventEncoder extends EventEncoder { + + @Override + public GamePacket encode(IgnoreListEvent event) { + GamePacketBuilder builder = new GamePacketBuilder(214, PacketType.VARIABLE_SHORT); + + List usernames = event.getUsernames(); + for (String username : usernames) { + builder.put(DataType.LONG, NameUtil.encodeBase37(username)); + } + + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/PlayerSynchronizationEventEncoder.java b/src/org/apollo/net/release/r317/PlayerSynchronizationEventEncoder.java index 3fb80e67..94810b68 100644 --- a/src/org/apollo/net/release/r317/PlayerSynchronizationEventEncoder.java +++ b/src/org/apollo/net/release/r317/PlayerSynchronizationEventEncoder.java @@ -310,14 +310,14 @@ public final class PlayerSynchronizationEventEncoder extends EventEncoder { + + @Override + public RemoveFriendEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new RemoveFriendEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/RemoveIgnoreEventDecoder.java b/src/org/apollo/net/release/r317/RemoveIgnoreEventDecoder.java new file mode 100644 index 00000000..d43912c1 --- /dev/null +++ b/src/org/apollo/net/release/r317/RemoveIgnoreEventDecoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.event.impl.RemoveIgnoreEvent; +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.EventDecoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventDecoder} for the {@link RemoveIgnoreEvent}. + * + * @author Major + */ +public class RemoveIgnoreEventDecoder extends EventDecoder { + + @Override + public RemoveIgnoreEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new RemoveIgnoreEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/SendFriendEventEncoder.java b/src/org/apollo/net/release/r317/SendFriendEventEncoder.java new file mode 100644 index 00000000..375567c9 --- /dev/null +++ b/src/org/apollo/net/release/r317/SendFriendEventEncoder.java @@ -0,0 +1,25 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.event.impl.SendFriendEvent; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.EventEncoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventEncoder} for the {@link SendFriendEvent}. + * + * @author Major + */ +public final class SendFriendEventEncoder extends EventEncoder { + + @Override + public GamePacket encode(SendFriendEvent event) { + GamePacketBuilder builder = new GamePacketBuilder(50); + builder.put(DataType.LONG, NameUtil.encodeBase37(event.getUsername())); + builder.put(DataType.BYTE, event.getWorld()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r317/SendPrivateMessageEventDecoder.java b/src/org/apollo/net/release/r317/SendPrivateMessageEventDecoder.java new file mode 100644 index 00000000..02d20285 --- /dev/null +++ b/src/org/apollo/net/release/r317/SendPrivateMessageEventDecoder.java @@ -0,0 +1,39 @@ +package org.apollo.net.release.r317; + +import org.apollo.game.event.impl.SendPrivateMessageEvent; +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.EventDecoder; +import org.apollo.util.NameUtil; +import org.apollo.util.TextUtil; + +/** + * An {@link EventDecoder} for the {@link SendPrivateMessageEvent}. + * + * @author Major + */ +public final class SendPrivateMessageEventDecoder extends EventDecoder { + + @Override + public SendPrivateMessageEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + + int length = packet.getLength() - 8; + + byte[] originalCompressed = new byte[length]; + reader.getBytes(originalCompressed); + + String uncompressed = TextUtil.uncompress(originalCompressed, length); + uncompressed = TextUtil.filterInvalidCharacters(uncompressed); + uncompressed = TextUtil.capitalize(uncompressed); + + byte[] recompressed = new byte[length]; + TextUtil.compress(uncompressed, recompressed); + + return new SendPrivateMessageEvent(username, new String(uncompressed), recompressed); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/AddFriendEventDecoder.java b/src/org/apollo/net/release/r377/AddFriendEventDecoder.java new file mode 100644 index 00000000..13ef9247 --- /dev/null +++ b/src/org/apollo/net/release/r377/AddFriendEventDecoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.event.impl.AddFriendEvent; +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.EventDecoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventDecoder} for the {@link AddFriendEvent}. + * + * @author Major + */ +public class AddFriendEventDecoder extends EventDecoder { + + @Override + public AddFriendEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new AddFriendEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/AddIgnoreEventDecoder.java b/src/org/apollo/net/release/r377/AddIgnoreEventDecoder.java new file mode 100644 index 00000000..b3f56782 --- /dev/null +++ b/src/org/apollo/net/release/r377/AddIgnoreEventDecoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.event.impl.AddIgnoreEvent; +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.EventDecoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventDecoder} for the {@link AddIgnoreEvent}. + * + * @author Major + */ +public final class AddIgnoreEventDecoder extends EventDecoder { + + @Override + public AddIgnoreEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new AddIgnoreEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/FriendServerStatusEventEncoder.java b/src/org/apollo/net/release/r377/FriendServerStatusEventEncoder.java new file mode 100644 index 00000000..8a4b92a1 --- /dev/null +++ b/src/org/apollo/net/release/r377/FriendServerStatusEventEncoder.java @@ -0,0 +1,22 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.event.impl.FriendServerStatusEvent; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.EventEncoder; + +/** + * An {@link EventEncoder} for the {@link FriendServerStatusEvent}. + * + * @author Major + */ +public class FriendServerStatusEventEncoder extends EventEncoder { + + @Override + public GamePacket encode(FriendServerStatusEvent event) { + GamePacketBuilder builder = new GamePacketBuilder(251); + builder.put(DataType.BYTE, event.getStatusCode()); + return builder.toGamePacket(); + } +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/IgnoreListEventEncoder.java b/src/org/apollo/net/release/r377/IgnoreListEventEncoder.java new file mode 100644 index 00000000..2eb289e6 --- /dev/null +++ b/src/org/apollo/net/release/r377/IgnoreListEventEncoder.java @@ -0,0 +1,31 @@ +package org.apollo.net.release.r377; + +import java.util.List; + +import org.apollo.game.event.impl.IgnoreListEvent; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.EventEncoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventEncoder} for the {@link IgnoreListEvent}. + * + * @author Major + */ +public final class IgnoreListEventEncoder extends EventEncoder { + + @Override + public GamePacket encode(IgnoreListEvent event) { + GamePacketBuilder builder = new GamePacketBuilder(226); + + List usernames = event.getUsernames(); + for (String username : usernames) { + builder.put(DataType.LONG, NameUtil.encodeBase37(username)); + } + + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/PrivacyOptionEventEncoder.java b/src/org/apollo/net/release/r377/PrivacyOptionEventEncoder.java index 72c699d0..c6534dca 100644 --- a/src/org/apollo/net/release/r377/PrivacyOptionEventEncoder.java +++ b/src/org/apollo/net/release/r377/PrivacyOptionEventEncoder.java @@ -17,9 +17,9 @@ public final class PrivacyOptionEventEncoder extends EventEncoder { + + @Override + public RemoveFriendEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new RemoveFriendEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/RemoveIgnoreEventDecoder.java b/src/org/apollo/net/release/r377/RemoveIgnoreEventDecoder.java new file mode 100644 index 00000000..03b21ba1 --- /dev/null +++ b/src/org/apollo/net/release/r377/RemoveIgnoreEventDecoder.java @@ -0,0 +1,24 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.event.impl.RemoveIgnoreEvent; +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.EventDecoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventDecoder} for the {@link RemoveIgnoreEvent}. + * + * @author Major + */ +public class RemoveIgnoreEventDecoder extends EventDecoder { + + @Override + public RemoveIgnoreEvent decode(GamePacket packet) { + GamePacketReader reader = new GamePacketReader(packet); + String username = NameUtil.decodeBase37(reader.getSigned(DataType.LONG)); + return new RemoveIgnoreEvent(username); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/release/r377/SendFriendEventEncoder.java b/src/org/apollo/net/release/r377/SendFriendEventEncoder.java new file mode 100644 index 00000000..edbfa240 --- /dev/null +++ b/src/org/apollo/net/release/r377/SendFriendEventEncoder.java @@ -0,0 +1,25 @@ +package org.apollo.net.release.r377; + +import org.apollo.game.event.impl.SendFriendEvent; +import org.apollo.net.codec.game.DataType; +import org.apollo.net.codec.game.GamePacket; +import org.apollo.net.codec.game.GamePacketBuilder; +import org.apollo.net.release.EventEncoder; +import org.apollo.util.NameUtil; + +/** + * An {@link EventEncoder} for the {@link SendFriendEvent}. + * + * @author Major + */ +public class SendFriendEventEncoder extends EventEncoder { + + @Override + public GamePacket encode(SendFriendEvent event) { + GamePacketBuilder builder = new GamePacketBuilder(78); + builder.put(DataType.LONG, NameUtil.encodeBase37(event.getUsername())); + builder.put(DataType.BYTE, event.getWorld()); + return builder.toGamePacket(); + } + +} \ No newline at end of file diff --git a/src/org/apollo/net/session/GameSession.java b/src/org/apollo/net/session/GameSession.java index dbd917a9..051c239c 100644 --- a/src/org/apollo/net/session/GameSession.java +++ b/src/org/apollo/net/session/GameSession.java @@ -101,9 +101,7 @@ public final class GameSession extends Session { } } - if (chain == null) { - logger.warning("No chain for event: " + event.getClass().getName() + "."); - } else { + if (chain != null) { try { chain.handle(player, event); } catch (Exception ex) { diff --git a/src/org/apollo/net/session/LoginSession.java b/src/org/apollo/net/session/LoginSession.java index 3a4b81a3..92ae5733 100644 --- a/src/org/apollo/net/session/LoginSession.java +++ b/src/org/apollo/net/session/LoginSession.java @@ -90,7 +90,7 @@ public final class LoginSession extends Session { Player player = response.getPlayer(); int rights = player == null ? 0 : player.getPrivilegeLevel().toInteger(); boolean log = false; - + if (player != null) { GameSession session = new GameSession(channel, serverContext, player); player.setSession(session, false /* TODO */); @@ -99,17 +99,16 @@ public final class LoginSession extends Session { if (registrationStatus != RegistrationStatus.OK) { player = null; + rights = 0; if (registrationStatus == RegistrationStatus.ALREADY_ONLINE) { status = LoginConstants.STATUS_ACCOUNT_ONLINE; } else { status = LoginConstants.STATUS_SERVER_FULL; } - rights = 0; } } ChannelFuture future = channel.writeAndFlush(new LoginResponse(status, rights, log)); - destroy(); if (player != null) { diff --git a/src/org/apollo/util/plugin/PluginContext.java b/src/org/apollo/util/plugin/PluginContext.java index aead3add..1fd43f98 100644 --- a/src/org/apollo/util/plugin/PluginContext.java +++ b/src/org/apollo/util/plugin/PluginContext.java @@ -7,6 +7,8 @@ import org.apollo.game.event.Event; import org.apollo.game.event.handler.EventHandler; import org.apollo.game.event.handler.chain.EventHandlerChain; import org.apollo.game.event.handler.chain.EventHandlerChainGroup; +import org.apollo.game.login.LoginListener; +import org.apollo.game.login.LogoutListener; import org.apollo.game.model.World; import org.apollo.net.release.EventDecoder; import org.apollo.net.release.EventEncoder; @@ -35,7 +37,7 @@ public final class PluginContext { } /** - * Adds a command listener. + * Adds a {@link CommandListener}. * * @param name The name of the listener. * @param listener The listener. @@ -45,7 +47,7 @@ public final class PluginContext { } /** - * Adds an event decoder. + * Adds an {@link EventDecoder}. * * @param The type of decoder. * @param releaseNo The release number. @@ -60,14 +62,14 @@ public final class PluginContext { } /** - * Adds an event encoder. + * Adds an {@link EventEncoder}. * - * @param The type of encoder. + * @param The type of encoder. * @param releaseNo The release number. * @param event The event. * @param encoder The event encoder. */ - public void addEventEncoder(int releaseNo, Class event, EventEncoder encoder) { + public void addEventEncoder(int releaseNo, Class event, EventEncoder encoder) { Release release = context.getRelease(); if (release.getReleaseNumber() == releaseNo) { release.register(event, encoder); @@ -75,16 +77,39 @@ public final class PluginContext { } /** - * Adds an event handler to the end of the chain. + * Adds an {@link EventHandler} to the end of the chain. * - * @param The type of event. + * @param The type of event. * @param event The event. * @param handler The handler. */ - public void addLastEventHandler(Class event, EventHandler handler) { + public void addLastEventHandler(Class event, EventHandler handler) { EventHandlerChainGroup chains = context.getService(GameService.class).getEventHandlerChains(); - EventHandlerChain chain = chains.getChain(event); - chain.addLast(handler); + EventHandlerChain chain = chains.getChain(event); + if (chain == null) { + chain = new EventHandlerChain(handler); + chains.register(event, chain); + } else { + chain.addLast(handler); + } + } + + /** + * Adds a {@link LoginListener}. + * + * @param listener The listener. + */ + public void addLoginListener(LoginListener listener) { + World.getWorld().getLoginDispatcher().register(listener); + } + + /** + * Adds a {@link LogoutListener}. + * + * @param listener The listener. + */ + public void addLogoutListener(LogoutListener listener) { + World.getWorld().getLogoutDispatcher().register(listener); } } \ No newline at end of file