Networked bit of a client

Hello guys!

What does JGO know about client design?

How should packets be handled when they’re incoming? How about outgoing?
You could technically set it up exactly as on the server, but it just feels wrong.

I began with java when writing servers, and working on those exclusively, so that i can do pretty well. I never participated in the work regarding clients, though, hence I don’t know anything about their design.

Is there any good reads on this, you guys can approve of?

This is for a game that requires a constant flow of packets, both ways.

There are a lot of topics here on this sort of thing. But otherwise the requirements are very vague. You need to define what you want to do a bit better than “constant flow of packets”.

I’m sending out packets at least twice every second to each client, for updating.
The client is supposed to send packets when something happens, such as movement or chat.

I’m using KryoNet, so I kind of want to use the same bindings for packet-handlers on both the client and the server.
It’s an array with classes that handles what happens in the application every time a packet is rechieved. Each of these handlers, are on the index in the array that matches the packetID of whateverr packet needs handling. It’s kind of like a huge switch.

I’m thinking I would like to bind them like this the same way on the client, as on the server. However, I’d like to override the actual handlers.
Would that even be possible, let alone “correct” for a networked application?

Can anyone give me some pseudo-code or soemthing, around how the entry-point of the client, the game-code, and the network-relating code is/could be/should be connected? :slight_smile:

sounds a lot like my system :stuck_out_tongue: cool


public class Packets {

	private static final int[] sizes = new int[256];
	private static final Packet[] packets = new Packet[256];
	static {
		packets[187] = new AttemptLogin();
		sizes[187] = -1;
		packets[23] = new RemotePlayer();
		sizes[23] = -1;
		packets[112] = new DrawingAction();
		sizes[112] = -1;
		packets[83] = new ChatMessage();
		sizes[83] = -1; // size can change, send it as a byte
		packets[241] = new RegionRequest();
		sizes[241] = -2; // size can change, send it as an int
	}

	public static Buffer fragment;
	public static ISAAC decryptor;

	public static void handle(Buffer buffer) { // read a chunk of data as a byte[] and pass it along to my custom Buffer class for easy reading
		boolean decrypt = true;
		if (fragment != null) {
			buffer.insertStart(fragment.array());
			fragment = null;
			decrypt = false;
		}
		while (buffer.remaining() > 0) {
			int opcode = buffer.getSigned();
			if (decrypt) {
				if (decryptor != null)
					opcode -= decryptor.next();
			} else {
				decrypt = true;
			}
			opcode &= 0xFF;

			int size = sizes[opcode];
			Packet packet = packets[opcode];
			if (packet == null) {
				System.out.println("Non-existant packet: " + opcode);
				return;
			}

			if (size == -1) {
				if (buffer.remaining() > 0)
					size = buffer.get();
				else {
					fragment = new Buffer(2).put(opcode);
					buffer.clear();
					System.out.println("Storing fragmented packet " + opcode + ".");
					return;
				}
			} else if (size == -2) {
				if (buffer.remaining() > 3)
					size = buffer.getInt();
				else {
					fragment = new Buffer(2).put(opcode);
					buffer.clear();
					System.out.println("Storing fragmented packet " + opcode + ".");
					return;
				}
			}

			int remaining = buffer.remaining() - size;

			if (remaining < 0) {
				fragment = new Buffer().put(opcode);
				if (sizes[opcode] == -2)
					fragment.putInt(size);
				else
					fragment.put(size);
				fragment.put(buffer.getBackingBuffer(), buffer.readPosition(), buffer.remaining());
				buffer.clear();
				System.out.println("Storing fragmented packet " + opcode + ", size " + fragment.writePosition() + ".");
				return;
			}

			try {
				packet.execute(buffer, opcode, size);
			} catch (Exception e) {
				e.printStackTrace();
			}

			if (buffer.remaining() != remaining) {
				System.out.println("<Opcode:" + opcode + "> Expected: " + remaining +", Actual: " + buffer.remaining());
				buffer.skip(buffer.remaining() - remaining);
			}
		}
	}

}