mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 08:39:11 +00:00
Merge branch 'master' into pathfinding.
This commit is contained in:
+11
-10
@@ -107,18 +107,19 @@ public final class Server {
|
||||
* @param jagGrabAddress The JAGGRAB address to bind to.
|
||||
*/
|
||||
public void bind(SocketAddress serviceAddress, SocketAddress httpAddress, SocketAddress jagGrabAddress) {
|
||||
logger.fine("Binding service listener to address: " + serviceAddress + "...");
|
||||
serviceBootstrap.bind(serviceAddress);
|
||||
|
||||
logger.fine("Binding HTTP listener to address: " + httpAddress + "...");
|
||||
try {
|
||||
httpBootstrap.bind(httpAddress);
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.WARNING, "Binding to HTTP failed: client will use JAGGRAB as a fallback (not recommended)!", t);
|
||||
}
|
||||
logger.fine("Binding service listener to address: " + serviceAddress + "...");
|
||||
serviceBootstrap.bind(serviceAddress).sync();
|
||||
|
||||
logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
|
||||
jagGrabBootstrap.bind(jagGrabAddress);
|
||||
logger.fine("Binding HTTP listener to address: " + httpAddress + "...");
|
||||
httpBootstrap.bind(httpAddress).sync();
|
||||
|
||||
logger.fine("Binding JAGGRAB listener to address: " + jagGrabAddress + "...");
|
||||
jagGrabBootstrap.bind(jagGrabAddress).sync();
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "Binding to a port failed: ensure apollo isn't already running.", e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
logger.info("Ready for connections.");
|
||||
}
|
||||
|
||||
@@ -148,14 +148,20 @@ public final class GameService extends Service {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a player (may block!).
|
||||
* Registers a {@link Player} (may block!).
|
||||
*
|
||||
* @param player The player.
|
||||
* @param player The Player.
|
||||
* @param session The {@link GameSession} of the Player.
|
||||
* @return A {@link RegistrationStatus}.
|
||||
*/
|
||||
public RegistrationStatus registerPlayer(Player player) {
|
||||
public RegistrationStatus registerPlayer(Player player, GameSession session) {
|
||||
synchronized (this) {
|
||||
return World.getWorld().register(player);
|
||||
RegistrationStatus status = World.getWorld().register(player);
|
||||
if (status == RegistrationStatus.OK) {
|
||||
player.setSession(session);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apollo.game.command;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.entity.setting.PrivilegeLevel;
|
||||
|
||||
/**
|
||||
* An interface which should be implemented to listen to {@link Command}s.
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package org.apollo.game.login;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
/**
|
||||
* A class that dispatches {@link Player}s to {@link LoginListener}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class LoginDispatcher {
|
||||
|
||||
/**
|
||||
* A {@link List} of login listeners.
|
||||
*/
|
||||
private List<LoginListener> 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.apollo.game.login;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
/**
|
||||
* A class that should be extended for actions that should be executed when the player logs in.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface LoginListener {
|
||||
|
||||
/**
|
||||
* Executes the action for this listener.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
public abstract void execute(Player player);
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package org.apollo.game.login;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
/**
|
||||
* A class that dispatches {@link Player}s to {@link LogoutListener}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class LogoutDispatcher {
|
||||
|
||||
/**
|
||||
* A {@link List} of logout listeners.
|
||||
*/
|
||||
private List<LogoutListener> 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.apollo.game.login;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
/**
|
||||
* An interface that should be implemented for actions that should be executed when the player logs out.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface LogoutListener {
|
||||
|
||||
/**
|
||||
* Executes the action for this listener.
|
||||
*
|
||||
* @param player The player.
|
||||
*/
|
||||
public abstract void execute(Player player);
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Contains login and logout listeners.
|
||||
*/
|
||||
package org.apollo.game.login;
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.apollo.game.message.handler;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
@@ -7,6 +11,7 @@ import org.apollo.game.model.entity.Player;
|
||||
* A chain of message handlers.
|
||||
*
|
||||
* @author Graham
|
||||
* @author Ryley
|
||||
* @param <M> The type of message handled by this chain.
|
||||
*/
|
||||
public final class MessageHandlerChain<M extends Message> {
|
||||
@@ -14,7 +19,7 @@ public final class MessageHandlerChain<M extends Message> {
|
||||
/**
|
||||
* The handlers.
|
||||
*/
|
||||
private MessageHandler<M>[] handlers;
|
||||
private final Deque<MessageHandler<M>> handlers;
|
||||
|
||||
/**
|
||||
* Creates the message handler chain.
|
||||
@@ -23,7 +28,7 @@ public final class MessageHandlerChain<M extends Message> {
|
||||
*/
|
||||
@SafeVarargs
|
||||
public MessageHandlerChain(MessageHandler<M>... handlers) {
|
||||
this.handlers = handlers;
|
||||
this.handlers = new ArrayDeque<>(Arrays.asList(handlers));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,36 +36,24 @@ public final class MessageHandlerChain<M extends Message> {
|
||||
*
|
||||
* @param handler The handler.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addLast(MessageHandler<M> handler) {
|
||||
MessageHandler<M>[] old = handlers;
|
||||
handlers = new MessageHandler[old.length + 1];
|
||||
System.arraycopy(old, 0, handlers, 0, old.length);
|
||||
handlers[old.length] = handler;
|
||||
handlers.addLast(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the message, passing it down the chain until the chain is broken or the message reaches the end of the
|
||||
* chain.
|
||||
* Handles the message, passing it down the chain until the chain is broken
|
||||
* or the message reaches the end of the chain.
|
||||
*
|
||||
* @param player The player.
|
||||
* @param message The message.
|
||||
*/
|
||||
public void handle(Player player, M message) {
|
||||
final boolean[] running = new boolean[1];
|
||||
running[0] = true;
|
||||
|
||||
MessageHandlerContext ctx = new MessageHandlerContext() {
|
||||
|
||||
@Override
|
||||
public void breakHandlerChain() {
|
||||
running[0] = false;
|
||||
}
|
||||
};
|
||||
MessageHandlerContext context = new MessageHandlerContext();
|
||||
|
||||
for (MessageHandler<M> handler : handlers) {
|
||||
handler.handle(ctx, player, message);
|
||||
if (!running[0]) {
|
||||
handler.handle(context, player, message);
|
||||
|
||||
if (context.isBroken()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,34 @@
|
||||
package org.apollo.game.message.handler;
|
||||
|
||||
/**
|
||||
* Provides operations specific to a {@link MessageHandler} in a {@link MessageHandlerChain}.
|
||||
* Provides operations specific to a {@link MessageHandler} in a
|
||||
* {@link MessageHandlerChain}.
|
||||
*
|
||||
* @author Graham
|
||||
* @author Ryley
|
||||
*/
|
||||
public abstract class MessageHandlerContext {
|
||||
public final class MessageHandlerContext {
|
||||
|
||||
/**
|
||||
* Denotes whether or not this handler chain is broken.
|
||||
*/
|
||||
private boolean broken;
|
||||
|
||||
/**
|
||||
* Breaks the handler chain.
|
||||
*/
|
||||
public abstract void breakHandlerChain();
|
||||
public void breakHandlerChain() {
|
||||
broken = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this handler chain is broken.
|
||||
*
|
||||
* @return {@code true} if this handler chain is broken, otherwise
|
||||
* {@code false}.
|
||||
*/
|
||||
public boolean isBroken() {
|
||||
return broken;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import org.apollo.util.LanguageUtil;
|
||||
*
|
||||
* @author Major
|
||||
* @author Graham
|
||||
* @author Ryley Kimmel <ryley.kimmel@live.com>
|
||||
* @author Ryley
|
||||
*/
|
||||
public final class EquipItemHandler extends MessageHandler<ItemOptionMessage> {
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ public final class PlayerDesignMessageHandler extends MessageHandler<PlayerDesig
|
||||
@Override
|
||||
public void handle(MessageHandlerContext ctx, Player player, PlayerDesignMessage message) {
|
||||
player.setAppearance(message.getAppearance());
|
||||
player.setNew(true);
|
||||
player.send(new CloseInterfaceMessage());
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.apollo.game.message.handler.MessageHandlerContext;
|
||||
import org.apollo.game.message.impl.PlayerDesignMessage;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.setting.Gender;
|
||||
import org.apollo.game.model.entity.setting.Gender;
|
||||
|
||||
/**
|
||||
* A {@link MessageHandler} that verifies {@link PlayerDesignMessage}s.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class FlashTabInterfaceMessage extends Message {
|
||||
|
||||
/**
|
||||
* The id of the tab to flash.
|
||||
*/
|
||||
private final int tab;
|
||||
|
||||
/**
|
||||
* Creates the FlashTabInterfaceMessage.
|
||||
*
|
||||
* @param tab The id of the tab to flash.
|
||||
*/
|
||||
public FlashTabInterfaceMessage(int tab) {
|
||||
this.tab = tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the tab to flash.
|
||||
*
|
||||
* @return The id.
|
||||
*/
|
||||
public int getTab() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent by the client indicating a flashing tab has been clicked.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class FlashingTabClickedMessage extends Message {
|
||||
|
||||
/**
|
||||
* The tab that was clicked.
|
||||
*/
|
||||
private final int tab;
|
||||
|
||||
/**
|
||||
* Creates the FlashingTabClickedMessage.
|
||||
*
|
||||
* @param tab The tab that was clicked.
|
||||
*/
|
||||
public FlashingTabClickedMessage(int tab) {
|
||||
this.tab = tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the tab that was clicked.
|
||||
*
|
||||
* @return The tab index.
|
||||
*/
|
||||
public int getTab() {
|
||||
return tab;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.entity.setting.PrivilegeLevel;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client that forwards a private chat.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.setting.ServerStatus;
|
||||
import org.apollo.game.model.entity.setting.ServerStatus;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to update the friend server status.
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.apollo.game.model.Position;
|
||||
*/
|
||||
public final class HintIconMessage extends Message {
|
||||
|
||||
// TODO identify the other types and use an enum.
|
||||
// TODO identify the other types.
|
||||
|
||||
/**
|
||||
* The type of a HintIcon.
|
||||
@@ -75,6 +75,24 @@ public final class HintIconMessage extends Message {
|
||||
return new HintIconMessage(Type.PLAYER, Optional.of(index), Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HintIconMessage that removes the current Npc hint icon.
|
||||
*
|
||||
* @return The HintIconMessage.
|
||||
*/
|
||||
public static HintIconMessage resetNpc() {
|
||||
return forNpc(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a HintIconMessage that removes the current Player hint icon.
|
||||
*
|
||||
* @return The HintIconMessage.
|
||||
*/
|
||||
public static HintIconMessage resetPlayer() {
|
||||
return forPlayer(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* The index of the Mob, if applicable.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.entity.setting.MembershipStatus;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client that specifies the local id and membership status of the current player.
|
||||
@@ -15,17 +16,17 @@ public final class IdAssignmentMessage extends Message {
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* The membership flag.
|
||||
* The MembershipStatus.
|
||||
*/
|
||||
private final boolean members;
|
||||
private final MembershipStatus members;
|
||||
|
||||
/**
|
||||
* Creates the local id message.
|
||||
*
|
||||
* @param id The id.
|
||||
* @param members The membership flag.
|
||||
* @param members The MembershipStatus.
|
||||
*/
|
||||
public IdAssignmentMessage(int id, boolean members) {
|
||||
public IdAssignmentMessage(int id, MembershipStatus members) {
|
||||
this.id = id;
|
||||
this.members = members;
|
||||
}
|
||||
@@ -40,12 +41,12 @@ public final class IdAssignmentMessage extends Message {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the membership flag.
|
||||
* Gets whether or not the Player is a {@link MembershipStatus#PAID paying member}.
|
||||
*
|
||||
* @return The membership flag.
|
||||
* @return {@code true} if the Player is a paying member, {@code false} if not.
|
||||
*/
|
||||
public boolean isMembers() {
|
||||
return members;
|
||||
return members == MembershipStatus.PAID;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client that opens a dialogue interface (an interface that appears in the chat box).
|
||||
*
|
||||
* @author Chris Fletcher
|
||||
*/
|
||||
public final class OpenDialogueOverlayMessage extends Message {
|
||||
|
||||
/**
|
||||
* The interface id.
|
||||
*/
|
||||
private final int interfaceId;
|
||||
|
||||
/**
|
||||
* Creates a new message with the specified interface id.
|
||||
*
|
||||
* @param interfaceId The interface id.
|
||||
*/
|
||||
public OpenDialogueOverlayMessage(int interfaceId) {
|
||||
this.interfaceId = interfaceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the interface id.
|
||||
*
|
||||
* @return The interface id.
|
||||
*/
|
||||
public int getInterfaceId() {
|
||||
return interfaceId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package org.apollo.game.message.impl;
|
||||
import org.apollo.game.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to open an interface and temporary sidebar overlay.
|
||||
* A {@link Message} sent to the client to open an interface and a sidebar.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
@@ -20,7 +20,7 @@ public final class OpenInterfaceSidebarMessage extends Message {
|
||||
private final int sidebarId;
|
||||
|
||||
/**
|
||||
* Creates the open interface sidebar message.
|
||||
* Creates the OpenInterfaceSidebarMessage.
|
||||
*
|
||||
* @param interfaceId The interface id.
|
||||
* @param sidebarId The sidebar id.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to open an overlay interface.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenOverlayMessage extends Message {
|
||||
|
||||
/**
|
||||
* The overlay id.
|
||||
*/
|
||||
private final int overlayId;
|
||||
|
||||
/**
|
||||
* Creates the OpenSidebarMessage.
|
||||
*
|
||||
* @param overlayId The overlay id.
|
||||
*/
|
||||
public OpenOverlayMessage(int overlayId) {
|
||||
this.overlayId = overlayId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overlay id.
|
||||
*
|
||||
* @return The overlay id.
|
||||
*/
|
||||
public int getOverlayId() {
|
||||
return overlayId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent to the client to open a sidebar interface.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenSidebarMessage extends Message {
|
||||
|
||||
/**
|
||||
* The sidebar id.
|
||||
*/
|
||||
private final int sidebarId;
|
||||
|
||||
/**
|
||||
* Creates the OpenSidebarMessage.
|
||||
*
|
||||
* @param sidebarId The sidebar id.
|
||||
*/
|
||||
public OpenSidebarMessage(int sidebarId) {
|
||||
this.sidebarId = sidebarId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sidebar id.
|
||||
*
|
||||
* @return The sidebar id.
|
||||
*/
|
||||
public int getSidebarId() {
|
||||
return sidebarId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apollo.game.message.impl;
|
||||
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.model.setting.PrivacyState;
|
||||
import org.apollo.game.model.entity.setting.PrivacyState;
|
||||
|
||||
/**
|
||||
* A {@link Message} sent both by and to the client to update the public chat, private (friend) chat, and trade chat
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.apollo.game.model;
|
||||
|
||||
import org.apollo.game.model.setting.Gender;
|
||||
import org.apollo.game.model.entity.setting.Gender;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ import org.apollo.fs.decoder.ItemDefinitionDecoder;
|
||||
import org.apollo.fs.decoder.NpcDefinitionDecoder;
|
||||
import org.apollo.fs.decoder.ObjectDefinitionDecoder;
|
||||
import org.apollo.game.command.CommandDispatcher;
|
||||
import org.apollo.game.login.LoginDispatcher;
|
||||
import org.apollo.game.login.LogoutDispatcher;
|
||||
import org.apollo.game.model.area.Sector;
|
||||
import org.apollo.game.model.area.SectorRepository;
|
||||
import org.apollo.game.model.def.EquipmentDefinition;
|
||||
@@ -27,6 +25,9 @@ import org.apollo.game.model.entity.Entity;
|
||||
import org.apollo.game.model.entity.GameObject;
|
||||
import org.apollo.game.model.entity.Npc;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.event.Event;
|
||||
import org.apollo.game.model.event.EventListener;
|
||||
import org.apollo.game.model.event.EventListenerChainSet;
|
||||
import org.apollo.game.scheduling.ScheduledTask;
|
||||
import org.apollo.game.scheduling.Scheduler;
|
||||
import org.apollo.io.EquipmentDefinitionParser;
|
||||
@@ -92,14 +93,9 @@ public final class World {
|
||||
private final CommandDispatcher commandDispatcher = new CommandDispatcher();
|
||||
|
||||
/**
|
||||
* The login dispatcher.
|
||||
* The EventListenerChainSet for this World.
|
||||
*/
|
||||
private final LoginDispatcher loginDispatcher = new LoginDispatcher();
|
||||
|
||||
/**
|
||||
* The logout dispatcher.
|
||||
*/
|
||||
private final LogoutDispatcher logoutDispatcher = new LogoutDispatcher();
|
||||
private final EventListenerChainSet events = new EventListenerChainSet();
|
||||
|
||||
/**
|
||||
* The {@link MobRepository} of {@link Npc}s.
|
||||
@@ -152,24 +148,6 @@ public final class World {
|
||||
return commandDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link LoginDispatcher}.
|
||||
*
|
||||
* @return The dispatcher.
|
||||
*/
|
||||
public LoginDispatcher getLoginDispatcher() {
|
||||
return loginDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link LogoutDispatcher}.
|
||||
*
|
||||
* @return The dispatcher.
|
||||
*/
|
||||
public LogoutDispatcher getLogoutDispatcher() {
|
||||
return logoutDispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the npc repository.
|
||||
*
|
||||
@@ -279,12 +257,13 @@ public final class World {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entities to sectors in the {@link SectorRepository}.
|
||||
* Adds an {@link EventListener}, listening for an {@link Event} of the specified type.
|
||||
*
|
||||
* @param entities The entities.
|
||||
* @param type The type of the Event.
|
||||
* @param listener The EventListener.
|
||||
*/
|
||||
private void placeEntities(Entity... entities) {
|
||||
Arrays.stream(entities).forEach(entity -> sectors.fromPosition(entity.getPosition()).addEntity(entity));
|
||||
public <E extends Event> void listenFor(Class<E> type, EventListener<E> listener) {
|
||||
events.putListener(type, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,6 +327,16 @@ public final class World {
|
||||
return scheduler.schedule(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the specified {@link Event}, passing it to the listeners..
|
||||
*
|
||||
* @param event The Event.
|
||||
* @return {@code true} if the Event should proceed, {@code false} if not.
|
||||
*/
|
||||
public boolean submit(Event event) {
|
||||
return events.notify(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the specified {@link Npc}.
|
||||
*
|
||||
@@ -375,11 +364,18 @@ public final class World {
|
||||
|
||||
Sector sector = sectors.fromPosition(player.getPosition());
|
||||
sector.removeEntity(player);
|
||||
|
||||
logoutDispatcher.dispatch(player);
|
||||
} else {
|
||||
logger.warning("Could not find player " + player + " to unregister!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entities to sectors in the {@link SectorRepository}.
|
||||
*
|
||||
* @param entities The entities.
|
||||
*/
|
||||
private void placeEntities(Entity... entities) {
|
||||
Arrays.stream(entities).forEach(entity -> sectors.fromPosition(entity.getPosition()).addEntity(entity));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apollo.game.model.Direction;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.area.collision.CollisionMatrix;
|
||||
import org.apollo.game.model.entity.Entity;
|
||||
import org.apollo.game.model.entity.Entity.EntityType;
|
||||
|
||||
@@ -23,7 +25,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
public final class Sector {
|
||||
|
||||
/**
|
||||
* The width and length of a sector, in tiles.
|
||||
* The width and length of a Sector, in tiles.
|
||||
*/
|
||||
public static final int SECTOR_SIZE = 8;
|
||||
|
||||
@@ -33,20 +35,25 @@ public final class Sector {
|
||||
private static final int DEFAULT_SET_SIZE = 2;
|
||||
|
||||
/**
|
||||
* The sector coordinates of this sector.
|
||||
* The SectorCoordinates of this Sector.
|
||||
*/
|
||||
private final SectorCoordinates coordinates;
|
||||
|
||||
/**
|
||||
* A map of positions to entities in that position.
|
||||
* The Map of Positions to Entities in that Position.
|
||||
*/
|
||||
private final Map<Position, Set<Entity>> entities = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A list of listeners registered to this sector.
|
||||
* A List of SectorListeners registered to this Sector.
|
||||
*/
|
||||
private final List<SectorListener> listeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The CollisionMatrix.
|
||||
*/
|
||||
private final CollisionMatrix[] matrices = CollisionMatrix.createMatrices(Position.HEIGHT_LEVELS, SECTOR_SIZE, SECTOR_SIZE);
|
||||
|
||||
/**
|
||||
* Creates a new sector.
|
||||
*
|
||||
@@ -67,28 +74,29 @@ public final class Sector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link Entity} from to sector. Note that this does not spawn the entity, or do any other action other than
|
||||
* Adds a {@link Entity} from to sector. Note that this does not spawn the Entity, or do any other action other than
|
||||
* register it to this sector.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @throws IllegalArgumentException If the entity does not belong in this sector.
|
||||
* @param entity The Entity.
|
||||
* @throws IllegalArgumentException If the Entity does not belong in this sector.
|
||||
*/
|
||||
public void addEntity(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
checkPosition(position);
|
||||
Set<Entity> local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
|
||||
|
||||
Set<Entity> local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
|
||||
local.add(entity);
|
||||
|
||||
notifyListeners(entity, SectorOperation.ADD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this sector contains the specified entity.
|
||||
* Checks if this sector contains the specified Entity.
|
||||
* <p>
|
||||
* This method operates in constant time.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @return {@code true} if this sector contains the entity, otherwise {@code false}.
|
||||
* @param entity The Entity.
|
||||
* @return {@code true} if this sector contains the Entity, otherwise {@code false}.
|
||||
*/
|
||||
public boolean contains(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
@@ -114,12 +122,13 @@ public final class Sector {
|
||||
* @return The list.
|
||||
*/
|
||||
public Set<Entity> getEntities(Position position) {
|
||||
return ImmutableSet.copyOf(entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE)));
|
||||
Set<Entity> set = entities.get(position);
|
||||
return (set == null) ? ImmutableSet.of() : ImmutableSet.copyOf(set);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a shallow copy of the {@link Set} of {@link Entity}s with the specified {@link EntityType}. The returned
|
||||
* type will be immutable. Type will be inferred from the call, so ensure that the entity type and the reference
|
||||
* type will be immutable. Type will be inferred from the call, so ensure that the Entity type and the reference
|
||||
* correspond, or this method will fail at runtime.
|
||||
*
|
||||
* @param position The {@link Position} containing the entities.
|
||||
@@ -127,21 +136,35 @@ public final class Sector {
|
||||
* @return The set of entities.
|
||||
*/
|
||||
public <T extends Entity> Set<T> getEntities(Position position, EntityType type) {
|
||||
Set<Entity> local = entities.computeIfAbsent(position, key -> new HashSet<>(DEFAULT_SET_SIZE));
|
||||
Set<Entity> local = entities.get(position);
|
||||
if (local == null) {
|
||||
return ImmutableSet.of();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<T> filtered = (Set<T>) local.stream().filter(entity -> entity.getEntityType() == type).collect(Collectors.toSet());
|
||||
Set<T> filtered = (Set<T>) local.stream().filter(Entity -> Entity.getEntityType() == type).collect(Collectors.toSet());
|
||||
return ImmutableSet.copyOf(filtered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the {@link Entity} that was in the specified {@code old} {@link Position}, to the current position of the
|
||||
* entity.
|
||||
* <p>
|
||||
* Both the {@code old} and current positions of the entity must belong to this sector.
|
||||
* Gets the {@link CollisionMatrix} at the specified height level.
|
||||
*
|
||||
* @param old The old position of the entity.
|
||||
* @param entity The entity to move.
|
||||
* @param height The height level.
|
||||
* @return The CollisionMatrix.
|
||||
*/
|
||||
public CollisionMatrix getMatrix(int height) {
|
||||
Preconditions.checkElementIndex(height, matrices.length, "Matrix height level must be [0, " + matrices.length + ").");
|
||||
return matrices[height];
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the {@link Entity} that was in the specified {@code old} {@link Position}, to the current position of the
|
||||
* Entity.
|
||||
* <p>
|
||||
* Both the {@code old} and current positions of the Entity must belong to this sector.
|
||||
*
|
||||
* @param old The old position of the Entity.
|
||||
* @param entity The Entity to move.
|
||||
* @throws IllegalArgumentException If either of the positions do not belong to this sector.
|
||||
*/
|
||||
public void moveEntity(Position old, Entity entity) {
|
||||
@@ -175,8 +198,8 @@ public final class Sector {
|
||||
/**
|
||||
* Removes a {@link Entity} from this sector.
|
||||
*
|
||||
* @param entity The entity.
|
||||
* @throws IllegalArgumentException If the entity does not belong in this sector, or if it was never added.
|
||||
* @param entity The Entity.
|
||||
* @throws IllegalArgumentException If the Entity does not belong in this sector, or if it was never added.
|
||||
*/
|
||||
public void removeEntity(Entity entity) {
|
||||
Position position = entity.getPosition();
|
||||
@@ -191,6 +214,22 @@ public final class Sector {
|
||||
notifyListeners(entity, SectorOperation.REMOVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not an Entity of the specified {@link EntityType type} can traverse the tile at the specified
|
||||
* coordinate pair.
|
||||
*
|
||||
* @param position The {@link Position} of the tile.
|
||||
* @param entity The {@link EntityType}.
|
||||
* @param direction The {@link Direction} the Entity is approaching from.
|
||||
* @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not.
|
||||
*/
|
||||
public boolean traversable(Position position, EntityType entity, Direction direction) {
|
||||
CollisionMatrix matrix = matrices[position.getHeight()];
|
||||
int x = position.getLocalX(), y = position.getLocalY();
|
||||
|
||||
return matrix.traversable(x, y, entity, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the specified {@link Position} is included in this sector.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.apollo.game.model.area.collision;
|
||||
|
||||
/**
|
||||
* A type of flag in a {@link CollisionMatrix}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public enum CollisionFlag {
|
||||
|
||||
/**
|
||||
* The walk north flag.
|
||||
*/
|
||||
MOB_NORTH(0),
|
||||
|
||||
/**
|
||||
* The walk east flag.
|
||||
*/
|
||||
MOB_EAST(1),
|
||||
|
||||
/**
|
||||
* The walk south flag.
|
||||
*/
|
||||
MOB_SOUTH(2),
|
||||
|
||||
/**
|
||||
* The walk west flag.
|
||||
*/
|
||||
MOB_WEST(3),
|
||||
|
||||
/**
|
||||
* The projectile north flag.
|
||||
*/
|
||||
PROJECTILE_NORTH(4),
|
||||
|
||||
/**
|
||||
* The projectile east flag.
|
||||
*/
|
||||
PROJECTILE_EAST(5),
|
||||
|
||||
/**
|
||||
* The projectile south flag.
|
||||
*/
|
||||
PROJECTILE_SOUTH(6),
|
||||
|
||||
/**
|
||||
* The projectile west flag.
|
||||
*/
|
||||
PROJECTILE_WEST(7);
|
||||
|
||||
/**
|
||||
* Returns an array of CollisionFlags that indicate if a Mob can traverse over a tile.
|
||||
*
|
||||
* @return The array of CollisionFlags.
|
||||
*/
|
||||
public static CollisionFlag[] mobs() {
|
||||
return new CollisionFlag[] { MOB_NORTH, MOB_EAST, MOB_SOUTH, MOB_WEST };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of CollisionFlags that indicate if a Projectile can traverse over a tile.
|
||||
*
|
||||
* @return The array of CollisionFlags.
|
||||
*/
|
||||
public static CollisionFlag[] projectiles() {
|
||||
return new CollisionFlag[] { PROJECTILE_NORTH, PROJECTILE_EAST, PROJECTILE_SOUTH, PROJECTILE_WEST };
|
||||
}
|
||||
|
||||
/**
|
||||
* The index of the bit this flag is stored in.
|
||||
*/
|
||||
private final int bit;
|
||||
|
||||
/**
|
||||
* Creates the CollisionFlag.
|
||||
*
|
||||
* @param bit The index of the bit this flag is stored in.
|
||||
*/
|
||||
private CollisionFlag(int bit) {
|
||||
this.bit = bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this CollisionFlag, as a {@code byte}.
|
||||
*
|
||||
* @return The value, as a {@code byte}.
|
||||
*/
|
||||
public byte asByte() {
|
||||
return (byte) (1 << bit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the bit this flag is stored in.
|
||||
*
|
||||
* @return The index of the bit.
|
||||
*/
|
||||
public int getBit() {
|
||||
return bit;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package org.apollo.game.model.area.collision;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apollo.game.model.Direction;
|
||||
import org.apollo.game.model.entity.Entity.EntityType;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* A 2-dimensional adjacency matrix containing tile collision data.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class CollisionMatrix {
|
||||
|
||||
/**
|
||||
* Creates an array of CollisionMatrix objects, all of the specified width and length.
|
||||
*
|
||||
* @param count The length of the array to create.
|
||||
* @param width The width of each CollisionMatrix.
|
||||
* @param length The length of each CollisionMatrix.
|
||||
* @return The array of CollisionMatrix objects.
|
||||
*/
|
||||
public static CollisionMatrix[] createMatrices(int count, int width, int length) {
|
||||
CollisionMatrix[] matrices = new CollisionMatrix[count];
|
||||
Arrays.setAll(matrices, index -> new CollisionMatrix(width, length));
|
||||
return matrices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that all types of traversal are allowed.
|
||||
*/
|
||||
private static final byte ALL_ALLOWED = 0b0000_0000;
|
||||
|
||||
/**
|
||||
* Indicates that no types of traversal are allowed.
|
||||
*/
|
||||
private static final byte ALL_BLOCKED = (byte) 0b1111_1111;
|
||||
|
||||
/**
|
||||
* The length of the matrix.
|
||||
*/
|
||||
private final int length;
|
||||
|
||||
/**
|
||||
* The collision matrix, as a {@code byte} array.
|
||||
*/
|
||||
private final byte[] matrix;
|
||||
|
||||
/**
|
||||
* The width of the matrix.
|
||||
*/
|
||||
private final int width;
|
||||
|
||||
/**
|
||||
* Creates the CollisionMatrix.
|
||||
*
|
||||
* @param width The width of the matrix.
|
||||
* @param length The length of the matrix.
|
||||
*/
|
||||
public CollisionMatrix(int width, int length) {
|
||||
this.width = width;
|
||||
this.length = length;
|
||||
matrix = new byte[width * length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not <strong>all</strong> of the specified {@link CollisionFlag}s are set for the specified
|
||||
* coordinate pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param flags The CollisionFlags.
|
||||
* @return {@code true} if all of the CollisionFlags are set, otherwise {@code false}.
|
||||
*/
|
||||
public boolean all(int x, int y, CollisionFlag... flags) {
|
||||
for (CollisionFlag flag : flags) {
|
||||
if ((get(x, y) & flag.asByte()) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not <strong>any</strong> of the specified {@link CollisionFlag}s are set for the specified
|
||||
* coordinate pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param flags The CollisionFlags.
|
||||
* @return {@code true} if any of the CollisionFlags are set, otherwise {@code false}.
|
||||
*/
|
||||
public boolean any(int x, int y, CollisionFlag... flags) {
|
||||
for (CollisionFlag flag : flags) {
|
||||
if ((get(x, y) & flag.asByte()) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely blocks the tile at the specified coordinate pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
*/
|
||||
public void block(int x, int y) {
|
||||
set(x, y, ALL_BLOCKED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears (i.e. sets to {@code false}) the value of the specified {@link CollisionFlag} for the specified coordinate
|
||||
* pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param flag The CollisionFlag.
|
||||
*/
|
||||
public void clear(int x, int y, CollisionFlag flag) {
|
||||
set(x, y, (byte) ~flag.asByte());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified {@link CollisionFlag} is set for the specified coordinate pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param flag The CollisionFlag.
|
||||
* @return {@code true} if the CollisionFlag is set, {@code false} if not.
|
||||
*/
|
||||
public boolean flagged(int x, int y, CollisionFlag flag) {
|
||||
return (get(x, y) & flag.asByte()) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the specified tile.
|
||||
*
|
||||
* @param x The x coordinate of the tile.
|
||||
* @param y The y coordinate of the tile.
|
||||
* @return The value.
|
||||
*/
|
||||
public int get(int x, int y) {
|
||||
return matrix[indexOf(x, y)] & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the cell of the specified coordinate pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
*/
|
||||
public void reset(int x, int y) {
|
||||
set(x, y, ALL_ALLOWED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets (i.e. sets to {@code true}) the value of the specified {@link CollisionFlag} for the specified coordinate
|
||||
* pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param flag The CollisionFlag.
|
||||
*/
|
||||
public void set(int x, int y, CollisionFlag flag) {
|
||||
set(x, y, flag.asByte());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("width", width).add("length", length).add("matrix", Arrays.toString(matrix))
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not an Entity of the specified {@link EntityType type} can traverse the tile at the specified
|
||||
* coordinate pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param entity The {@link EntityType}.
|
||||
* @param direction The {@link Direction} the Entity is approaching from.
|
||||
* @return {@code true} if the tile at the specified coordinate pair is traversable, {@code false} if not.
|
||||
*/
|
||||
public boolean traversable(int x, int y, EntityType entity, Direction direction) {
|
||||
CollisionFlag[] flags = CollisionFlag.forType(entity);
|
||||
int north = 0, east = 1, south = 2, west = 3;
|
||||
|
||||
switch (direction) {
|
||||
case NORTH_WEST:
|
||||
return any(x, y, flags[south], flags[east]);
|
||||
case NORTH:
|
||||
return flagged(x, y, flags[south]);
|
||||
case NORTH_EAST:
|
||||
return any(x, y, flags[south], flags[west]);
|
||||
case EAST:
|
||||
return flagged(x, y, flags[west]);
|
||||
case SOUTH_EAST:
|
||||
return any(x, y, flags[north], flags[west]);
|
||||
case SOUTH:
|
||||
return flagged(x, y, flags[north]);
|
||||
case SOUTH_WEST:
|
||||
return any(x, y, flags[north], flags[east]);
|
||||
case WEST:
|
||||
return flagged(x, y, flags[east]);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unrecognised direction " + direction + ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index in the matrix for the specified coordinate pair.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @return The index.
|
||||
* @throws ArrayIndexOutOfBoundsException If the specified coordinate pair does not fit in this matrix.
|
||||
*/
|
||||
private int indexOf(int x, int y) {
|
||||
int index = y * width + x;
|
||||
Preconditions.checkElementIndex(index, matrix.length, "Index out of bounds.");
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the appropriate index for the specified coordinate pair to the specified value.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param value The value.
|
||||
*/
|
||||
private void set(int x, int y, byte value) {
|
||||
matrix[indexOf(x, y)] = value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains classes related to tile collision data.
|
||||
*/
|
||||
package org.apollo.game.model.area.collision;
|
||||
@@ -16,6 +16,7 @@ import org.apollo.game.model.area.SectorRepository;
|
||||
import org.apollo.game.model.def.NpcDefinition;
|
||||
import org.apollo.game.model.entity.attr.Attribute;
|
||||
import org.apollo.game.model.entity.attr.AttributeMap;
|
||||
import org.apollo.game.model.event.impl.MobPositionUpdateEvent;
|
||||
import org.apollo.game.model.inv.Inventory;
|
||||
import org.apollo.game.model.inv.Inventory.StackMode;
|
||||
import org.apollo.game.model.inv.InventoryConstants;
|
||||
@@ -156,7 +157,7 @@ public abstract class Mob extends Entity {
|
||||
* @return The value of the attribute.
|
||||
*/
|
||||
public final Attribute<?> getAttribute(String name) {
|
||||
return attributes.getAttribute(name);
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,7 +369,7 @@ public abstract class Mob extends Entity {
|
||||
* @param value The attribute.
|
||||
*/
|
||||
public final void setAttribute(String name, Attribute<?> value) {
|
||||
attributes.setAttribute(name, value);
|
||||
attributes.set(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,6 +404,15 @@ public abstract class Mob extends Entity {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this mobs interacting index.
|
||||
*
|
||||
* @return The interaction index of this mob.
|
||||
*/
|
||||
public int getInteractionIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this mob's interacting mob.
|
||||
*
|
||||
@@ -410,7 +420,7 @@ public abstract class Mob extends Entity {
|
||||
*/
|
||||
public final void setInteractingMob(Mob mob) {
|
||||
interactingMob = mob;
|
||||
blockSet.add(SynchronizationBlock.createInteractingMobBlock(mob.index));
|
||||
blockSet.add(SynchronizationBlock.createInteractingMobBlock(mob.getInteractionIndex()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,6 +429,9 @@ public abstract class Mob extends Entity {
|
||||
* @param position The position.
|
||||
*/
|
||||
public final void setPosition(Position position) {
|
||||
World.getWorld().submit(new MobPositionUpdateEvent(this, position));
|
||||
// Intentionally ignore the Event result - accidentally terminating this method would break the entire server.
|
||||
|
||||
Position old = this.position;
|
||||
SectorRepository repository = World.getWorld().getSectorRepository();
|
||||
Sector current = repository.fromPosition(old);
|
||||
|
||||
@@ -19,6 +19,17 @@ import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.area.Sector;
|
||||
import org.apollo.game.model.entity.attr.Attribute;
|
||||
import org.apollo.game.model.entity.attr.AttributeDefinition;
|
||||
import org.apollo.game.model.entity.attr.AttributeMap;
|
||||
import org.apollo.game.model.entity.attr.AttributePersistence;
|
||||
import org.apollo.game.model.entity.attr.NumericalAttribute;
|
||||
import org.apollo.game.model.entity.setting.MembershipStatus;
|
||||
import org.apollo.game.model.entity.setting.PrivacyState;
|
||||
import org.apollo.game.model.entity.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.entity.setting.ScreenBrightness;
|
||||
import org.apollo.game.model.event.impl.LoginEvent;
|
||||
import org.apollo.game.model.event.impl.LogoutEvent;
|
||||
import org.apollo.game.model.inter.InterfaceConstants;
|
||||
import org.apollo.game.model.inter.InterfaceListener;
|
||||
import org.apollo.game.model.inter.InterfaceSet;
|
||||
@@ -31,9 +42,6 @@ import org.apollo.game.model.inv.Inventory.StackMode;
|
||||
import org.apollo.game.model.inv.InventoryConstants;
|
||||
import org.apollo.game.model.inv.InventoryListener;
|
||||
import org.apollo.game.model.inv.SynchronizationInventoryListener;
|
||||
import org.apollo.game.model.setting.PrivacyState;
|
||||
import org.apollo.game.model.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.setting.ScreenBrightness;
|
||||
import org.apollo.game.model.skill.LevelUpSkillListener;
|
||||
import org.apollo.game.model.skill.SynchronizationSkillListener;
|
||||
import org.apollo.game.sync.block.SynchronizationBlock;
|
||||
@@ -52,6 +60,11 @@ import com.google.common.base.Preconditions;
|
||||
*/
|
||||
public final class Player extends Mob {
|
||||
|
||||
static {
|
||||
AttributeMap.define("run_energy", AttributeDefinition.forInt(100, AttributePersistence.PERSISTENT));
|
||||
AttributeMap.define("client_version", AttributeDefinition.forInt(0, AttributePersistence.TRANSIENT));
|
||||
}
|
||||
|
||||
/**
|
||||
* The player's appearance.
|
||||
*/
|
||||
@@ -72,32 +85,11 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private transient Deque<Point> clicks = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* The version of the client this player is using. This is not the same as the release number, instead denoting the
|
||||
* custom version.
|
||||
*/
|
||||
private transient int clientVersion;
|
||||
|
||||
/**
|
||||
* This player's credentials.
|
||||
*/
|
||||
private PlayerCredentials credentials;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return credentials.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Player) {
|
||||
Player other = (Player) obj;
|
||||
return credentials.equals(other.credentials);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A flag which indicates there are npcs that couldn't be added.
|
||||
*/
|
||||
@@ -144,14 +136,9 @@ public final class Player extends Mob {
|
||||
private transient Position lastKnownSector;
|
||||
|
||||
/**
|
||||
* The membership flag.
|
||||
* The MembershipStatus of this Player.
|
||||
*/
|
||||
private transient boolean members = false;
|
||||
|
||||
/**
|
||||
* A flag indicating if the player is new.
|
||||
*/
|
||||
private boolean newPlayer = false;
|
||||
private transient MembershipStatus members = MembershipStatus.FREE;
|
||||
|
||||
/**
|
||||
* This player's prayer icon.
|
||||
@@ -168,16 +155,6 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private final transient Deque<Message> queuedMessages = new ArrayDeque<>();
|
||||
|
||||
/**
|
||||
* A flag indicating if the sector changed in the last cycle.
|
||||
*/
|
||||
private transient boolean sectorChanged = false;
|
||||
|
||||
/**
|
||||
* The player's run energy.
|
||||
*/
|
||||
private int runEnergy = 100;
|
||||
|
||||
/**
|
||||
* A flag indicating if this player is running.
|
||||
*/
|
||||
@@ -188,6 +165,11 @@ public final class Player extends Mob {
|
||||
*/
|
||||
private ScreenBrightness screenBrightness = ScreenBrightness.NORMAL;
|
||||
|
||||
/**
|
||||
* A flag indicating if the sector changed in the last cycle.
|
||||
*/
|
||||
private transient boolean sectorChanged = false;
|
||||
|
||||
/**
|
||||
* The {@link GameSession} currently attached to this {@link Player}.
|
||||
*/
|
||||
@@ -263,6 +245,16 @@ public final class Player extends Mob {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof Player) {
|
||||
Player other = (Player) obj;
|
||||
return credentials.equals(other.credentials);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the excessive npcs flag.
|
||||
*/
|
||||
@@ -329,7 +321,8 @@ public final class Player extends Mob {
|
||||
* @return The version.
|
||||
*/
|
||||
public int getClientVersion() {
|
||||
return clientVersion;
|
||||
Attribute<Integer> version = attributes.get("client_version");
|
||||
return version.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,6 +375,11 @@ public final class Player extends Mob {
|
||||
return ignores;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInteractionIndex() {
|
||||
return getIndex() | 0x8000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this player's interface set.
|
||||
*
|
||||
@@ -433,7 +431,8 @@ public final class Player extends Mob {
|
||||
* @return The run energy.
|
||||
*/
|
||||
public int getRunEnergy() {
|
||||
return runEnergy;
|
||||
Attribute<Integer> energy = attributes.get("run_energy");
|
||||
return energy.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,6 +489,11 @@ public final class Player extends Mob {
|
||||
return worldId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return credentials.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not the player with the specified username is on this player's ignore list.
|
||||
*
|
||||
@@ -551,16 +555,16 @@ public final class Player extends Mob {
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean isMembers() {
|
||||
return members;
|
||||
return members == MembershipStatus.PAID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this player has logged in before.
|
||||
* Gets the {@link MembershipStatus} of this Player.
|
||||
*
|
||||
* @return A flag indicating if the player is new.
|
||||
* @return The MembershipStatus.
|
||||
*/
|
||||
public boolean isNew() {
|
||||
return newPlayer;
|
||||
public MembershipStatus getMembershipStatus() {
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -594,7 +598,9 @@ public final class Player extends Mob {
|
||||
* Logs the player out, if possible.
|
||||
*/
|
||||
public void logout() {
|
||||
send(new LogoutMessage());
|
||||
if (World.getWorld().submit(new LogoutEvent(this))) {
|
||||
send(new LogoutMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -675,6 +681,27 @@ public final class Player extends Mob {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the initial messages.
|
||||
*/
|
||||
public void sendInitialMessages() {
|
||||
blockSet.add(SynchronizationBlock.createAppearanceBlock(this));
|
||||
send(new IdAssignmentMessage(index, members)); // TODO should this be sent when we reconnect?
|
||||
sendMessage("Welcome to RuneScape.");
|
||||
|
||||
int[] tabs = InterfaceConstants.DEFAULT_INVENTORY_TABS;
|
||||
for (int tab = 0; tab < tabs.length; tab++) {
|
||||
send(new SwitchTabInterfaceMessage(tab, tabs[tab]));
|
||||
}
|
||||
|
||||
inventory.forceRefresh();
|
||||
equipment.forceRefresh();
|
||||
bank.forceRefresh();
|
||||
skillSet.forceRefresh();
|
||||
|
||||
World.getWorld().submit(new LoginEvent(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the player.
|
||||
*
|
||||
@@ -691,7 +718,7 @@ public final class Player extends Mob {
|
||||
* @param filterable Whether or not the message can be filtered.
|
||||
*/
|
||||
public void sendMessage(String message, boolean filterable) {
|
||||
if (clientVersion > 0) {
|
||||
if (getClientVersion() > 0) {
|
||||
send(new ServerChatMessage(message, filterable));
|
||||
} else if (!filterable || !filteringMessages) {
|
||||
send(new ServerChatMessage(message));
|
||||
@@ -748,12 +775,12 @@ public final class Player extends Mob {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value denoting the client's modified version. TODO make this an attribute?
|
||||
* Sets the value denoting the client's modified version.
|
||||
*
|
||||
* @param clientVersion The client version.
|
||||
* @param version The client version.
|
||||
*/
|
||||
public void setClientVersion(int clientVersion) {
|
||||
this.clientVersion = clientVersion;
|
||||
public void setClientVersion(int version) {
|
||||
attributes.set("client_version", new NumericalAttribute(version));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -797,19 +824,10 @@ public final class Player extends Mob {
|
||||
*
|
||||
* @param members The new membership flag.
|
||||
*/
|
||||
public void setMembers(boolean members) {
|
||||
public void setMembers(MembershipStatus members) {
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new player flag. TODO make this an attribute?
|
||||
*
|
||||
* @param newPlayer A flag indicating if the player has played before.
|
||||
*/
|
||||
public void setNew(boolean newPlayer) {
|
||||
this.newPlayer = newPlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's prayer icon. TODO make this an attribute?
|
||||
*
|
||||
@@ -829,22 +847,13 @@ public final class Player extends Mob {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sector changed flag.
|
||||
* Sets the player's run energy.
|
||||
*
|
||||
* @param sectorChanged A flag indicating if the sector has changed.
|
||||
* @param energy The energy.
|
||||
*/
|
||||
public void setSectorChanged(boolean sectorChanged) {
|
||||
this.sectorChanged = sectorChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's run energy. TODO make this an attribute?
|
||||
*
|
||||
* @param runEnergy The energy.
|
||||
*/
|
||||
public void setRunEnergy(int runEnergy) {
|
||||
this.runEnergy = runEnergy;
|
||||
send(new UpdateRunEnergyMessage(runEnergy));
|
||||
public void setRunEnergy(int energy) {
|
||||
attributes.set("run_energy", new NumericalAttribute(energy));
|
||||
send(new UpdateRunEnergyMessage(energy));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -856,18 +865,22 @@ public final class Player extends Mob {
|
||||
this.screenBrightness = brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sector changed flag.
|
||||
*
|
||||
* @param sectorChanged A flag indicating if the sector has changed.
|
||||
*/
|
||||
public void setSectorChanged(boolean sectorChanged) {
|
||||
this.sectorChanged = sectorChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's {@link GameSession}.
|
||||
*
|
||||
* @param session The player's {@link GameSession}.
|
||||
* @param reconnecting The reconnecting flag.
|
||||
*/
|
||||
public void setSession(GameSession session, boolean reconnecting) {
|
||||
public void setSession(GameSession session) {
|
||||
this.session = session;
|
||||
if (!reconnecting) {
|
||||
sendInitialMessages();
|
||||
}
|
||||
blockSet.add(SynchronizationBlock.createAppearanceBlock(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -931,7 +944,7 @@ public final class Player extends Mob {
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("username", getUsername()).add("privilege", privilegeLevel)
|
||||
.add("client version", clientVersion).toString();
|
||||
.add("client version", getClientVersion()).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -977,27 +990,4 @@ public final class Player extends Mob {
|
||||
skillSet.addListener(new LevelUpSkillListener(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the initial messages.
|
||||
*/
|
||||
private void sendInitialMessages() {
|
||||
send(new IdAssignmentMessage(index, members)); // TODO should this be sent when we reconnect?
|
||||
sendMessage("Welcome to RuneScape.");
|
||||
if (!newPlayer) {
|
||||
interfaceSet.openWindow(InterfaceConstants.AVATAR_DESIGN);
|
||||
}
|
||||
|
||||
int[] tabs = InterfaceConstants.DEFAULT_INVENTORY_TABS;
|
||||
for (int tab = 0; tab < tabs.length; tab++) {
|
||||
send(new SwitchTabInterfaceMessage(tab, tabs[tab]));
|
||||
}
|
||||
|
||||
inventory.forceRefresh();
|
||||
equipment.forceRefresh();
|
||||
bank.forceRefresh();
|
||||
skillSet.forceRefresh();
|
||||
|
||||
World.getWorld().getLoginDispatcher().dispatch(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,12 +13,12 @@ public abstract class Attribute<T> {
|
||||
/**
|
||||
* The type of this attribute.
|
||||
*/
|
||||
private final AttributeType type;
|
||||
protected final AttributeType type;
|
||||
|
||||
/**
|
||||
* The value of this attribute.
|
||||
*/
|
||||
protected T value;
|
||||
protected final T value;
|
||||
|
||||
/**
|
||||
* Creates the attribute with the specified {@link AttributeType} and value.
|
||||
@@ -31,6 +31,13 @@ public abstract class Attribute<T> {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes this Attribute into a byte array.
|
||||
*
|
||||
* @return The byte array.
|
||||
*/
|
||||
public abstract byte[] encode();
|
||||
|
||||
/**
|
||||
* Gets the type of this attribute.
|
||||
*
|
||||
@@ -49,4 +56,11 @@ public abstract class Attribute<T> {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Sting representation of this Attribute. Will be used to write this Attribute as a String, if
|
||||
* required.
|
||||
*/
|
||||
@Override
|
||||
public abstract String toString();
|
||||
|
||||
}
|
||||
@@ -10,25 +10,69 @@ package org.apollo.game.model.entity.attr;
|
||||
public final class AttributeDefinition<T> {
|
||||
|
||||
/**
|
||||
* The default value of this definition.
|
||||
* Creates an AttributeDefinition for a {@code boolean}.
|
||||
*
|
||||
* @param defaultValue The default value of the definition.
|
||||
* @param persistence The {@link AttributePersistence} of the definition.
|
||||
* @return The AttributeDefinition.
|
||||
*/
|
||||
public static AttributeDefinition<Boolean> forBoolean(boolean defaultValue, AttributePersistence persistence) {
|
||||
return new AttributeDefinition<>(defaultValue, persistence, AttributeType.BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AttributeDefinition for a {@code double}.
|
||||
*
|
||||
* @param defaultValue The default value of the definition.
|
||||
* @param persistence The {@link AttributePersistence} of the definition.
|
||||
* @return The AttributeDefinition.
|
||||
*/
|
||||
public static AttributeDefinition<Double> forDouble(double defaultValue, AttributePersistence persistence) {
|
||||
return new AttributeDefinition<>(defaultValue, persistence, AttributeType.DOUBLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AttributeDefinition for an {@code int}.
|
||||
*
|
||||
* @param defaultValue The default value of the definition.
|
||||
* @param persistence The {@link AttributePersistence} of the definition.
|
||||
* @return The AttributeDefinition.
|
||||
*/
|
||||
public static AttributeDefinition<Integer> forInt(int defaultValue, AttributePersistence persistence) {
|
||||
return new AttributeDefinition<>(defaultValue, persistence, AttributeType.LONG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AttributeDefinition for a String.
|
||||
*
|
||||
* @param defaultValue The default value of the definition.
|
||||
* @param persistence The {@link AttributePersistence} of the definition.
|
||||
* @return The AttributeDefinition.
|
||||
*/
|
||||
public static AttributeDefinition<String> forString(String defaultValue, AttributePersistence persistence) {
|
||||
return new AttributeDefinition<>(defaultValue, persistence, AttributeType.STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default value of the Attribute.
|
||||
*/
|
||||
private final T defaultValue;
|
||||
|
||||
/**
|
||||
* The persistence state of this definition.
|
||||
* The persistence state of the Attribute.
|
||||
*/
|
||||
private final AttributePersistence persistence;
|
||||
|
||||
/**
|
||||
* The type of this definition.
|
||||
* The type of the Attribute.
|
||||
*/
|
||||
private final AttributeType type;
|
||||
|
||||
/**
|
||||
* Creates the attribute definition.
|
||||
* Creates the AttributeDefinition.
|
||||
*
|
||||
* @param defaultValue The default value.
|
||||
* @param persistence The {@link AttributePersistence} state.
|
||||
* @param persistence The {@link AttributePersistence}.
|
||||
* @param type The {@link AttributeType}.
|
||||
*/
|
||||
public AttributeDefinition(T defaultValue, AttributePersistence persistence, AttributeType type) {
|
||||
@@ -38,7 +82,7 @@ public final class AttributeDefinition<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default value of this attribute definition.
|
||||
* Gets the default value of this AttributeDefinition.
|
||||
*
|
||||
* @return The default value.
|
||||
*/
|
||||
@@ -47,18 +91,18 @@ public final class AttributeDefinition<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the persistence state of this attribute definition.
|
||||
* Gets the {@link AttributePersistence} of this AttributeDefinition.
|
||||
*
|
||||
* @return The persistence.
|
||||
* @return The AttributePersistence.
|
||||
*/
|
||||
public AttributePersistence getPersistence() {
|
||||
return persistence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link AttributeType} of this definition.
|
||||
* Gets the {@link AttributeType} of this AttributeDefinition
|
||||
*
|
||||
* @return The attribute type.
|
||||
* @return The AttributeType.
|
||||
*/
|
||||
public AttributeType getType() {
|
||||
return type;
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.apollo.game.model.entity.attr;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jruby.RubySymbol;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
@@ -12,10 +14,15 @@ import com.google.common.base.Preconditions;
|
||||
*/
|
||||
public final class AttributeMap {
|
||||
|
||||
/**
|
||||
* The default size of the map.
|
||||
*/
|
||||
private static final int DEFAULT_MAP_SIZE = 2;
|
||||
|
||||
/**
|
||||
* The map of attribute names to definitions.
|
||||
*/
|
||||
private static Map<String, AttributeDefinition<?>> definitions = new HashMap<>(1);
|
||||
private static Map<String, AttributeDefinition<?>> definitions = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Registers an {@link AttributeDefinition}.
|
||||
@@ -23,7 +30,7 @@ public final class AttributeMap {
|
||||
* @param name The name of the attribute.
|
||||
* @param definition The definition.
|
||||
*/
|
||||
public static void addDefinition(String name, AttributeDefinition<?> definition) {
|
||||
public static void define(String name, AttributeDefinition<?> definition) {
|
||||
definitions.put(name, definition);
|
||||
}
|
||||
|
||||
@@ -33,8 +40,9 @@ public final class AttributeMap {
|
||||
* @param name The name of the attribute.
|
||||
* @return The attribute definition.
|
||||
*/
|
||||
public static AttributeDefinition<?> getDefinition(String name) {
|
||||
return definitions.get(name);
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> AttributeDefinition<T> getDefinition(String name) {
|
||||
return (AttributeDefinition<T>) definitions.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,10 +54,20 @@ public final class AttributeMap {
|
||||
return new HashMap<>(definitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not an {@link AttributeDefinition} with the specified name exists.
|
||||
*
|
||||
* @param name The name of the AttributeDefinition.
|
||||
* @return {@code true} if the AttributeDefinition exists, {@code false} if not.
|
||||
*/
|
||||
public static boolean hasDefinition(String name) {
|
||||
return definitions.containsKey(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* The map of attribute names to attributes.
|
||||
*/
|
||||
private Map<String, Attribute<?>> attributes = new HashMap<>();
|
||||
private Map<String, Attribute<?>> attributes = new HashMap<>(DEFAULT_MAP_SIZE);
|
||||
|
||||
/**
|
||||
* Gets the {@link Attribute} with the specified name.
|
||||
@@ -57,8 +75,13 @@ public final class AttributeMap {
|
||||
* @param name The name of the attribute.
|
||||
* @return The attribute.
|
||||
*/
|
||||
public Attribute<?> getAttribute(String name) {
|
||||
return attributes.get(name);
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Attribute<T> get(String name) {
|
||||
AttributeDefinition<T> definition = getDefinition(name);
|
||||
Preconditions.checkNotNull(definition, "Attributes must be defined before their value can be retreived.");
|
||||
|
||||
return (Attribute<T>) attributes.computeIfAbsent(name,
|
||||
key -> createAttribute(definition.getDefault(), definition.getType()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,9 +99,32 @@ public final class AttributeMap {
|
||||
* @param name The name of the attribute.
|
||||
* @param attribute The attribute.
|
||||
*/
|
||||
public void setAttribute(String name, Attribute<?> attribute) {
|
||||
public void set(String name, Attribute<?> attribute) {
|
||||
Preconditions.checkNotNull(getDefinition(name), "Attributes must be defined before their value can be set.");
|
||||
attributes.put(name, attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link Attribute} with the specified value and {@link AttributeType}.
|
||||
*
|
||||
* @param value The value of the Attribute.
|
||||
* @param type The AttributeType.
|
||||
* @return The Attribute.
|
||||
*/
|
||||
private <T> Attribute<?> createAttribute(T value, AttributeType type) {
|
||||
switch (type) {
|
||||
case LONG:
|
||||
case DOUBLE:
|
||||
return new NumericalAttribute((Integer) value);
|
||||
case STRING:
|
||||
return new StringAttribute((String) value);
|
||||
case SYMBOL:
|
||||
return new StringAttribute(((RubySymbol) value).asJavaString(), true);
|
||||
case BOOLEAN:
|
||||
return new BooleanAttribute((Boolean) value);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unrecognised type " + type + ".");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ public enum AttributePersistence {
|
||||
/**
|
||||
* The serialized persistence type, indicating that the attribute will be saved.
|
||||
*/
|
||||
SERIALIZED,
|
||||
PERSISTENT,
|
||||
|
||||
/**
|
||||
* The transient persistence type, indicating that the attribute will not be saved.
|
||||
|
||||
@@ -16,4 +16,14 @@ public final class BooleanAttribute extends Attribute<Boolean> {
|
||||
super(AttributeType.BOOLEAN, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encode() {
|
||||
return new byte[] { (byte) (value ? 1 : 0) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Boolean.toString(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.apollo.game.model.entity.attr;
|
||||
|
||||
import com.google.common.primitives.Longs;
|
||||
|
||||
/**
|
||||
* An {@link Attribute} with a numerical value.
|
||||
*
|
||||
@@ -26,4 +28,15 @@ public final class NumericalAttribute extends Attribute<Number> {
|
||||
super(typeOf(value), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encode() {
|
||||
long encoded = (type == AttributeType.DOUBLE) ? Double.doubleToLongBits((double) value) : (long) value;
|
||||
return Longs.toByteArray(encoded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (type == AttributeType.DOUBLE) ? Double.toString((double) value) : Long.toString((long) value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.apollo.game.model.entity.attr;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* An {@link Attribute} with a string value.
|
||||
*
|
||||
@@ -26,4 +28,14 @@ public final class StringAttribute extends Attribute<String> {
|
||||
super(symbol ? AttributeType.SYMBOL : AttributeType.STRING, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encode() {
|
||||
return value.getBytes(Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.apollo.game.model.setting;
|
||||
package org.apollo.game.model.entity.setting;
|
||||
|
||||
/**
|
||||
* An enumeration containing the two genders (male and female). This enumeration relies on the ordering of the elements
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.apollo.game.model.entity.setting;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The membership status of a Player.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public enum MembershipStatus {
|
||||
|
||||
/**
|
||||
* The free membership status.
|
||||
*/
|
||||
FREE(0),
|
||||
|
||||
/**
|
||||
* The paid membership status.
|
||||
*/
|
||||
PAID(1);
|
||||
|
||||
/**
|
||||
* Gets the MembershipStatus with the specified value.
|
||||
*
|
||||
* @param value The integer value of the MembershipStatus.
|
||||
* @return The MembershipStatus.
|
||||
* @throws IllegalArgumentException If no MembershipStatus with the specified the value exists.
|
||||
*/
|
||||
public static MembershipStatus valueOf(int value) {
|
||||
Optional<MembershipStatus> optional = Arrays.stream(values()).filter(status -> status.value == value).findAny();
|
||||
return optional.orElseThrow(() -> new IllegalArgumentException("Illegal membership status value."));
|
||||
}
|
||||
|
||||
/**
|
||||
* The integer value of this MembershipStatus.
|
||||
*/
|
||||
private final int value;
|
||||
|
||||
/**
|
||||
* Creates the MembershipStatus.
|
||||
*
|
||||
* @param value The integer value.
|
||||
*/
|
||||
private MembershipStatus(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this MembershipStatus.
|
||||
*
|
||||
* @return The value.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.apollo.game.model.setting;
|
||||
package org.apollo.game.model.entity.setting;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.apollo.game.model.setting;
|
||||
package org.apollo.game.model.entity.setting;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.apollo.game.model.setting;
|
||||
package org.apollo.game.model.entity.setting;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.apollo.game.model.setting;
|
||||
package org.apollo.game.model.entity.setting;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* Contains player setting or customisation-related classes.
|
||||
*/
|
||||
package org.apollo.game.model.setting;
|
||||
package org.apollo.game.model.entity.setting;
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.apollo.game.model.event;
|
||||
|
||||
/**
|
||||
* A type of event that may occur in the game world.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public abstract class Event {
|
||||
|
||||
/**
|
||||
* Indicates whether or not the Event chain has been terminated.
|
||||
*/
|
||||
private boolean terminated;
|
||||
|
||||
/**
|
||||
* Terminates the Event chain.
|
||||
*/
|
||||
public final void terminate() {
|
||||
terminated = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the Event chain has been terminated.
|
||||
*
|
||||
* @return {@code true} if the Event chain has been terminated, otherwise {@code false}.
|
||||
*/
|
||||
public final boolean terminated() {
|
||||
return terminated;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.apollo.game.model.event;
|
||||
|
||||
/**
|
||||
* A listener for an {@link Event} that may occur in the game world.
|
||||
*
|
||||
* @author Major
|
||||
*
|
||||
* @param <E> The type of Event.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface EventListener<E> {
|
||||
|
||||
/**
|
||||
* Handles the {@link Event} that occurred.
|
||||
*
|
||||
* @param event The Event.
|
||||
*/
|
||||
public void handle(E event);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.apollo.game.model.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
|
||||
/**
|
||||
* A chain of {@link EventListener}s.
|
||||
*
|
||||
* @author Major
|
||||
* @param <E> The type of {@link Event} the listeners in this chain listen for.
|
||||
*/
|
||||
final class EventListenerChain<E extends Event> {
|
||||
|
||||
/**
|
||||
* The List of EventListeners.
|
||||
*/
|
||||
private final List<EventListener<E>> listeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The Class type of this chain.
|
||||
*/
|
||||
private final Class<E> type;
|
||||
|
||||
/**
|
||||
* Creates the EventListenerChain.
|
||||
*
|
||||
* @param type The {@link Class} type of this chain.
|
||||
*/
|
||||
public EventListenerChain(Class<E> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link EventListener} to this chain.
|
||||
*
|
||||
* @param listener The EventListener to add.
|
||||
*/
|
||||
public void addListener(EventListener<E> listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies each {@link EventListener} in this chain that an {@link Event} has occurred.
|
||||
*
|
||||
* @param event The event.
|
||||
* @return {@code true} if the Event should continue on with its outcome, {@code false} if not.
|
||||
*/
|
||||
public boolean notify(E event) {
|
||||
for (EventListener<E> listener : listeners) {
|
||||
listener.handle(event);
|
||||
|
||||
if (event.terminated()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(this).add("type", type).add("listeners", listeners).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.apollo.game.model.event;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A set of {@link EventListenerChain}s.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class EventListenerChainSet {
|
||||
|
||||
/**
|
||||
* The Map of Event Classes to EventListenerChains.
|
||||
*/
|
||||
private final Map<Class<? extends Event>, EventListenerChain<? extends Event>> chains = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Notifies the appropriate {@link EventListenerChain} that an {@link Event} has occurred.
|
||||
*
|
||||
* @param event The Event.
|
||||
* @return {@code true} if the Event should continue on with its outcome, {@code false} if not.
|
||||
*/
|
||||
public <E extends Event> boolean notify(E event) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EventListenerChain<E> chain = (EventListenerChain<E>) chains.get(event.getClass());
|
||||
return (chain == null) ? true : chain.notify(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places the {@link EventListenerChain} into this set.
|
||||
*
|
||||
* @param clazz The {@link Class} to associate the EventListenerChain with.
|
||||
* @param listener The EventListenerChain.
|
||||
*/
|
||||
public <E extends Event> void putListener(Class<E> clazz, EventListener<E> listener) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EventListenerChain<E> chain = (EventListenerChain<E>) chains.computeIfAbsent(clazz, EventListenerChain::new);
|
||||
chain.addListener(listener);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.apollo.game.model.event;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
|
||||
/**
|
||||
* An {@link Event} involving a {@link Player}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public abstract class PlayerEvent extends Event {
|
||||
|
||||
/**
|
||||
* The Player.
|
||||
*/
|
||||
private final Player player;
|
||||
|
||||
/**
|
||||
* Creates the PlayerEvent.
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
*/
|
||||
public PlayerEvent(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Player}.
|
||||
*
|
||||
* @return The Player.
|
||||
*/
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.apollo.game.model.event.impl;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.event.Event;
|
||||
import org.apollo.game.model.event.PlayerEvent;
|
||||
|
||||
/**
|
||||
* An {@link Event} indicating that a player's open interfaces are about to be closed.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class CloseInterfacesEvent extends PlayerEvent {
|
||||
|
||||
/**
|
||||
* Creates the CloseInterfacesEvent.
|
||||
*
|
||||
* @param player The {@link Player} whose interfaces are being closed.
|
||||
*/
|
||||
public CloseInterfacesEvent(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.apollo.game.model.event.impl;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.event.PlayerEvent;
|
||||
|
||||
/**
|
||||
* A {@link PlayerEvent} that is fired when a {@link Player} logs in.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class LoginEvent extends PlayerEvent {
|
||||
|
||||
/**
|
||||
* Creates the LoginEvent.
|
||||
*
|
||||
* @param player The {@link Player} logging in.
|
||||
*/
|
||||
public LoginEvent(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.apollo.game.model.event.impl;
|
||||
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.event.PlayerEvent;
|
||||
|
||||
/**
|
||||
* A {@link PlayerEvent} that is fired when a {@link Player} logs out.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class LogoutEvent extends PlayerEvent {
|
||||
|
||||
/**
|
||||
* Creates the LogoutEvent.
|
||||
*
|
||||
* @param player The {@link Player} logging out.
|
||||
*/
|
||||
public LogoutEvent(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.apollo.game.model.event.impl;
|
||||
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.entity.Mob;
|
||||
import org.apollo.game.model.event.Event;
|
||||
|
||||
/**
|
||||
* An {@link Event} created when a Mob's Position is being updated.
|
||||
* <p>
|
||||
* This Event intentionally ignores the result of execution - it should not be possible for a plugin to prevent this
|
||||
* Event from happening, only to listen for it.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class MobPositionUpdateEvent extends Event {
|
||||
|
||||
/**
|
||||
* The Mob whose position is being updated.
|
||||
*/
|
||||
private final Mob mob;
|
||||
|
||||
/**
|
||||
* The next Position of the Mob.
|
||||
*/
|
||||
private final Position next;
|
||||
|
||||
/**
|
||||
* Creates the MobPositionUpdateEvent.
|
||||
*
|
||||
* @param mob The {@link Mob} whose Position is being updated.
|
||||
* @param next The next {@link Position} of the Mob.
|
||||
*/
|
||||
public MobPositionUpdateEvent(Mob mob, Position next) {
|
||||
this.mob = mob;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Mob} being moved.
|
||||
*
|
||||
* @return The Mob.
|
||||
*/
|
||||
public Mob getMob() {
|
||||
return mob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Position} this {@link Mob} is being moved to.
|
||||
*
|
||||
* @return The Position.
|
||||
*/
|
||||
public Position getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains Event implementations.
|
||||
*/
|
||||
package org.apollo.game.model.event.impl;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains event-related classes.
|
||||
*/
|
||||
package org.apollo.game.model.event;
|
||||
@@ -7,11 +7,6 @@ package org.apollo.game.model.inter;
|
||||
*/
|
||||
public class InterfaceConstants {
|
||||
|
||||
/**
|
||||
* The avatar design interface id.
|
||||
*/
|
||||
public static final int AVATAR_DESIGN = 3559;
|
||||
|
||||
/**
|
||||
* The default inventory tab ids.
|
||||
*/
|
||||
|
||||
@@ -7,10 +7,16 @@ import java.util.Optional;
|
||||
import org.apollo.game.message.impl.CloseInterfaceMessage;
|
||||
import org.apollo.game.message.impl.EnterAmountMessage;
|
||||
import org.apollo.game.message.impl.OpenDialogueInterfaceMessage;
|
||||
import org.apollo.game.message.impl.OpenDialogueOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenInterfaceMessage;
|
||||
import org.apollo.game.message.impl.OpenInterfaceSidebarMessage;
|
||||
import org.apollo.game.message.impl.OpenOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenSidebarMessage;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.event.impl.CloseInterfacesEvent;
|
||||
import org.apollo.game.model.inter.dialogue.DialogueListener;
|
||||
import org.apollo.game.model.inv.InventoryListener;
|
||||
|
||||
/**
|
||||
* Represents the set of interfaces the player has open.
|
||||
@@ -83,8 +89,11 @@ public final class InterfaceSet {
|
||||
* Closes the current open interface(s).
|
||||
*/
|
||||
public void close() {
|
||||
closeAndNotify();
|
||||
player.send(new CloseInterfaceMessage());
|
||||
CloseInterfacesEvent event = new CloseInterfacesEvent(player);
|
||||
if (World.getWorld().submit(event)) {
|
||||
closeAndNotify();
|
||||
player.send(new CloseInterfaceMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,10 +145,10 @@ public final class InterfaceSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a chat box dialogue.
|
||||
* Opens a dialogue interface.
|
||||
*
|
||||
* @param listener The listener for the dialogue.
|
||||
* @param dialogueId The dialogue's id.
|
||||
* @param listener The {@link DialogueListener}.
|
||||
* @param dialogueId The dialogue id.
|
||||
*/
|
||||
public void openDialogue(DialogueListener listener, int dialogueId) {
|
||||
closeAndNotify();
|
||||
@@ -152,14 +161,39 @@ public final class InterfaceSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a chat box dialogue.
|
||||
* Opens a dialogue.
|
||||
*
|
||||
* @param dialogueId The dialogue's id.
|
||||
* @param dialogueId The dialogue id.
|
||||
*/
|
||||
public void openDialogue(int dialogueId) {
|
||||
openDialogue(null, dialogueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a dialogue overlay interface.
|
||||
*
|
||||
* @param listener The {@link DialogueListener}.
|
||||
* @param dialogueId The dialogue id.
|
||||
*/
|
||||
public void openDialogueOverlay(DialogueListener listener, int dialogueId) {
|
||||
closeAndNotify();
|
||||
|
||||
this.dialogueListener = Optional.ofNullable(listener);
|
||||
this.listener = Optional.ofNullable(listener);
|
||||
|
||||
interfaces.put(InterfaceType.DIALOGUE, dialogueId);
|
||||
player.send(new OpenDialogueOverlayMessage(dialogueId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a dialogue overlay.
|
||||
*
|
||||
* @param dialogueId The dialogue id.
|
||||
*/
|
||||
public void openDialogueOverlay(int dialogueId) {
|
||||
openDialogueOverlay(null, dialogueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the enter amount dialogue.
|
||||
*
|
||||
@@ -170,6 +204,42 @@ public final class InterfaceSet {
|
||||
player.send(new EnterAmountMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an overlay interface.
|
||||
*
|
||||
* @param overlay The overlay id.
|
||||
*/
|
||||
public void openOverlay(int overlay) {
|
||||
interfaces.put(InterfaceType.OVERLAY, overlay);
|
||||
player.send(new OpenOverlayMessage(overlay));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an sidebar interface.
|
||||
*
|
||||
* @param sidebar The sidebar id.
|
||||
*/
|
||||
public void openSidebar(int sidebar) {
|
||||
closeAndNotify();
|
||||
interfaces.put(InterfaceType.SIDEBAR, sidebar);
|
||||
|
||||
player.send(new OpenSidebarMessage(sidebar));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an sidebar interface with the specified {@link InventoryListener}.
|
||||
*
|
||||
* @param listener The listener.
|
||||
* @param sidebar The sidebar id.
|
||||
*/
|
||||
public void openSidebar(InterfaceListener listener, int sidebar) {
|
||||
closeAndNotify();
|
||||
this.listener = Optional.ofNullable(listener);
|
||||
interfaces.put(InterfaceType.SIDEBAR, sidebar);
|
||||
|
||||
player.send(new OpenSidebarMessage(sidebar));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a window.
|
||||
*
|
||||
|
||||
@@ -3,10 +3,7 @@ package org.apollo.game.model.inter.bank;
|
||||
import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.def.ItemDefinition;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.inter.InterfaceListener;
|
||||
import org.apollo.game.model.inv.Inventory;
|
||||
import org.apollo.game.model.inv.InventoryListener;
|
||||
import org.apollo.game.model.inv.SynchronizationInventoryListener;
|
||||
|
||||
/**
|
||||
* Contains bank-related utility methods.
|
||||
@@ -65,18 +62,8 @@ public final class BankUtils {
|
||||
* @param player The player.
|
||||
*/
|
||||
public static void openBank(Player player) {
|
||||
InventoryListener invListener = new SynchronizationInventoryListener(player, BankConstants.SIDEBAR_INVENTORY_ID);
|
||||
InventoryListener bankListener = new SynchronizationInventoryListener(player, BankConstants.BANK_INVENTORY_ID);
|
||||
|
||||
player.getInventory().addListener(invListener);
|
||||
player.getBank().addListener(bankListener);
|
||||
|
||||
player.getInventory().forceRefresh();
|
||||
player.getBank().forceRefresh();
|
||||
|
||||
InterfaceListener interListener = new BankInterfaceListener(player, invListener, bankListener);
|
||||
|
||||
player.getInterfaceSet().openWindowWithSidebar(interListener, BankConstants.BANK_WINDOW_ID, BankConstants.SIDEBAR_ID);
|
||||
// Required for access within plugin Actions.
|
||||
player.openBank();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.apollo.game.sync.block;
|
||||
|
||||
import org.apollo.game.message.impl.ChatMessage;
|
||||
import org.apollo.game.model.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.entity.setting.PrivilegeLevel;
|
||||
|
||||
/**
|
||||
* The chat {@link SynchronizationBlock}. Only players can utilise this block.
|
||||
|
||||
@@ -20,11 +20,12 @@ import org.apollo.game.model.entity.attr.AttributeType;
|
||||
import org.apollo.game.model.entity.attr.BooleanAttribute;
|
||||
import org.apollo.game.model.entity.attr.NumericalAttribute;
|
||||
import org.apollo.game.model.entity.attr.StringAttribute;
|
||||
import org.apollo.game.model.entity.setting.Gender;
|
||||
import org.apollo.game.model.entity.setting.MembershipStatus;
|
||||
import org.apollo.game.model.entity.setting.PrivacyState;
|
||||
import org.apollo.game.model.entity.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.entity.setting.ScreenBrightness;
|
||||
import org.apollo.game.model.inv.Inventory;
|
||||
import org.apollo.game.model.setting.Gender;
|
||||
import org.apollo.game.model.setting.PrivacyState;
|
||||
import org.apollo.game.model.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.setting.ScreenBrightness;
|
||||
import org.apollo.io.player.PlayerLoader;
|
||||
import org.apollo.io.player.PlayerLoaderResponse;
|
||||
import org.apollo.net.codec.login.LoginConstants;
|
||||
@@ -57,35 +58,28 @@ public final class BinaryPlayerLoader implements PlayerLoader {
|
||||
}
|
||||
|
||||
try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
|
||||
// read credentials and privileges
|
||||
String name = StreamUtil.readString(in);
|
||||
String pass = StreamUtil.readString(in);
|
||||
String password = StreamUtil.readString(in);
|
||||
|
||||
if (!name.equalsIgnoreCase(credentials.getUsername()) || !SCryptUtil.check(credentials.getPassword(), pass)) {
|
||||
if (!name.equalsIgnoreCase(credentials.getUsername()) || !SCryptUtil.check(credentials.getPassword(), password)) {
|
||||
return new PlayerLoaderResponse(LoginConstants.STATUS_INVALID_CREDENTIALS);
|
||||
}
|
||||
|
||||
// set the credentials password to the scrypted one
|
||||
credentials.setPassword(pass);
|
||||
credentials.setPassword(password); // Update password to the hashed one.
|
||||
|
||||
PrivilegeLevel privilegeLevel = PrivilegeLevel.valueOf(in.readByte());
|
||||
boolean members = in.readBoolean();
|
||||
MembershipStatus members = MembershipStatus.valueOf(in.readByte());
|
||||
|
||||
// read settings
|
||||
PrivacyState chatPrivacy = PrivacyState.valueOf(in.readByte(), true);
|
||||
PrivacyState friendPrivacy = PrivacyState.valueOf(in.readByte(), false);
|
||||
PrivacyState tradePrivacy = PrivacyState.valueOf(in.readByte(), false);
|
||||
int runEnergy = in.readByte();
|
||||
ScreenBrightness brightness = ScreenBrightness.valueOf(in.readByte());
|
||||
|
||||
// read position
|
||||
int x = in.readUnsignedShort();
|
||||
int y = in.readUnsignedShort();
|
||||
int height = in.readUnsignedByte();
|
||||
|
||||
// read appearance
|
||||
boolean designed = in.readBoolean();
|
||||
|
||||
int genderIntValue = in.readUnsignedByte();
|
||||
Gender gender = genderIntValue == Gender.MALE.toInteger() ? Gender.MALE : Gender.FEMALE;
|
||||
int[] style = new int[7];
|
||||
@@ -106,15 +100,12 @@ public final class BinaryPlayerLoader implements PlayerLoader {
|
||||
player.setRunEnergy(runEnergy);
|
||||
player.setScreenBrightness(brightness);
|
||||
|
||||
player.setNew(designed);
|
||||
player.setAppearance(new Appearance(gender, style, colors));
|
||||
|
||||
// read inventories
|
||||
readInventory(in, player.getInventory());
|
||||
readInventory(in, player.getEquipment());
|
||||
readInventory(in, player.getBank());
|
||||
|
||||
// read skills
|
||||
int size = in.readUnsignedByte();
|
||||
SkillSet skills = player.getSkillSet();
|
||||
skills.stopFiringEvents();
|
||||
@@ -138,7 +129,7 @@ public final class BinaryPlayerLoader implements PlayerLoader {
|
||||
|
||||
int ignoreCount = in.readByte();
|
||||
List<String> ignores = new ArrayList<>(ignoreCount);
|
||||
for (int i = 0; i < ignoreCount; i++) {
|
||||
for (int times = 0; times < ignoreCount; times++) {
|
||||
ignores.add(NameUtil.decodeBase37(in.readLong()));
|
||||
}
|
||||
player.setIgnoredUsernames(ignores);
|
||||
@@ -160,27 +151,28 @@ public final class BinaryPlayerLoader implements PlayerLoader {
|
||||
private static Map<String, Attribute<?>> readAttributes(DataInputStream in) throws IOException {
|
||||
int count = in.readInt();
|
||||
Map<String, Attribute<?>> attributes = new HashMap<>(count);
|
||||
Attribute<?> attribute;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int times = 0; times < count; times++) {
|
||||
String name = StreamUtil.readString(in);
|
||||
AttributeType type = AttributeType.valueOf(in.read());
|
||||
Attribute<?> attribute;
|
||||
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
attribute = new BooleanAttribute(in.read() == 1);
|
||||
break;
|
||||
case DOUBLE:
|
||||
attribute = new NumericalAttribute(in.readDouble());
|
||||
break;
|
||||
case LONG:
|
||||
attribute = new NumericalAttribute(in.readLong());
|
||||
break;
|
||||
case STRING:
|
||||
case SYMBOL:
|
||||
attribute = new StringAttribute(StreamUtil.readString(in), type == AttributeType.SYMBOL);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Undefined attribute type: " + type + ".");
|
||||
case BOOLEAN:
|
||||
attribute = new BooleanAttribute(in.read() == 1);
|
||||
break;
|
||||
case DOUBLE:
|
||||
attribute = new NumericalAttribute(in.readDouble());
|
||||
break;
|
||||
case LONG:
|
||||
attribute = new NumericalAttribute(in.readLong());
|
||||
break;
|
||||
case STRING:
|
||||
case SYMBOL:
|
||||
attribute = new StringAttribute(StreamUtil.readString(in), type == AttributeType.SYMBOL);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Undefined attribute type: " + type + ".");
|
||||
}
|
||||
attributes.put(name, attribute);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.apollo.game.model.entity.SkillSet;
|
||||
import org.apollo.game.model.entity.attr.Attribute;
|
||||
import org.apollo.game.model.entity.attr.AttributeMap;
|
||||
import org.apollo.game.model.entity.attr.AttributePersistence;
|
||||
import org.apollo.game.model.entity.attr.AttributeType;
|
||||
import org.apollo.game.model.inv.Inventory;
|
||||
import org.apollo.io.player.PlayerSaver;
|
||||
import org.apollo.util.NameUtil;
|
||||
@@ -35,27 +34,22 @@ public final class BinaryPlayerSaver implements PlayerSaver {
|
||||
File file = BinaryPlayerUtil.getFile(player.getUsername());
|
||||
|
||||
try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
|
||||
// write credentials and privileges
|
||||
StreamUtil.writeString(out, player.getUsername());
|
||||
StreamUtil.writeString(out, player.getCredentials().getPassword());
|
||||
out.writeByte(player.getPrivilegeLevel().toInteger());
|
||||
out.writeBoolean(player.isMembers());
|
||||
out.writeByte(player.getMembershipStatus().getValue());
|
||||
|
||||
// write settings
|
||||
out.writeByte(player.getChatPrivacy().toInteger(true));
|
||||
out.writeByte(player.getFriendPrivacy().toInteger(false));
|
||||
out.writeByte(player.getTradePrivacy().toInteger(false));
|
||||
out.writeByte(player.getRunEnergy());
|
||||
out.writeByte(player.getScreenBrightness().toInteger());
|
||||
|
||||
// write position
|
||||
Position position = player.getPosition();
|
||||
out.writeShort(position.getX());
|
||||
out.writeShort(position.getY());
|
||||
out.writeByte(position.getHeight());
|
||||
|
||||
// write appearance
|
||||
out.writeBoolean(player.isNew());
|
||||
Appearance appearance = player.getAppearance();
|
||||
out.writeByte(appearance.getGender().toInteger());
|
||||
int[] style = appearance.getStyle();
|
||||
@@ -66,14 +60,11 @@ public final class BinaryPlayerSaver implements PlayerSaver {
|
||||
for (int color : colors) {
|
||||
out.writeByte(color);
|
||||
}
|
||||
out.flush();
|
||||
|
||||
// write inventories
|
||||
writeInventory(out, player.getInventory());
|
||||
writeInventory(out, player.getEquipment());
|
||||
writeInventory(out, player.getBank());
|
||||
|
||||
// write skills
|
||||
SkillSet skills = player.getSkillSet();
|
||||
out.writeByte(skills.size());
|
||||
for (int id = 0; id < skills.size(); id++) {
|
||||
@@ -95,47 +86,20 @@ public final class BinaryPlayerSaver implements PlayerSaver {
|
||||
}
|
||||
|
||||
Set<Entry<String, Attribute<?>>> attributes = player.getAttributes().entrySet();
|
||||
attributes.removeIf(e -> AttributeMap.getDefinition(e.getKey()).getPersistence() != AttributePersistence.SERIALIZED);
|
||||
attributes.removeIf(e -> AttributeMap.getDefinition(e.getKey()).getPersistence() != AttributePersistence.PERSISTENT);
|
||||
out.writeInt(attributes.size());
|
||||
|
||||
for (Entry<String, Attribute<?>> entry : attributes) {
|
||||
String name = entry.getKey();
|
||||
StreamUtil.writeString(out, name);
|
||||
saveAttribute(out, entry.getValue());
|
||||
|
||||
Attribute<?> attribute = entry.getValue();
|
||||
out.writeByte(attribute.getType().getValue());
|
||||
out.write(attribute.encode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an {@link Attribute} to the specified output stream.
|
||||
*
|
||||
* @param out The output stream.
|
||||
* @param attribute The attribute.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
private static void saveAttribute(DataOutputStream out, Attribute<?> attribute) throws IOException {
|
||||
AttributeType type = attribute.getType();
|
||||
|
||||
out.writeByte(type.getValue());
|
||||
switch (type) {
|
||||
case BOOLEAN:
|
||||
out.writeByte((Boolean) attribute.getValue() ? 1 : 0);
|
||||
break;
|
||||
case DOUBLE:
|
||||
out.writeDouble((Double) attribute.getValue());
|
||||
break;
|
||||
case LONG:
|
||||
out.writeLong((Long) attribute.getValue());
|
||||
break;
|
||||
case STRING:
|
||||
case SYMBOL:
|
||||
StreamUtil.writeString(out, (String) attribute.getValue());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Undefined attribute type " + type + ".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an inventory to the specified output stream.
|
||||
*
|
||||
|
||||
@@ -32,8 +32,8 @@ public final class BinaryPlayerUtil {
|
||||
* @return The file.
|
||||
*/
|
||||
public static File getFile(String username) {
|
||||
username = NameUtil.decodeBase37(NameUtil.encodeBase37(username));
|
||||
return new File(SAVED_GAMES_DIRECTORY, username + ".dat");
|
||||
String filtered = NameUtil.decodeBase37(NameUtil.encodeBase37(username));
|
||||
return new File(SAVED_GAMES_DIRECTORY, filtered + ".dat");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,8 @@ package org.apollo.io.player.impl;
|
||||
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.entity.Player;
|
||||
import org.apollo.game.model.setting.PrivilegeLevel;
|
||||
import org.apollo.game.model.entity.setting.MembershipStatus;
|
||||
import org.apollo.game.model.entity.setting.PrivilegeLevel;
|
||||
import org.apollo.io.player.PlayerLoader;
|
||||
import org.apollo.io.player.PlayerLoaderResponse;
|
||||
import org.apollo.net.codec.login.LoginConstants;
|
||||
@@ -26,7 +27,7 @@ public final class DummyPlayerLoader implements PlayerLoader {
|
||||
|
||||
Player player = new Player(credentials, DEFAULT_POSITION);
|
||||
player.setPrivilegeLevel(PrivilegeLevel.ADMINISTRATOR);
|
||||
player.setMembers(true);
|
||||
player.setMembers(MembershipStatus.PAID);
|
||||
|
||||
return new PlayerLoaderResponse(status, player);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.util.Attribute;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -65,25 +67,36 @@ public final class ApolloHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
@Override
|
||||
public void channelRead(ChannelHandlerContext ctx, Object message) {
|
||||
if (ctx.attr(NetworkConstants.SESSION_KEY).get() == null) {
|
||||
try {
|
||||
Attribute<Session> attribute = ctx.attr(NetworkConstants.SESSION_KEY);
|
||||
Session session = attribute.get();
|
||||
|
||||
if (message instanceof HttpRequest || message instanceof JagGrabRequest) {
|
||||
new UpdateSession(ctx.channel(), serverContext).messageReceived(message);
|
||||
} else {
|
||||
session = new UpdateSession(ctx.channel(), serverContext);
|
||||
}
|
||||
|
||||
if (session != null) {
|
||||
session.messageReceived(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Perhaps let HandshakeMessage implement Message to remove this explicit check
|
||||
if (message instanceof HandshakeMessage) {
|
||||
HandshakeMessage handshakeMessage = (HandshakeMessage) message;
|
||||
|
||||
switch (handshakeMessage.getServiceId()) {
|
||||
case HandshakeConstants.SERVICE_GAME:
|
||||
ctx.attr(NetworkConstants.SESSION_KEY).set(new LoginSession(ctx, serverContext));
|
||||
attribute.set(new LoginSession(ctx, serverContext));
|
||||
break;
|
||||
|
||||
case HandshakeConstants.SERVICE_UPDATE:
|
||||
ctx.attr(NetworkConstants.SESSION_KEY).set(new UpdateSession(ctx.channel(), serverContext));
|
||||
attribute.set(new UpdateSession(ctx.channel(), serverContext));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid service id.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ctx.attr(NetworkConstants.SESSION_KEY).get().messageReceived(message);
|
||||
|
||||
} finally {
|
||||
ReferenceCountUtil.release(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.burtleburtle.bob.rand.IsaacRandom;
|
||||
@@ -61,7 +60,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, GameDecoderState state) throws IOException {
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, GameDecoderState state) {
|
||||
switch (state) {
|
||||
case GAME_OPCODE:
|
||||
decodeOpcode(in, out);
|
||||
@@ -96,9 +95,8 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
* @param out The {@link List} of objects to be passed along the pipeline.
|
||||
* @throws IOException If a received opcode or packet type is illegal.
|
||||
*/
|
||||
private void decodeOpcode(ByteBuf buffer, List<Object> out) throws IOException {
|
||||
private void decodeOpcode(ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.isReadable()) {
|
||||
int encryptedOpcode = buffer.readUnsignedByte();
|
||||
opcode = encryptedOpcode - random.nextInt() & 0xFF;
|
||||
@@ -121,7 +119,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
setState(GameDecoderState.GAME_LENGTH);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Illegal packet type: " + type + ".");
|
||||
throw new IllegalStateException("Illegal packet type: " + type + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apollo.net.codec.login.LoginDecoder;
|
||||
import org.apollo.net.codec.login.LoginEncoder;
|
||||
@@ -19,35 +20,41 @@ import org.apollo.net.codec.update.UpdateEncoder;
|
||||
*/
|
||||
public final class HandshakeDecoder extends ByteToMessageDecoder {
|
||||
|
||||
/**
|
||||
* The logger for this class.
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(HandshakeDecoder.class.getName());
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.isReadable()) {
|
||||
int id = buffer.readUnsignedByte();
|
||||
|
||||
switch (id) {
|
||||
case HandshakeConstants.SERVICE_GAME:
|
||||
ctx.pipeline().addFirst("loginEncoder", new LoginEncoder());
|
||||
ctx.pipeline().addAfter("handshakeDecoder", "loginDecoder", new LoginDecoder());
|
||||
break;
|
||||
case HandshakeConstants.SERVICE_UPDATE:
|
||||
ctx.pipeline().addFirst("updateEncoder", new UpdateEncoder());
|
||||
ctx.pipeline().addBefore("handler", "updateDecoder", new UpdateDecoder());
|
||||
ByteBuf buf = ctx.alloc().buffer(8);
|
||||
buf.writeLong(0);
|
||||
ctx.channel().writeAndFlush(buf);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid service id.");
|
||||
}
|
||||
|
||||
ctx.pipeline().remove(this);
|
||||
HandshakeMessage message = new HandshakeMessage(id);
|
||||
|
||||
out.add(message);
|
||||
if (buffer.isReadable()) {
|
||||
out.add(buffer.readBytes(buffer.readableBytes()));
|
||||
}
|
||||
if (!buffer.isReadable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = buffer.readUnsignedByte();
|
||||
|
||||
switch (id) {
|
||||
case HandshakeConstants.SERVICE_GAME:
|
||||
ctx.pipeline().addFirst("loginEncoder", new LoginEncoder());
|
||||
ctx.pipeline().addAfter("handshakeDecoder", "loginDecoder", new LoginDecoder());
|
||||
break;
|
||||
|
||||
case HandshakeConstants.SERVICE_UPDATE:
|
||||
ctx.pipeline().addFirst("updateEncoder", new UpdateEncoder());
|
||||
ctx.pipeline().addBefore("handler", "updateDecoder", new UpdateDecoder());
|
||||
|
||||
ByteBuf buf = ctx.alloc().buffer(8).writeLong(0);
|
||||
ctx.channel().writeAndFlush(buf);
|
||||
break;
|
||||
|
||||
default:
|
||||
ByteBuf data = buffer.readBytes(buffer.readableBytes());
|
||||
logger.info(String.format("Unexpected handshake request received: %d data: %s", id, data.toString()));
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.pipeline().remove(this);
|
||||
out.add(new HandshakeMessage(id));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package org.apollo.net.codec.login;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.List;
|
||||
@@ -28,7 +28,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
/**
|
||||
* The secure random number generator.
|
||||
*/
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
/**
|
||||
* The login packet length.
|
||||
@@ -54,11 +54,11 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
* Creates the login decoder with the default initial state.
|
||||
*/
|
||||
public LoginDecoder() {
|
||||
super(LoginDecoderState.LOGIN_HANDSHAKE, true);
|
||||
super(LoginDecoderState.LOGIN_HANDSHAKE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, LoginDecoderState state) throws Exception {
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, LoginDecoderState state) {
|
||||
switch (state) {
|
||||
case LOGIN_HANDSHAKE:
|
||||
decodeHandshake(ctx, in, out);
|
||||
@@ -70,7 +70,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
decodePayload(ctx, in, out);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid login decoder state.");
|
||||
throw new IllegalStateException("Invalid login decoder state: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
private void decodeHandshake(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.isReadable()) {
|
||||
usernameHash = buffer.readUnsignedByte();
|
||||
serverSeed = random.nextLong();
|
||||
serverSeed = RANDOM.nextLong();
|
||||
|
||||
ByteBuf response = ctx.alloc().buffer(17);
|
||||
response.writeByte(LoginConstants.STATUS_EXCHANGE_DATA);
|
||||
@@ -102,14 +102,14 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
* @param ctx The channel handler context.
|
||||
* @param buffer The buffer.
|
||||
* @param out The {@link List} of objects to pass forward through the pipeline.
|
||||
* @throws IOException If the login type sent by the client is invalid.
|
||||
*/
|
||||
private void decodeHeader(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws IOException {
|
||||
private void decodeHeader(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.readableBytes() >= 2) {
|
||||
int loginType = buffer.readUnsignedByte();
|
||||
|
||||
if (loginType != LoginConstants.TYPE_STANDARD && loginType != LoginConstants.TYPE_RECONNECTION) {
|
||||
throw new IOException("Invalid login type.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
reconnecting = loginType == LoginConstants.TYPE_RECONNECTION;
|
||||
@@ -125,9 +125,8 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
* @param ctx The channel handler context.
|
||||
* @param buffer The buffer.
|
||||
* @param out The {@link List} of objects to pass forward through the pipeline.
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
|
||||
private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.readableBytes() >= loginLength) {
|
||||
ByteBuf payload = buffer.readBytes(loginLength);
|
||||
int clientVersion = 255 - payload.readUnsignedByte();
|
||||
@@ -136,7 +135,8 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
|
||||
int lowMemoryFlag = payload.readUnsignedByte();
|
||||
if (lowMemoryFlag != 0 && lowMemoryFlag != 1) {
|
||||
throw new Exception("Invalid value for low memory flag.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean lowMemory = lowMemoryFlag == 1;
|
||||
@@ -148,7 +148,8 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
|
||||
int securePayloadLength = payload.readUnsignedByte();
|
||||
if (securePayloadLength != loginLength - 41) {
|
||||
throw new Exception("Secure payload length mismatch.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf securePayload = payload.readBytes(securePayloadLength);
|
||||
@@ -160,13 +161,15 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
|
||||
int secureId = securePayload.readUnsignedByte();
|
||||
if (secureId != 10) {
|
||||
throw new Exception("Invalid secure payload id.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
long clientSeed = securePayload.readLong();
|
||||
long reportedServerSeed = securePayload.readLong();
|
||||
if (reportedServerSeed != serverSeed) {
|
||||
throw new Exception("Server seed mismatch.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
int uid = securePayload.readInt();
|
||||
@@ -174,10 +177,9 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
String username = BufferUtil.readString(securePayload);
|
||||
String password = BufferUtil.readString(securePayload);
|
||||
|
||||
if (password.length() < 6 || password.length() > 20) {
|
||||
throw new Exception("Invalid password.");
|
||||
} else if (username.isEmpty() || username.length() > 12) {
|
||||
throw new Exception("Invalid username.");
|
||||
if (password.length() < 6 || password.length() > 20 || username.isEmpty() || username.length() > 12) {
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_INVALID_CREDENTIALS);
|
||||
return;
|
||||
}
|
||||
|
||||
int[] seed = new int[4];
|
||||
@@ -196,14 +198,23 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
PlayerCredentials credentials = new PlayerCredentials(username, password, usernameHash, uid);
|
||||
IsaacRandomPair randomPair = new IsaacRandomPair(encodingRandom, decodingRandom);
|
||||
|
||||
LoginRequest request = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber, archiveCrcs,
|
||||
clientVersion);
|
||||
LoginRequest request = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber, archiveCrcs, clientVersion);
|
||||
|
||||
out.add(request);
|
||||
if (buffer.isReadable()) {
|
||||
out.add(buffer.readBytes(buffer.readableBytes()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a response code to the client and closes the current channel.
|
||||
*
|
||||
* @param ctx The context of the channel handler.
|
||||
* @param responseCode The response code to write.
|
||||
*/
|
||||
private void writeResponseCode(ChannelHandlerContext ctx, int responseCode) {
|
||||
ByteBuf buffer = ctx.alloc().buffer(1);
|
||||
buffer.writeByte(responseCode);
|
||||
|
||||
ctx.writeAndFlush(buffer).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.FlashTabInterfaceMessage;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link FlashTabInterfaceMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class FlashTabInterfaceMessageEncoder extends MessageEncoder<FlashTabInterfaceMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(FlashTabInterfaceMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(24);
|
||||
builder.put(DataType.BYTE, DataTransformation.SUBTRACT, message.getTab());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.FlashingTabClickedMessage;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketReader;
|
||||
import org.apollo.net.release.MessageDecoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageDecoder} for the {@link FlashingTabClickedMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class FlashingTabClickedMessageDecoder extends MessageDecoder<FlashingTabClickedMessage> {
|
||||
|
||||
@Override
|
||||
public FlashingTabClickedMessage decode(GamePacket packet) {
|
||||
GamePacketReader reader = new GamePacketReader(packet);
|
||||
int tab = (int) reader.getUnsigned(DataType.BYTE);
|
||||
return new FlashingTabClickedMessage(tab);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.OpenDialogueOverlayMessage;
|
||||
import org.apollo.net.codec.game.DataOrder;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link OpenDialogueOverlayMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenDialogueOverlayMessageEncoder extends MessageEncoder<OpenDialogueOverlayMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(OpenDialogueOverlayMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(218);
|
||||
builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getInterfaceId());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.OpenOverlayMessage;
|
||||
import org.apollo.net.codec.game.DataOrder;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link OpenOverlayMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenOverlayMessageEncoder extends MessageEncoder<OpenOverlayMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(OpenOverlayMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(208);
|
||||
builder.put(DataType.SHORT, DataOrder.LITTLE, message.getOverlayId());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.OpenSidebarMessage;
|
||||
import org.apollo.net.codec.game.DataOrder;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link OpenSidebarMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenSidebarMessageEncoder extends MessageEncoder<OpenSidebarMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(OpenSidebarMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(142);
|
||||
builder.put(DataType.SHORT, DataOrder.LITTLE, message.getSidebarId());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package org.apollo.net.release.r317;
|
||||
|
||||
import org.apollo.game.message.impl.PlayerDesignMessage;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.setting.Gender;
|
||||
import org.apollo.game.model.entity.setting.Gender;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketReader;
|
||||
|
||||
@@ -9,8 +9,8 @@ import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.def.EquipmentDefinition;
|
||||
import org.apollo.game.model.entity.EquipmentConstants;
|
||||
import org.apollo.game.model.entity.setting.Gender;
|
||||
import org.apollo.game.model.inv.Inventory;
|
||||
import org.apollo.game.model.setting.Gender;
|
||||
import org.apollo.game.sync.block.AnimationBlock;
|
||||
import org.apollo.game.sync.block.AppearanceBlock;
|
||||
import org.apollo.game.sync.block.ChatBlock;
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.apollo.game.message.impl.ConfigMessage;
|
||||
import org.apollo.game.message.impl.DisplayCrossbonesMessage;
|
||||
import org.apollo.game.message.impl.DisplayTabInterfaceMessage;
|
||||
import org.apollo.game.message.impl.EnterAmountMessage;
|
||||
import org.apollo.game.message.impl.FlashTabInterfaceMessage;
|
||||
import org.apollo.game.message.impl.ForwardPrivateChatMessage;
|
||||
import org.apollo.game.message.impl.FriendServerStatusMessage;
|
||||
import org.apollo.game.message.impl.HintIconMessage;
|
||||
@@ -15,8 +16,11 @@ import org.apollo.game.message.impl.IgnoreListMessage;
|
||||
import org.apollo.game.message.impl.LogoutMessage;
|
||||
import org.apollo.game.message.impl.NpcSynchronizationMessage;
|
||||
import org.apollo.game.message.impl.OpenDialogueInterfaceMessage;
|
||||
import org.apollo.game.message.impl.OpenDialogueOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenInterfaceMessage;
|
||||
import org.apollo.game.message.impl.OpenInterfaceSidebarMessage;
|
||||
import org.apollo.game.message.impl.OpenOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenSidebarMessage;
|
||||
import org.apollo.game.message.impl.PlayerSynchronizationMessage;
|
||||
import org.apollo.game.message.impl.PositionMessage;
|
||||
import org.apollo.game.message.impl.PrivacyOptionMessage;
|
||||
@@ -124,6 +128,7 @@ public final class Release317 extends Release {
|
||||
register(130, new ClosedInterfaceMessageDecoder());
|
||||
register(208, new EnteredAmountMessageDecoder());
|
||||
register(40, new DialogueContinueMessageDecoder());
|
||||
register(120, new FlashingTabClickedMessageDecoder());
|
||||
|
||||
register(53, new ItemOnItemMessageDecoder());
|
||||
register(237, new MagicOnItemMessageDecoder());
|
||||
@@ -207,5 +212,10 @@ public final class Release317 extends Release {
|
||||
register(IgnoreListMessage.class, new IgnoreListMessageEncoder());
|
||||
register(SendFriendMessage.class, new SendFriendMessageEncoder());
|
||||
register(HintIconMessage.class, new HintIconMessageEncoder());
|
||||
register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder());
|
||||
register(OpenSidebarMessage.class, new OpenSidebarMessageEncoder());
|
||||
register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder());
|
||||
register(OpenDialogueOverlayMessage.class, new OpenDialogueOverlayMessageEncoder());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.FlashTabInterfaceMessage;
|
||||
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.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link FlashTabInterfaceMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class FlashTabInterfaceMessageEncoder extends MessageEncoder<FlashTabInterfaceMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(FlashTabInterfaceMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(283);
|
||||
builder.put(DataType.BYTE, message.getTab());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.FlashingTabClickedMessage;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketReader;
|
||||
import org.apollo.net.release.MessageDecoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageDecoder} for the {@link FlashingTabClickedMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class FlashingTabClickedMessageDecoder extends MessageDecoder<FlashingTabClickedMessage> {
|
||||
|
||||
@Override
|
||||
public FlashingTabClickedMessage decode(GamePacket packet) {
|
||||
GamePacketReader reader = new GamePacketReader(packet);
|
||||
int tab = (int) reader.getUnsigned(DataType.BYTE);
|
||||
return new FlashingTabClickedMessage(tab);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.OpenDialogueOverlayMessage;
|
||||
import org.apollo.net.codec.game.DataOrder;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link OpenDialogueOverlayMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenDialogueOverlayMessageEncoder extends MessageEncoder<OpenDialogueOverlayMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(OpenDialogueOverlayMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(158);
|
||||
builder.put(DataType.SHORT, DataOrder.LITTLE, message.getInterfaceId());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.OpenOverlayMessage;
|
||||
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.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link OpenOverlayMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenOverlayMessageEncoder extends MessageEncoder<OpenOverlayMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(OpenOverlayMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(50);
|
||||
builder.put(DataType.SHORT, message.getOverlayId());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.OpenSidebarMessage;
|
||||
import org.apollo.net.codec.game.DataOrder;
|
||||
import org.apollo.net.codec.game.DataTransformation;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketBuilder;
|
||||
import org.apollo.net.release.MessageEncoder;
|
||||
|
||||
/**
|
||||
* A {@link MessageEncoder} for the {@link OpenSidebarMessage}.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class OpenSidebarMessageEncoder extends MessageEncoder<OpenSidebarMessage> {
|
||||
|
||||
@Override
|
||||
public GamePacket encode(OpenSidebarMessage message) {
|
||||
GamePacketBuilder builder = new GamePacketBuilder(246);
|
||||
builder.put(DataType.SHORT, DataOrder.LITTLE, DataTransformation.ADD, message.getSidebarId());
|
||||
return builder.toGamePacket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package org.apollo.net.release.r377;
|
||||
|
||||
import org.apollo.game.message.impl.PlayerDesignMessage;
|
||||
import org.apollo.game.model.Appearance;
|
||||
import org.apollo.game.model.setting.Gender;
|
||||
import org.apollo.game.model.entity.setting.Gender;
|
||||
import org.apollo.net.codec.game.DataType;
|
||||
import org.apollo.net.codec.game.GamePacket;
|
||||
import org.apollo.net.codec.game.GamePacketReader;
|
||||
|
||||
@@ -9,8 +9,8 @@ import org.apollo.game.model.Item;
|
||||
import org.apollo.game.model.Position;
|
||||
import org.apollo.game.model.def.EquipmentDefinition;
|
||||
import org.apollo.game.model.entity.EquipmentConstants;
|
||||
import org.apollo.game.model.entity.setting.Gender;
|
||||
import org.apollo.game.model.inv.Inventory;
|
||||
import org.apollo.game.model.setting.Gender;
|
||||
import org.apollo.game.sync.block.AnimationBlock;
|
||||
import org.apollo.game.sync.block.AppearanceBlock;
|
||||
import org.apollo.game.sync.block.ChatBlock;
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.apollo.game.message.impl.ConfigMessage;
|
||||
import org.apollo.game.message.impl.DisplayCrossbonesMessage;
|
||||
import org.apollo.game.message.impl.DisplayTabInterfaceMessage;
|
||||
import org.apollo.game.message.impl.EnterAmountMessage;
|
||||
import org.apollo.game.message.impl.FlashTabInterfaceMessage;
|
||||
import org.apollo.game.message.impl.ForwardPrivateChatMessage;
|
||||
import org.apollo.game.message.impl.FriendServerStatusMessage;
|
||||
import org.apollo.game.message.impl.HintIconMessage;
|
||||
@@ -15,8 +16,11 @@ import org.apollo.game.message.impl.IgnoreListMessage;
|
||||
import org.apollo.game.message.impl.LogoutMessage;
|
||||
import org.apollo.game.message.impl.NpcSynchronizationMessage;
|
||||
import org.apollo.game.message.impl.OpenDialogueInterfaceMessage;
|
||||
import org.apollo.game.message.impl.OpenDialogueOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenInterfaceMessage;
|
||||
import org.apollo.game.message.impl.OpenInterfaceSidebarMessage;
|
||||
import org.apollo.game.message.impl.OpenOverlayMessage;
|
||||
import org.apollo.game.message.impl.OpenSidebarMessage;
|
||||
import org.apollo.game.message.impl.PlayerSynchronizationMessage;
|
||||
import org.apollo.game.message.impl.PositionMessage;
|
||||
import org.apollo.game.message.impl.PrivacyOptionMessage;
|
||||
@@ -124,6 +128,7 @@ public final class Release377 extends Release {
|
||||
register(110, new ClosedInterfaceMessageDecoder());
|
||||
register(75, new EnteredAmountMessageDecoder());
|
||||
register(226, new DialogueContinueMessageDecoder());
|
||||
register(119, new FlashingTabClickedMessageDecoder());
|
||||
|
||||
register(1, new ItemOnItemMessageDecoder());
|
||||
register(36, new MagicOnItemMessageDecoder());
|
||||
@@ -203,6 +208,10 @@ public final class Release377 extends Release {
|
||||
register(IgnoreListMessage.class, new IgnoreListMessageEncoder());
|
||||
register(SendFriendMessage.class, new SendFriendMessageEncoder());
|
||||
register(HintIconMessage.class, new HintIconMessageEncoder());
|
||||
register(FlashTabInterfaceMessage.class, new FlashTabInterfaceMessageEncoder());
|
||||
register(OpenSidebarMessage.class, new OpenSidebarMessageEncoder());
|
||||
register(OpenOverlayMessage.class, new OpenOverlayMessageEncoder());
|
||||
register(OpenDialogueOverlayMessage.class, new OpenDialogueOverlayMessageEncoder());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,37 +85,34 @@ public final class LoginSession extends Session {
|
||||
* @param response The response.
|
||||
*/
|
||||
public void handlePlayerLoaderResponse(LoginRequest request, PlayerLoaderResponse response) {
|
||||
GameService gameService = serverContext.getService(GameService.class);
|
||||
GameService service = serverContext.getService(GameService.class);
|
||||
Channel channel = getChannel();
|
||||
|
||||
Optional<Player> responsePlayer = response.getPlayer();
|
||||
Optional<Player> optional = response.getPlayer();
|
||||
int status = response.getStatus(), rights = 0;
|
||||
boolean flagged = false;
|
||||
|
||||
if (responsePlayer.isPresent()) {
|
||||
Player player = responsePlayer.get();
|
||||
if (optional.isPresent()) {
|
||||
Player player = optional.get();
|
||||
rights = player.getPrivilegeLevel().toInteger();
|
||||
|
||||
GameSession session = new GameSession(channel, serverContext, player);
|
||||
player.setSession(session, false /* TODO */);
|
||||
RegistrationStatus registration = service.registerPlayer(player, session);
|
||||
|
||||
RegistrationStatus registrationStatus = gameService.registerPlayer(player);
|
||||
|
||||
if (registrationStatus != RegistrationStatus.OK) {
|
||||
responsePlayer = Optional.empty();
|
||||
if (registration != RegistrationStatus.OK) {
|
||||
optional = Optional.empty();
|
||||
rights = 0;
|
||||
if (registrationStatus == RegistrationStatus.ALREADY_ONLINE) {
|
||||
status = LoginConstants.STATUS_ACCOUNT_ONLINE;
|
||||
} else {
|
||||
status = LoginConstants.STATUS_SERVER_FULL;
|
||||
}
|
||||
|
||||
status = (registration == RegistrationStatus.ALREADY_ONLINE) ? LoginConstants.STATUS_ACCOUNT_ONLINE
|
||||
: LoginConstants.STATUS_SERVER_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
ChannelFuture future = channel.writeAndFlush(new LoginResponse(status, rights, flagged));
|
||||
|
||||
destroy();
|
||||
|
||||
if (responsePlayer.isPresent()) {
|
||||
if (optional.isPresent()) {
|
||||
IsaacRandomPair randomPair = request.getRandomPair();
|
||||
Release release = serverContext.getRelease();
|
||||
|
||||
@@ -129,10 +126,14 @@ public final class LoginSession extends Session {
|
||||
channel.pipeline().remove("loginDecoder");
|
||||
channel.pipeline().remove("loginEncoder");
|
||||
|
||||
channelContext.attr(NetworkConstants.SESSION_KEY).set(responsePlayer.get().getSession());
|
||||
channelContext.attr(NetworkConstants.SESSION_KEY).set(optional.get().getSession());
|
||||
} else {
|
||||
future.addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
if (optional.isPresent() && !request.isReconnecting()) {
|
||||
optional.get().sendInitialMessages();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package org.apollo.tools;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apollo.fs.IndexedFileSystem;
|
||||
import org.apollo.fs.decoder.ItemDefinitionDecoder;
|
||||
import org.apollo.game.model.def.ItemDefinition;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* A tool for updating the note data.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class NoteUpdater {
|
||||
|
||||
/**
|
||||
* The entry point of the application.
|
||||
*
|
||||
* @param args The command line arguments.
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
Preconditions.checkArgument(args.length == 1, "Usage:\njava -cp ... org.apollo.tools.NoteUpdater [release].");
|
||||
String release = args[0];
|
||||
|
||||
try (DataOutputStream os = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data/note-" + release
|
||||
+ ".dat")));
|
||||
IndexedFileSystem fs = new IndexedFileSystem(Paths.get("data/fs/", release), true)) {
|
||||
ItemDefinitionDecoder decoder = new ItemDefinitionDecoder(fs);
|
||||
ItemDefinition[] defs = decoder.decode();
|
||||
ItemDefinition.init(defs);
|
||||
|
||||
os.writeShort(defs.length);
|
||||
Map<Integer, Integer> itemToNote = new HashMap<>();
|
||||
|
||||
for (int id = 0; id < defs.length; id++) {
|
||||
ItemDefinition def = ItemDefinition.lookup(id);
|
||||
if (def.isNote()) {
|
||||
itemToNote.put(def.getNoteInfoId(), def.getId());
|
||||
}
|
||||
}
|
||||
|
||||
for (int id = 0; id < defs.length; id++) {
|
||||
if (itemToNote.containsKey(id)) {
|
||||
os.writeBoolean(true); // notable
|
||||
os.writeShort(itemToNote.get(id));
|
||||
} else {
|
||||
os.writeBoolean(false); // not notable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,11 +9,13 @@ import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.handler.codec.http.HttpResponse;
|
||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apollo.fs.IndexedFileSystem;
|
||||
import org.apollo.update.resource.CombinedResourceProvider;
|
||||
@@ -21,6 +23,8 @@ import org.apollo.update.resource.HypertextResourceProvider;
|
||||
import org.apollo.update.resource.ResourceProvider;
|
||||
import org.apollo.update.resource.VirtualResourceProvider;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
/**
|
||||
* A worker which services HTTP requests.
|
||||
*
|
||||
@@ -31,7 +35,7 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
|
||||
/**
|
||||
* The default character set.
|
||||
*/
|
||||
private static final Charset CHARACTER_SET = Charset.forName("ISO-8859-1");
|
||||
private static final Charset CHARACTER_SET = Charsets.ISO_8859_1;
|
||||
|
||||
/**
|
||||
* The value of the server header.
|
||||
@@ -41,7 +45,7 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
|
||||
/**
|
||||
* The directory with web files.
|
||||
*/
|
||||
private static final File WWW_DIRECTORY = new File("./data/www/");
|
||||
private static final Path WWW_DIRECTORY = Paths.get("data/www");
|
||||
|
||||
/**
|
||||
* Creates the HTTP request worker.
|
||||
@@ -50,8 +54,7 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
|
||||
* @param fs The file system.
|
||||
*/
|
||||
public HttpRequestWorker(UpdateDispatcher dispatcher, IndexedFileSystem fs) {
|
||||
super(dispatcher, new CombinedResourceProvider(new VirtualResourceProvider(fs), new HypertextResourceProvider(
|
||||
WWW_DIRECTORY)));
|
||||
super(dispatcher, new CombinedResourceProvider(new VirtualResourceProvider(fs), new HypertextResourceProvider(WWW_DIRECTORY)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,21 +118,18 @@ public final class HttpRequestWorker extends RequestWorker<HttpRequest, Resource
|
||||
@Override
|
||||
protected void service(ResourceProvider provider, Channel channel, HttpRequest request) throws IOException {
|
||||
String path = request.getUri();
|
||||
ByteBuffer buf = provider.get(path);
|
||||
Optional<ByteBuffer> buf = provider.get(path);
|
||||
|
||||
ByteBuf wrapped;
|
||||
HttpResponseStatus status = HttpResponseStatus.OK;
|
||||
|
||||
String mime = getMimeType(request.getUri());
|
||||
|
||||
if (buf == null) {
|
||||
if (!buf.isPresent()) {
|
||||
status = HttpResponseStatus.NOT_FOUND;
|
||||
wrapped = createErrorPage(status, "The page you requested could not be found.");
|
||||
mime = "text/html";
|
||||
} else {
|
||||
wrapped = Unpooled.wrappedBuffer(buf);
|
||||
}
|
||||
|
||||
ByteBuf wrapped = buf.isPresent() ? Unpooled.wrappedBuffer(buf.get()) : createErrorPage(status, "The page you requested could not be found.");
|
||||
|
||||
HttpResponse response = new DefaultHttpResponse(request.getProtocolVersion(), status);
|
||||
|
||||
response.headers().set("Date", new Date());
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.netty.channel.ChannelFutureListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apollo.fs.IndexedFileSystem;
|
||||
import org.apollo.net.codec.jaggrab.JagGrabRequest;
|
||||
@@ -38,12 +39,13 @@ public final class JagGrabRequestWorker extends RequestWorker<JagGrabRequest, Re
|
||||
|
||||
@Override
|
||||
protected void service(ResourceProvider provider, Channel channel, JagGrabRequest request) throws IOException {
|
||||
ByteBuffer buf = provider.get(request.getFilePath());
|
||||
if (buf == null) {
|
||||
channel.close();
|
||||
} else {
|
||||
ByteBuf wrapped = Unpooled.wrappedBuffer(buf);
|
||||
Optional<ByteBuffer> buffer = provider.get(request.getFilePath());
|
||||
|
||||
if (buffer.isPresent()) {
|
||||
ByteBuf wrapped = Unpooled.wrappedBuffer(buffer.get());
|
||||
channel.writeAndFlush(new JagGrabResponse(wrapped)).addListener(ChannelFutureListener.CLOSE);
|
||||
} else {
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@ package org.apollo.update.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A resource provider composed of multiple resource providers.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class CombinedResourceProvider extends ResourceProvider {
|
||||
public final class CombinedResourceProvider implements ResourceProvider {
|
||||
|
||||
/**
|
||||
* An array of resource providers.
|
||||
@@ -30,13 +31,13 @@ public final class CombinedResourceProvider extends ResourceProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer get(String path) throws IOException {
|
||||
public Optional<ByteBuffer> get(String path) throws IOException {
|
||||
for (ResourceProvider provider : providers) {
|
||||
if (provider.accept(path)) {
|
||||
return provider.get(path);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,62 +1,67 @@
|
||||
package org.apollo.update.resource;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.FileChannel.MapMode;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A {@link ResourceProvider} which provides additional hypertext resources.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class HypertextResourceProvider extends ResourceProvider {
|
||||
public final class HypertextResourceProvider implements ResourceProvider {
|
||||
|
||||
/**
|
||||
* The base directory from which documents are served.
|
||||
* The base {@link Path} from which documents are served.
|
||||
*/
|
||||
private final File base;
|
||||
private final Path base;
|
||||
|
||||
/**
|
||||
* Creates a new hypertext resource provider with the specified base directory.
|
||||
*
|
||||
* @param base The base directory.
|
||||
*/
|
||||
public HypertextResourceProvider(File base) {
|
||||
public HypertextResourceProvider(Path base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(String path) throws IOException {
|
||||
File file = new File(base, path);
|
||||
URI target = file.toURI().normalize();
|
||||
if (target.toASCIIString().startsWith(base.toURI().normalize().toASCIIString())) {
|
||||
if (file.isDirectory()) {
|
||||
file = new File(file, "index.html");
|
||||
}
|
||||
return file.exists();
|
||||
Path file = base.resolve(path);
|
||||
|
||||
URI target = file.toUri().normalize();
|
||||
if (!target.toASCIIString().startsWith(base.toUri().normalize().toASCIIString())) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (Files.isDirectory(file)) {
|
||||
file = file.resolve("index.html");
|
||||
}
|
||||
|
||||
return Files.exists(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer get(String path) throws IOException {
|
||||
File file = new File(base, path);
|
||||
if (file.isDirectory()) {
|
||||
file = new File(file, "index.html");
|
||||
}
|
||||
if (!file.exists()) {
|
||||
return null;
|
||||
public Optional<ByteBuffer> get(String path) throws IOException {
|
||||
Path root = base.resolve(path);
|
||||
|
||||
if (Files.isDirectory(root)) {
|
||||
root = root.resolve("index.html");
|
||||
}
|
||||
|
||||
ByteBuffer buffer;
|
||||
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
|
||||
buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, raf.length());
|
||||
if (!Files.exists(root)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return buffer;
|
||||
try (FileChannel channel = FileChannel.open(root)) {
|
||||
ByteBuffer buf = channel.map(MapMode.READ_ONLY, 0, Files.size(root));
|
||||
return Optional.of(buf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,13 +2,14 @@ package org.apollo.update.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* A class which provides resources.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public abstract class ResourceProvider {
|
||||
public interface ResourceProvider {
|
||||
|
||||
/**
|
||||
* Checks that this provider can fulfil a request to the specified resource.
|
||||
@@ -17,15 +18,16 @@ public abstract class ResourceProvider {
|
||||
* @return {@code true} if the provider can fulfil a request to the resource, {@code false} otherwise.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public abstract boolean accept(String path) throws IOException;
|
||||
public boolean accept(String path) throws IOException;
|
||||
|
||||
/**
|
||||
* Gets a resource by its path.
|
||||
* Gets the resource data, as a {@link ByteBuffer}, wrapped in an {@link Optional}.
|
||||
*
|
||||
* @param path The path.
|
||||
* @return The resource, or {@code null} if it doesn't exist.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
* @param path The path to the resource.
|
||||
* @return A {@code ByteBuffer} representation of a resource if it exists otherwise {@link Optional#empty()} is
|
||||
* returned.
|
||||
* @throws IOException If some I/O exception occurs.
|
||||
*/
|
||||
public abstract ByteBuffer get(String path) throws IOException;
|
||||
public Optional<ByteBuffer> get(String path) throws IOException;
|
||||
|
||||
}
|
||||
@@ -2,6 +2,10 @@ package org.apollo.update.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apollo.fs.IndexedFileSystem;
|
||||
|
||||
@@ -11,13 +15,12 @@ import org.apollo.fs.IndexedFileSystem;
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class VirtualResourceProvider extends ResourceProvider {
|
||||
public final class VirtualResourceProvider implements ResourceProvider {
|
||||
|
||||
/**
|
||||
* An array of valid prefixes.
|
||||
* A {@link List} of valid prefixes.
|
||||
*/
|
||||
private static final String[] VALID_PREFIXES = { "crc", "title", "config", "interface", "media", "versionlist", "textures",
|
||||
"wordenc", "sounds" };
|
||||
private static final List<String> VALID_PREFIXES = Arrays.asList("/crc", "/title", "/config", "/interface", "/media", "/versionlist", "/textures", "/wordenc", "/sounds");
|
||||
|
||||
/**
|
||||
* The file system.
|
||||
@@ -26,7 +29,7 @@ public final class VirtualResourceProvider extends ResourceProvider {
|
||||
|
||||
/**
|
||||
* Creates a new virtual resource provider with the specified file system.
|
||||
*
|
||||
*
|
||||
* @param fs The file system.
|
||||
*/
|
||||
public VirtualResourceProvider(IndexedFileSystem fs) {
|
||||
@@ -35,36 +38,34 @@ public final class VirtualResourceProvider extends ResourceProvider {
|
||||
|
||||
@Override
|
||||
public boolean accept(String path) throws IOException {
|
||||
for (String prefix : VALID_PREFIXES) {
|
||||
if (path.startsWith("/" + prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
return VALID_PREFIXES.stream().anyMatch(path::startsWith);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer get(String path) throws IOException {
|
||||
public Optional<ByteBuffer> get(String path) throws IOException {
|
||||
if (path.startsWith("/crc")) {
|
||||
return fs.getCrcTable();
|
||||
return Optional.of(fs.getCrcTable());
|
||||
} else if (path.startsWith("/title")) {
|
||||
return fs.getFile(0, 1);
|
||||
return Optional.of(fs.getFile(0, 1));
|
||||
} else if (path.startsWith("/config")) {
|
||||
return fs.getFile(0, 2);
|
||||
return Optional.of(fs.getFile(0, 2));
|
||||
} else if (path.startsWith("/interface")) {
|
||||
return fs.getFile(0, 3);
|
||||
return Optional.of(fs.getFile(0, 3));
|
||||
} else if (path.startsWith("/media")) {
|
||||
return fs.getFile(0, 4);
|
||||
return Optional.of(fs.getFile(0, 4));
|
||||
} else if (path.startsWith("/versionlist")) {
|
||||
return fs.getFile(0, 5);
|
||||
return Optional.of(fs.getFile(0, 5));
|
||||
} else if (path.startsWith("/textures")) {
|
||||
return fs.getFile(0, 6);
|
||||
return Optional.of(fs.getFile(0, 6));
|
||||
} else if (path.startsWith("/wordenc")) {
|
||||
return fs.getFile(0, 7);
|
||||
return Optional.of(fs.getFile(0, 7));
|
||||
} else if (path.startsWith("/sounds")) {
|
||||
return fs.getFile(0, 8);
|
||||
return Optional.of(fs.getFile(0, 8));
|
||||
}
|
||||
return null;
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,8 +5,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A stateful implementation of a {@link ByteToMessageDecoder} which may be extended and used by other classes. The
|
||||
@@ -17,7 +16,7 @@ import com.google.common.base.Preconditions;
|
||||
* The current state is supplied as a parameter in the {@link StatefulFrameDecoder#decode} and
|
||||
* {@link StatefulFrameDecoder#decodeLast} methods.
|
||||
*
|
||||
* This class is not thread safe: it is recommended that the state is only set in the decode methods overriden.
|
||||
* This class is not thread safe: it is recommended that the state is only set in the decode methods overridden.
|
||||
*
|
||||
* @author Graham
|
||||
* @param <T> The state enumeration.
|
||||
@@ -36,17 +35,6 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMess
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public StatefulFrameDecoder(T state) {
|
||||
this(state, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the stateful frame decoder with the specified initial state and unwrap flag.
|
||||
*
|
||||
* @param state The initial state.
|
||||
* @param unwrap The unwrap flag.
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public StatefulFrameDecoder(T state, boolean unwrap) {
|
||||
setState(state);
|
||||
}
|
||||
|
||||
@@ -66,24 +54,6 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMess
|
||||
*/
|
||||
protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, T state) throws Exception;
|
||||
|
||||
@Override
|
||||
protected final void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
decodeLast(ctx, in, out, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes remaining data before the channel is closed into a frame. You may override this method, but it is not
|
||||
* required. If you do not, remaining data will be discarded!
|
||||
*
|
||||
* @param ctx The current context of this handler.
|
||||
* @param in The cumulative buffer, which may contain zero or more bytes.
|
||||
* @param out The {@link List} of objects to pass forward through the pipeline.
|
||||
* @param state The current state. The state may be changed by calling {@link #setState}.
|
||||
*/
|
||||
protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, T state) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new state.
|
||||
*
|
||||
@@ -91,8 +61,7 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMess
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public final void setState(T state) {
|
||||
Preconditions.checkNotNull(state, "State cannot be null.");
|
||||
this.state = state;
|
||||
this.state = Objects.requireNonNull(state, "State cannot be null.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,24 +3,24 @@ package org.apollo.util.plugin;
|
||||
import org.apollo.ServerContext;
|
||||
import org.apollo.game.GameService;
|
||||
import org.apollo.game.command.CommandListener;
|
||||
import org.apollo.game.login.LoginListener;
|
||||
import org.apollo.game.login.LogoutListener;
|
||||
import org.apollo.game.message.Message;
|
||||
import org.apollo.game.message.handler.MessageHandler;
|
||||
import org.apollo.game.message.handler.MessageHandlerChain;
|
||||
import org.apollo.game.message.handler.MessageHandlerChainGroup;
|
||||
import org.apollo.game.model.World;
|
||||
import org.apollo.game.model.event.EventListener;
|
||||
import org.apollo.game.model.event.impl.LoginEvent;
|
||||
import org.apollo.game.model.event.impl.LogoutEvent;
|
||||
|
||||
/**
|
||||
* The {@link PluginContext} contains methods a plugin can use to interface with the server, for example, by adding
|
||||
* {@link MessageHandler}s to {@link MessageHandlerChain}s.
|
||||
*
|
||||
* @author Graham
|
||||
* @author Major
|
||||
*/
|
||||
public final class PluginContext {
|
||||
|
||||
// TODO move listeners to world?
|
||||
|
||||
/**
|
||||
* Adds a {@link CommandListener}.
|
||||
*
|
||||
@@ -32,21 +32,21 @@ public final class PluginContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link LoginListener}.
|
||||
* Adds an {@link EventListener} for a {@link LoginEvent}.
|
||||
*
|
||||
* @param listener The listener.
|
||||
*/
|
||||
public static void addLoginListener(LoginListener listener) {
|
||||
World.getWorld().getLoginDispatcher().register(listener);
|
||||
public static void addLoginListener(EventListener<LoginEvent> listener) {
|
||||
World.getWorld().listenFor(LoginEvent.class, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link LogoutListener}.
|
||||
* Adds an {@link EventListener} for a {@link LogoutEvent}.
|
||||
*
|
||||
* @param listener The listener.
|
||||
*/
|
||||
public static void addLogoutListener(LogoutListener listener) {
|
||||
World.getWorld().getLogoutDispatcher().register(listener);
|
||||
public static void addLogoutListener(EventListener<LogoutEvent> listener) {
|
||||
World.getWorld().listenFor(LogoutEvent.class, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user