Задумал я тут выложить на Github свою очередную поделку — простой сервер на Node.js и клиента к нему на Unity. Много раз сам гуглил различные библиотеки, пробовал, тестировал, пытался сам написать что-то (с моими познаниями в Node.js :), но потом подсмотрел как сделано у старого китайского Pomelo, который уже сто лет не поддерживается.
Если честно, когда я первый раз узнал про Pomelo и начал его изучать, то понял, что для моих текущих задач такой функциональности не требуется, поэтому решил выпилить всё что не нужно. В итоге, осталось вот что:
Опыта в Node.js у меня не очень много, поэтому я нагуглил такой фреймворк — Architect. Не знаю насколько это оправдано, но пока сделано с помощью него.
- многопользовательский сервер для нереалтаймовых игр
- отправка и получение команд и запросов (аналог JSON RPC)
- поддержка SSL
- основная часть на Architect
- простое добавление команд: один файл = одна команда
- работает с MongoDB
Команды (события)
public void TestCommand () {
JsonObject param = new JsonObject();
param["param"] = "value";
_connector.Command("test-cmd", param);
// _connector.Command("test-cmd"); // without params
}
Чтобы «слушать» команды с сервера надо подписаться на команду (событие):
public void TestCommand () {
_connector.On("test-cmd", OnTestCmd);
// _connector.Off("test-cmd", OnTestCmd); // unsubscribe
}
void OnTestCmd (JsonObject result) {
if (_connector.IsError (result)) {
// handle error
return;
}
// handle result
}
Запросы (RPC)
public void TestRequest () {
JsonObject param = new JsonObject();
param["param"] = "value";
_connector.Request ("test-rqt", param, (result) => {
// handle answer
});
// _connector.Request ("test-rqt", OnTestRequest); // without params
// _connector.Request ("test-rqt", param, OnTestRequest); // callback in external method
}
void OnTestRequest (JsonObject result) {
if (_connector.IsError (result)) {
// handle error
return;
}
// handle result
}
На RPC запросы с сервера можно подписаться также как и на обычные команды. Отличие в том, на них надо обязательно «отвечать».
На сервере каждая команда находится в отдельном файле и экспортируется, как-то так:
module.exports = function (commander, message, imports) {
if (!validate(message.data, commander.protocol.log)) {
commander.sendError(message, "invalid_data");
return;
}
...
commander.sendResponse(message, { result: "ok" });
};
Протокол сообщений можно легко переделать, добавить шифрование или свой какой-то формат, можно посмотреть в репе Pomelo, у меня будет также примерно.
Для создания простой многопользовательской онлайн игры — этого достаточно. Это будет такая демка, когда можно взять сервер и клиент, запустить и сразу увидеть как оно работает. Код будет полностью доступен, так что умеющие в Node.js и C#, смогут переписать мои «костыли» на свои :)
После тестирования и «боевой» проверки на игре, если всё получится, думаю сделать небольшой курс, где опишу, как на основе такой базы делать несложные онлайн игры. Но замечу ещё раз — НЕ реалтайм!
Stay tuned.