Skip to content

Instantly share code, notes, and snippets.

@yakreved
Created February 21, 2014 14:29
Show Gist options
  • Save yakreved/9135251 to your computer and use it in GitHub Desktop.
Save yakreved/9135251 to your computer and use it in GitHub Desktop.
SocketMessagesDispatcher
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System;
// В этот класс преобразуется JSON сообщения от сервера
public struct SocketMessage {
// Первый элемент массива - заголовок сообщения
// ["kill_combat", 1]
// name == "kill_combat"
public string name;
// Параметр сообщения, может быть разного типа, или null, если нет параметра
// ["wait", {"delay": 30}
// parametr == Dictionary { delay = 30 }
public object parameter;
// Мы подразумеваем что в сообщение максимум один параметр (имя + параметр)
public override string ToString()
{
return "[\""+name+"\","+JsonFx.Json.JsonWriter.Serialize(parameter)+"]";
}
}
// Данный клас принимает сообщения из сокета. Склеивает или расклеивает их на отдельные JSON-ки
// И запускает заданный контроллер для каждого типа сообщения
// Например можно задать такой роут:
// SocketMessageDispatcher.addRoute("login_successfull", delegate(param) { new LoginController().success() })
// Это значит, что когда придёт сообщение от сервера типа:
// ["login_successfull", "ok"]
// вызовется метод success контроллера LoginController
//
// У класса есть два статических метода main и combat, предназначенные соответвенно
// для обработки сообщений с мейн-сервера и комбат сервера
//
// Из-за огранчений юнити по работе с главным тредом, вместе с этим классом работает
public class SocketMessagesDispatcher {
private static SocketMessagesDispatcher _main;
private static SocketMessagesDispatcher _combat;
private string msgBuffer = String.Empty;
public delegate void RouteDelegate(object param);
private Dictionary<string, RouteDelegate> RouteDict = new Dictionary<string, RouteDelegate>();
// Инстанс для соединения с главным сервером приложения
public static SocketMessagesDispatcher main {
get {
if(_main == null) {
_main = new SocketMessagesDispatcher();
}
return _main;
}
}
// Инстанс для соединения с сервером боя
public static SocketMessagesDispatcher combat {
get {
if(_combat == null) {
_combat = new SocketMessagesDispatcher();
}
return _combat;
}
}
// Получаем сообщение от сервера, оно может быть не валидным JSON-ом, например частью сообщения, или сразу двумя сообщениями
public void receivedRawMessage(string msg) {
Dbg.Log(msg);
lock(this) {
Dbg.Log("Raw message receiver" + msg);
msg = msg.Replace("\0", "");
string completeMsg = msgBuffer + msg;
if(completeMsg[completeMsg.Length - 1] == '\n') {
msgBuffer = "";
}
else {
msgBuffer += msg;
return;
}
foreach(string queryString in completeMsg.Split('\n')) {
SocketMessage message = new SocketMessage();
try {
if(queryString == "") continue;
message = JsonParser.ParseJsonToSocketMessage(queryString);
}
catch(Exception ex){
Dbg.Log("Can't parse json message <<<" + queryString + ">>> " + ex);
continue;
}
SocketMessagesQueue.AddMessage(message, this);
}
}
}
// Добавляем обработчик сообещений. Можно в одну строку типа:
// SocketMessagesDispatcher.addRoute('some', delegate(p) { ... }).addRoute('another', delegate(p) { ... })
public SocketMessagesDispatcher addRoute(string messageName, RouteDelegate route){
RouteDict[messageName] = route;
return this;
}
public void Route(SocketMessage message) {
if(RouteDict.ContainsKey(message.name)) {
Dbg.Log("Run routing on " + message.name);
RouteDict[message.name](message);
}
else {
Dbg.Log("Can't route server message " + message.name);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment