2

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?

1

Using queues is a good idea, but I'm not a fan of using Java serialization to pass the message objects, or of using java classes to represent various message types. The whole serialization process is too opaque, inefficient, and wasteful of bandwidth. It's also fragile in the sense that minor differences between client and server class hierarchies can cause the communication to break, and there is no hope of ever having clients that are not based on the same Java classes.

I would define your message structure as a text stream that can be parsed, and implement java classes to print/parse it. The amount that these messages are implemented by java classes is up to you.

You'll thank yourself daily for making your basic communication stream something that ought to be humanly comprehensible. And don't forget to tack on your own end-to-end sequencing, checksums, and hashes to assure the integrity of your communications. Network errors are not the only thing you're guarding against - there are also bugs elsewhere in the process, and the prospect of hackers interfering your your communications.

  • My apologies, I'm not serializing this over the network. Both of these are (currently) running within the same JVM instance, so the queue will hold the actual objects. – Zymus Sep 22 '16 at 5:37
  • Eventually you will (serialize). Without serialization, there are lots of possible structures, define class Message with abstract method DoIt(), and all subclasses of Message will define a DoIt() method, and your inner loop will contain thisMessage.DoIt() to handle the message. – ddyer Sep 22 '16 at 7:09
  • 1
    Totally agree on the human-comprehensibility. Look into using something a library like Apache Thrift to do a lot of the hard work for you. It has a lot of flexibility including the ability to define your own message protocol if you want something efficient. – Kevin Shea Dec 21 '16 at 8:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.