Newer
Older
hanabi-networking / src / server / Message.java
package server;

import org.json.JSONObject;

import card.Card;

import org.json.JSONException;

public class Message {
	public static final byte[] MAGIC = { 1, 3, 3, 7 };

	public static final byte MSG_FIRST_MSG = Move.DRY << 1;
	public static final byte MSG_YOURTURN = MSG_FIRST_MSG + 0;
	public static final byte MAG_READY = MSG_FIRST_MSG + 1;
	public static final byte MSG_UNREADY = MSG_FIRST_MSG + 2;
	public static final byte MSG_INVALID = MSG_FIRST_MSG + 3; //FIXME first, fix all other errors (META_MOVE_INVALID)
	public static final byte MSG_VALID = MSG_FIRST_MSG + 4; //FIXME first, fix all other errors (META_MOVE_VALID)
	public static final byte MSG_WON = MSG_FIRST_MSG + 5;
	public static final byte MSG_LOST = MSG_FIRST_MSG + 6;
	public static final byte MSG_LEAVE = MSG_FIRST_MSG + 7;
	public static final byte MSG_CONNECTION_VALID = MSG_FIRST_MSG + 8;
	public static final byte MSG_CONNECTION_INVALID = MSG_FIRST_MSG + 9;
	public static final byte MSG_LAST_MSG = MSG_CONNECTION_INVALID;

	public static final byte HINT_COLOR = 0;
	public static final byte HINT_VALUE = 1;

	public enum MsgByteCat { MSG, MOVE, INVALID };

	private static MsgByteCat msgByteCat(byte b) {
		if(b > 0 && b < MSG_FIRST_MSG) return MsgByteCat.MOVE;
		if(b >= MSG_FIRST_MSG && b <= MSG_LAST_MSG) return MsgByteCat.MSG;
		return MsgByteCat.INVALID;
	}
	
	private static void throwOnWrongMsgByte(byte b, MsgByteCat shouldBe) {
		MsgByteCat is = msgByteCat(b);
		if(is != shouldBe) {
			throw new InternalHanabiError("Message type is " + is + ", but it should be " + shouldBe + ".");
		}
	}

	private int origin;
	private byte msgType;
	private Move move;
	//private JSONObject jo;

	public Message(byte mT) { this(-1, mT); }
	public Message(byte mT, Move m) { this(-1, mT, m); }
	
	public Message(int o, byte mT) {
		throwOnWrongMsgByte(mT, MsgByteCat.MSG);
		origin = o;
		setMsgType(mT);
	}

	public Message(int o, byte moveType, Move m) {
		throwOnWrongMsgByte(moveType, MsgByteCat.MOVE);
		origin = o;
		setMsgType(moveType);
		move = m;
	}

	//public Message(JSONObject jo) throws JSONException {
		//this.jo = (JSONObject)jo.clone();
		//this.jo = jo; // TODO: clone?
//		moveType = (byte)jo.getInt("msgType");
	//}

//	public static Message newMove(Card c) {
//		try {
//			return new Message(c.toJson());
//		} catch(JSONException ex) {
//			throw new InternalHanabiError(ex);
//		}
//	}

	public Message(byte[] bytes) {
		throw new RuntimeException("Not implemented. This is a bug.");
	}

	public byte[] toBytes() {
		return toBytes(ServerGame.PROTO_VIBE_DUMB);
	}

	public byte[] toBytes(byte proto) {
		switch(proto) {
		case ServerGame.PROTO_VIBE_DUMB:
			throw new RuntimeException("Not implemented. This is a bug.");
		default:
			throw new InternalHanabiError("Message.toBytes(byte) called with invalid protocol code " + proto + ".");
		}
	}

//	public JSONObject getJson() {
//		return jo;
//	}
//	public String toJsonString() {
//		if(jo == null) return "";
//		return jo.toString();
//	}
	public byte getMsgType() {
		return msgType; 
	}

	public int getOrigin() {
		return origin;
//		try {
//			return jo.getInt("origin");
//		} catch(JSONException ex) {
//			throw new InternalHanabiError(ex);
//		}
	}

	public void setOrigin(int orig) { origin = orig; }

	public int getHintType() {
		if(msgType != Move.HINT) {
			throw new RuntimeException("Internal Error: Hint type of non-hint move requested.");
		}
		try {
			return jo.getInt("type");
		} catch(JSONException ex) {
			throw new InternalHanabiError(ex);
		}
	}
	public int getValue() {
		if(msgType != Move.HINT) {
			throw new RuntimeException("Internal Error: Hint value of non-hint message requested.");
		}
		try {
			return jo.getInt("value");
		} catch(JSONException ex) {
			throw new InternalHanabiError(ex);
		}
	}
	public int getHintRecipient() {
		if(msgType != Move.HINT) {
			throw new RuntimeException("Internal Error: Target player ID of non-hint message requested.");
		}
		try {
			return jo.getInt("playerId");
		} catch(JSONException ex) {
			throw new InternalHanabiError(ex);
		}
	}
	
	public int getOwnId() {
		if(msgType != MSG_CONNECTION_VALID) {
			throw new RuntimeException("Internal Error: ownId of non-connection valid message requested.");
		}
		try {
			return jo.getInt("id");
		} catch(JSONException ex) {
			throw new InternalHanabiError(ex);
		}
	}

	public static Message makeInvalidMoveAnswer(Message m) {
		return new Message(MSG_INVALID);
	}

	public static Message makeItsYourTurnMessage() {
		return new Message(MSG_YOURTURN);
	}

	public boolean isNonMove() {
		return msgByteCat(msgType) == MsgByteCat.MSG;
		//return msgType >= MSG_FIRST_MSG;
	}

	public void setMsgType(byte msgType) {
		this.msgType = msgType;
		try {
			jo.put("msgType", msgType);
		} catch (JSONException ex) {
			throw new InternalHanabiError(ex);
		}
	}
	public Move getMove() {
		return move;
	}
}