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?