Advertisement

game's protocol between client/server

Started by June 10, 2014 12:17 PM
3 comments, last by YyYo 10 years, 5 months ago

Hi...

I an designing my first game, like checkers, and decided that messages between client and server will be text based(json).

In the game, each player in its turn, can:

- move to next position

- kill opponent's soldier

- eaten by opponent soldier

option 1: use a single message for all action, and let the server decide if the action is move || kill || eaten

e.g: {TYPE: "MOVE" , SRC_POS: <POSITION> DEST_POS: <POSITION> }

option 2: use a dedicated message for each type of action

e.g: {TYPE: "MOVE" ....} , {TYPE: "KILL" ....} , {TYPE: "EATEN" ....}

I prefer option-2, since its eliminate so many if-else in server code, to figure out what kind of action is.

What is better, and which will cause failures/bugs in future ???

Typically, it won't matter what the contents of the message are when you need to handle where it goes. Usually, you might prefix the message with an identifier (type) that can be used to select the appropriate recipient. The contents are then managed by the requesting handler.

If you're using JSON, everything is serialised/deserialised in one go, so this is less explicit in practice, but you can still simply define the message to include a type field, and the rest is up to the sender.

That way, you check the type field and dispatch to the recipient as needed. Creating a generic message that does everything every message might need is both a waste of bandwidth and development time.

Advertisement

you mention:

If you're using JSON, everything is serialised/deserialised

Should I deserialize the received json into an object ??? e.g: { TYPE: 'MOVE' ...} => class MoveAction

currently I parse the received json and using String comparison to figure out what is the action.

What is more appropriate ??

Thx

In general, you want your code to be as table-driven and data-driven as possible. If you find yourself writing the same code multiple times, find a way to compress it into a table lookup or similar.

Thus, the creation of various Actions from string might look like:

class Action { /* abstract base class */ };
class MoveAction : public Action { /* concrete class */ };

class KillAction : public Action { /* concrete class */ };

class DieAction : public Action { /* concrete class */ };
 


struct NamedAction {
  char const *name;
  Action (*makeAction)(JSON *, Context *);
}
g_allActions[] = {
  { "move", &MakeMoveAction },
  { "kill", &MakeKillAction },
  { "die", &MakeDieAction },
};
 
Action *ActionFromJSON(JSON *json, Context *ctx) {
  char const *type = json->KeyAsString("type");
  if (!type) return nullptr;
  for (size_t i = 0; i != countof(g_allActions); ++i) {
    if (!strcmp(g_allActions[i].name, type)) {
      return (*g_allActions[i].makeAction)(json, ctx);
    }
  }
  return nullptr;
}

In a larger system, you'll likely use a hash table instead of a linear table scan, and each action kind will register itself in this table on start-up in some way.

enum Bool { True, False, FileNotFound };

First thank @hplus0603

I take your idea and Factory pattern and it fits exactly as I need.


public class ActionFactory {
	public static Action createAction(JSONObject object){
		
		try{
			String username = object.getString("USERNAME");			
			String type = object.getString("TYPE");
			String src= object.getString("SRC");
			String dest = object.getString("DEST");

			if(type == "MOVE"){
				return new ActionMove(username,src,dest);
			}
			else if(type == "KILL"){
				return new ActionKill(username,src,dest);
			}
			
			else if(type == "DIED"){
				return new ActionDied(username, src, dest);
			}
			else if(type == "TIE"){
				
			}
		}
		catch(JSONException e){
			e.printStackTrace();
		}
		
			
		return null;
		
	}
}

This topic is closed to new replies.

Advertisement