I'm planning on using a message queue for communication between a game engine and game server. This should allow me to write both without direct dependencies on each other.
The example that I'll use in this question is a DisconnectMessage
. A server can send a DisconnectMessage
to the engine if, for example, the client has exceeded the timeout value and has not responded to a ping request. The engine can also send a DisconnectMessage
to the server if, for example, a server operator issues a kick
command for a player. In both of these cases, the player is saved to the game's player repository.
So what I have at the moment is a server, a game engine, and two message queues (one for incoming, one for outgoing).
For now, what I'd like to have is one instance of a type-safe message handler for each message type. This is where the problem is for me, as I am unable to get a specific handler for a generic message.
The code I have is something like:
public interface GameMessage { } public interface GameMessageHandler<T extends GameMessage> { public void handle(T message); } public class DisconnectMessage implements GameMessage { // ... } public class DisconnectMessageHandler implements GameMessageHandler<DisconnectMessage> { @Override public void handle(DisconnectMessage message) { // ... something something } } public class GameEngine implements Runnable { public GameEngine(Queue<GameMessage> in, Queue<GameMessage> out) { // ... } @Override public void run() { if (!in.empty()) { GameMessage message = in.poll(); handle(message); } } }
The current method I have (that does not work) is as follows
// in GameEngine public <T extends GameMessage> void handle(T message) { GameMessageHandler<T> handler = getHandler(message.getClass()); handler.handle(message); } public <M extends Message, H extends GameMessageHandler<M>> H getHandler(Class<M> messageClass) { // get handler somehow from a dictionary }
However, Java's type system does not allow me to achieve this in this manner.
Is there a way that I can get a concrete message handler from the base interface class?
Or, perhaps a different question that could change the answer; is there a different/better way than using a message queue to prevent a circular dependency?