Implementation of websockets in servatrice and test js client
226
webclient/index.html
Executable file
|
|
@ -0,0 +1,226 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Servatrice web client</title>
|
||||
<link rel="stylesheet" href="js/jquery-ui-1.11.4.css">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="loading">
|
||||
Loading servatrice web client...
|
||||
</div>
|
||||
|
||||
<div id="tabs" style="display:none">
|
||||
<ul>
|
||||
<li><a href="#tab-login">Login</a></li>
|
||||
<li><a href="#tab-server">Server</a></li>
|
||||
<li><a href="#tab-account">Account</a></li>
|
||||
</ul>
|
||||
|
||||
<div id="tab-login">
|
||||
<h3>Login to server</h3>
|
||||
<label for="host">Host</label>
|
||||
<input type="text" id="host" value="127.0.0.1" />
|
||||
<br/>
|
||||
<label for="port">Port</label>
|
||||
<input type="text" id="port" value ="4748" />
|
||||
<br/>
|
||||
<label for="user">Username</label>
|
||||
<input type="text" id="user" />
|
||||
<br/>
|
||||
<label for="pass">Password</label>
|
||||
<input type="password" id="pass" />
|
||||
<br/>
|
||||
<button id="loginnow">Connect</button>
|
||||
<button id="quit" style="display:none">Disconnect</button>
|
||||
<span id="status"></span>
|
||||
</div>
|
||||
|
||||
<div id="tab-server">
|
||||
<h3>Rooms</h3>
|
||||
<span id="roomslist"></span>
|
||||
<h3>Server messages</h3>
|
||||
<div id="servermessages"></div>
|
||||
</div>
|
||||
|
||||
<div id="tab-account">
|
||||
<h3>User info</h3>
|
||||
<span id="userinfo"></span>
|
||||
<h3>Buddies</h3>
|
||||
<select id="buddies" size="10"></select>
|
||||
<h3>Ignores</h3>
|
||||
<select id="ignores" size="10"></select>
|
||||
<h3>Missing features</h3>
|
||||
<span id="features"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="js/jquery-1.11.3.js"></script>
|
||||
<script src="js/jquery-ui-1.11.4.js"></script>
|
||||
<script src="js/long.js"></script>
|
||||
<script src="js/bytebuffer.js"></script>
|
||||
<script src="js/protobuf.js"></script>
|
||||
<script src="webclient.js"></script>
|
||||
|
||||
<script>
|
||||
$("#tabs").tabs();
|
||||
$("#tabs").tabs("disable").tabs("enable", "tab-login");
|
||||
$("#loading").hide();
|
||||
$("#tabs").show();
|
||||
|
||||
$( document ).ready(function() {
|
||||
|
||||
function ts2time(ts) {
|
||||
var d = new Date(Number(ts));
|
||||
return ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2) + ':' + ('0' + d.getSeconds()).slice(-2);
|
||||
}
|
||||
|
||||
function getTime() {
|
||||
var d = new Date();
|
||||
return ('0' + d.getHours()).slice(-2) + ':' + ('0' + d.getMinutes()).slice(-2) + ':' + ('0' + d.getSeconds()).slice(-2);
|
||||
}
|
||||
|
||||
function htmlEscape(msg) {
|
||||
return $("<div>").text(msg).html();
|
||||
}
|
||||
|
||||
$("#loginnow").click(connect);
|
||||
$("#host, #port, #user, #pass").keydown(function(e) {
|
||||
if (e.keyCode == 13) { connect(); }
|
||||
});
|
||||
|
||||
function connect() {
|
||||
var host = $("#host").val();
|
||||
var port = $("#port").val();
|
||||
if(!host.length || !port.length)
|
||||
{
|
||||
alert('Please enter a valid host and port.');
|
||||
return;
|
||||
}
|
||||
|
||||
var options = {
|
||||
"debug": true,
|
||||
"autojoinrooms" : true,
|
||||
"host": host,
|
||||
"port": port,
|
||||
"user": $("#user").val(),
|
||||
"pass": $("#pass").val(),
|
||||
"statusCallback" : function(id, desc) {
|
||||
$("#status").text(desc);
|
||||
if(id == StatusEnum.LOGGEDIN)
|
||||
{
|
||||
$("#tabs").tabs("enable").tabs("option", "active", 1);
|
||||
$("#loginnow").hide();
|
||||
$("#quit").show();
|
||||
} else {
|
||||
$("#tabs").tabs("disable").tabs("enable", "tab-login").tabs("option", "active", 0);
|
||||
$("#quit").hide();
|
||||
$("#loginnow").show().prop("disabled", false);
|
||||
// close rooms
|
||||
$(".room-header, .room-div").remove();
|
||||
|
||||
}
|
||||
},
|
||||
"connectionClosedCallback" : function(id, desc) {
|
||||
$("#status").text('Connection closed: ' + desc);
|
||||
$("#tabs").tabs("disable").tabs("enable", "tab-login").tabs("option", "active", 0);
|
||||
$("#quit").hide();
|
||||
$("#loginnow").show().prop("disabled", false);
|
||||
// close rooms
|
||||
$(".room-header, .room-div").remove();
|
||||
},
|
||||
"serverMessageCallback" : function(message) {
|
||||
$("#servermessages").append(htmlEscape(message) + '<br/>');
|
||||
},
|
||||
"userInfoCallback" : function(data) {
|
||||
$("#userinfo").empty();
|
||||
$.each(data.userInfo, function(key, value) {
|
||||
// filter out inherited properties
|
||||
if (data.userInfo.hasOwnProperty(key))
|
||||
$('#userinfo').append(key + ': ' + value + '<br/>');
|
||||
});
|
||||
|
||||
$('#buddies').empty();
|
||||
$.each(data.buddyList, function(key, value) {
|
||||
$('#buddies').append('<option>' + value.name + '</option>');
|
||||
});
|
||||
|
||||
$('#ignores').empty();
|
||||
$.each(data.ignoreList, function(key, value) {
|
||||
$('#ignores').append('<option>' + value.name + '</option>');
|
||||
});
|
||||
|
||||
$("#features").text(JSON.stringify(data.missingFeatures, null, 4));
|
||||
},
|
||||
"listRoomsCallback" : function(rooms) {
|
||||
$("#roomslist").text(JSON.stringify(rooms, null, 4));
|
||||
},
|
||||
"errorCallback" : function(id, desc) {
|
||||
$("#roomslist").text(desc);
|
||||
},
|
||||
"joinRoomCallback" : function(room) {
|
||||
$("div#tabs ul").append(
|
||||
"<li class='room-header'><a href='#tab-room-" + room["roomId"] + "'>" + room["name"] + "</a></li>"
|
||||
);
|
||||
$("div#tabs").append(
|
||||
"<div class='room-div' id='tab-room-" + room["roomId"] + "'>" + room["name"] +
|
||||
"<h3>Userlist</h3>" +
|
||||
"<select class=\"userlist\" size=\"10\"></select>" +
|
||||
"<h3>Chat</h3>" +
|
||||
"<div class=\"output\"></div>" +
|
||||
"<br/><input type=\"text\" class=\"input\" />" +
|
||||
"<button class=\"say\">say</button>" +
|
||||
"</div>"
|
||||
);
|
||||
$("div#tabs").tabs("refresh");
|
||||
|
||||
$("#tab-room-" + room["roomId"] + " .userlist").empty();
|
||||
$.each(room["userList"], function(key, value) {
|
||||
$("#tab-room-" + room["roomId"] + " .userlist").append('<option>' + value.name + '</option>');
|
||||
});
|
||||
|
||||
$("#tab-room-" + room["roomId"] + " .say").click(function() {
|
||||
var msg = $("#tab-room-" + room["roomId"] + " .input").val();
|
||||
$("#tab-room-" + room["roomId"] + " .input").val("");
|
||||
WebClient.roomSay(room["roomId"], msg);
|
||||
});
|
||||
$("#tab-room-" + room["roomId"] + " .input").keydown(function(e) {
|
||||
if (e.keyCode == 13) {
|
||||
var msg = $("#tab-room-" + room["roomId"] + " .input").val();
|
||||
$("#tab-room-" + room["roomId"] + " .input").val("");
|
||||
WebClient.roomSay(room["roomId"], msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
"roomMessageCallback" : function(roomId, message) {
|
||||
var text;
|
||||
switch(message["messageType"])
|
||||
{
|
||||
case WebClient.pb.Event_RoomSay.RoomMessageType.Welcome:
|
||||
text = "<span class='serverwelcome'>" + htmlEscape(message["message"]) + "</span>";
|
||||
break;
|
||||
case WebClient.pb.Event_RoomSay.RoomMessageType.ChatHistory:
|
||||
text = "<span class='chathistory'>[" + ts2time(message["timeOf"]) + "] " + htmlEscape(message["message"]) + "</span>";
|
||||
break;
|
||||
default:
|
||||
text = "[" + getTime() + "] " + htmlEscape(message["name"]) + ": " + htmlEscape(message["message"]);
|
||||
break;
|
||||
}
|
||||
$("#tab-room-" + roomId + " .output").append(text + '<br/>');
|
||||
},
|
||||
};
|
||||
|
||||
$(this).prop("disabled", true);
|
||||
WebClient.connect(options);
|
||||
};
|
||||
|
||||
$("#quit").click(function() {
|
||||
WebClient.disconnect();
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
3651
webclient/js/bytebuffer.js
Executable file
BIN
webclient/js/images/ui-bg_diagonals-thick_18_b81900_40x40.png
Normal file
|
After Width: | Height: | Size: 418 B |
BIN
webclient/js/images/ui-bg_diagonals-thick_20_666666_40x40.png
Normal file
|
After Width: | Height: | Size: 312 B |
BIN
webclient/js/images/ui-bg_flat_10_000000_40x100.png
Normal file
|
After Width: | Height: | Size: 205 B |
BIN
webclient/js/images/ui-bg_glass_100_f6f6f6_1x400.png
Normal file
|
After Width: | Height: | Size: 262 B |
BIN
webclient/js/images/ui-bg_glass_100_fdf5ce_1x400.png
Normal file
|
After Width: | Height: | Size: 348 B |
BIN
webclient/js/images/ui-bg_glass_65_ffffff_1x400.png
Normal file
|
After Width: | Height: | Size: 207 B |
BIN
webclient/js/images/ui-bg_gloss-wave_35_f6a828_500x100.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
webclient/js/images/ui-bg_highlight-soft_100_eeeeee_1x100.png
Normal file
|
After Width: | Height: | Size: 278 B |
BIN
webclient/js/images/ui-bg_highlight-soft_75_ffe45c_1x100.png
Normal file
|
After Width: | Height: | Size: 328 B |
BIN
webclient/js/images/ui-icons_222222_256x240.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
webclient/js/images/ui-icons_228ef1_256x240.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
webclient/js/images/ui-icons_ef8c08_256x240.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
webclient/js/images/ui-icons_ffd27a_256x240.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
webclient/js/images/ui-icons_ffffff_256x240.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
10351
webclient/js/jquery-1.11.3.js
vendored
Executable file
1225
webclient/js/jquery-ui-1.11.4.css
vendored
Normal file
16617
webclient/js/jquery-ui-1.11.4.js
vendored
Normal file
1220
webclient/js/long.js
Executable file
5211
webclient/js/protobuf.js
Executable file
1
webclient/pb
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../common/pb
|
||||
54
webclient/style.css
Executable file
|
|
@ -0,0 +1,54 @@
|
|||
p {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#tab-login {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#tab-login label {
|
||||
display: block;
|
||||
width: 100px;
|
||||
float: left;
|
||||
padding-right: 10px;
|
||||
clear:left;
|
||||
}
|
||||
|
||||
#tab-login input {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#loading {
|
||||
font-size: 200%;
|
||||
text-align:center;
|
||||
margin-top:200px;
|
||||
}
|
||||
|
||||
.output, #servermessages {
|
||||
width:100%;
|
||||
min-height: 400px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
word-wrap: break-word;
|
||||
word-break:break-all;
|
||||
background-color: #fff;
|
||||
box-shadow: inset 1px 1px 3px #999;
|
||||
padding: .5em;
|
||||
}
|
||||
|
||||
.input {
|
||||
width:95%;
|
||||
}
|
||||
|
||||
.serverwelcome {
|
||||
color: #006600;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.chathistory {
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#buddies, #ignores, .userlist {
|
||||
width: 20em;
|
||||
}
|
||||
424
webclient/webclient.js
Executable file
|
|
@ -0,0 +1,424 @@
|
|||
var StatusEnum = {
|
||||
DISCONNECTED : 0,
|
||||
CONNECTING : 1,
|
||||
CONNECTED : 2,
|
||||
LOGGINGIN : 3,
|
||||
LOGGEDIN : 4,
|
||||
DISCONNECTING : 99
|
||||
};
|
||||
|
||||
var WebClient = {
|
||||
status : StatusEnum.DISCONNECTED,
|
||||
socket : 0,
|
||||
keepalivecb: null,
|
||||
lastPingPending: false,
|
||||
cmdId : 0,
|
||||
initialized: false,
|
||||
pendingCommands : {},
|
||||
options : {
|
||||
host: "",
|
||||
port: "",
|
||||
user: "",
|
||||
pass: "",
|
||||
debug: false,
|
||||
autojoinrooms: false,
|
||||
keepalive: 5000
|
||||
},
|
||||
|
||||
protobuf : null,
|
||||
builder : null,
|
||||
pb : null,
|
||||
pbfiles : [
|
||||
// commands
|
||||
"pb/commands.proto",
|
||||
"pb/session_commands.proto",
|
||||
"pb/room_commands.proto",
|
||||
// replies
|
||||
"pb/server_message.proto",
|
||||
"pb/response.proto",
|
||||
"pb/response_login.proto",
|
||||
"pb/session_event.proto",
|
||||
"pb/event_server_message.proto",
|
||||
"pb/event_connection_closed.proto",
|
||||
"pb/event_list_rooms.proto",
|
||||
"pb/response_join_room.proto",
|
||||
"pb/room_event.proto",
|
||||
"pb/event_room_say.proto"
|
||||
],
|
||||
|
||||
initialize : function()
|
||||
{
|
||||
this.protobuf = dcodeIO.ProtoBuf;
|
||||
this.builder = this.protobuf.newBuilder({ convertFieldsToCamelCase: true });
|
||||
|
||||
$.each(this.pbfiles, function(index, fileName) {
|
||||
WebClient.protobuf.loadProtoFile(fileName, WebClient.builder);
|
||||
});
|
||||
|
||||
this.pb = this.builder.build();
|
||||
|
||||
this.initialized=true;
|
||||
},
|
||||
|
||||
guid : function(options)
|
||||
{
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
||||
},
|
||||
|
||||
setStatus : function(status, desc)
|
||||
{
|
||||
this.status = status;
|
||||
if(this.options.debug)
|
||||
console.log("Stats change:", status, desc)
|
||||
if(this.options.statusCallback)
|
||||
this.options.statusCallback(status, desc);
|
||||
},
|
||||
|
||||
resetConnectionvars : function () {
|
||||
this.cmdId = 0;
|
||||
this.pendingCommands = {};
|
||||
},
|
||||
|
||||
sendCommand : function (cmd, callback)
|
||||
{
|
||||
this.cmdId++;
|
||||
cmd["cmdId"] = this.cmdId;
|
||||
this.pendingCommands[this.cmdId] = callback;
|
||||
|
||||
if (this.socket.readyState == WebSocket.OPEN) {
|
||||
this.socket.send(cmd.toArrayBuffer());
|
||||
if(this.options.debug)
|
||||
console.log("Sent: " + cmd.toString());
|
||||
} else {
|
||||
if(this.options.debug)
|
||||
console.log("Send: Not connected");
|
||||
}
|
||||
},
|
||||
|
||||
sendRoomCommand : function(roomId, roomCmd, callback)
|
||||
{
|
||||
var cmd = new WebClient.pb.CommandContainer({
|
||||
"roomId" : roomId,
|
||||
"roomCommand" : [ roomCmd ]
|
||||
});
|
||||
WebClient.sendCommand(cmd, callback);
|
||||
},
|
||||
|
||||
sendSessionCommand : function(ses, callback)
|
||||
{
|
||||
var cmd = new WebClient.pb.CommandContainer({
|
||||
"sessionCommand" : [ ses ]
|
||||
});
|
||||
WebClient.sendCommand(cmd, callback);
|
||||
},
|
||||
|
||||
startPingLoop : function()
|
||||
{
|
||||
keepalivecb = setInterval(function() {
|
||||
// check if the previous ping got no reply
|
||||
if(WebClient.lastPingPending)
|
||||
{
|
||||
WebClient.socket.close();
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTED, 'Connection timeout');
|
||||
}
|
||||
|
||||
// stop the ping loop if we're disconnected
|
||||
if(WebClient.status != StatusEnum.LOGGEDIN)
|
||||
{
|
||||
clearInterval(keepalivecb);
|
||||
keepalivecb = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// send a ping
|
||||
var CmdPing = new WebClient.pb.Command_Ping();
|
||||
|
||||
var sc = new WebClient.pb.SessionCommand({
|
||||
".Command_Ping.ext" : CmdPing
|
||||
});
|
||||
|
||||
WebClient.lastPingPending = true;
|
||||
WebClient.sendSessionCommand(sc, function() {
|
||||
WebClient.lastPingPending = false;
|
||||
});
|
||||
|
||||
}, WebClient.options.keepalive);
|
||||
},
|
||||
|
||||
doLogin : function()
|
||||
{
|
||||
var CmdLogin = new WebClient.pb.Command_Login({
|
||||
"userName" : this.options.user,
|
||||
"password" : this.options.pass,
|
||||
"clientid" : this.guid(),
|
||||
"clientver" : "webclient-0.1 (2015-12-23)",
|
||||
"clientfeatures" : [ "client_id", "client_ver"],
|
||||
});
|
||||
|
||||
var sc = new WebClient.pb.SessionCommand({
|
||||
".Command_Login.ext" : CmdLogin
|
||||
});
|
||||
|
||||
this.sendSessionCommand(sc, function(raw) {
|
||||
var resp = raw[".Response_Login.ext"];
|
||||
switch(raw.responseCode)
|
||||
{
|
||||
case WebClient.pb.Response.ResponseCode.RespOk:
|
||||
WebClient.setStatus(StatusEnum.LOGGEDIN, 'Logged in.');
|
||||
|
||||
if(WebClient.options.userInfoCallback)
|
||||
WebClient.options.userInfoCallback(resp);
|
||||
|
||||
WebClient.startPingLoop();
|
||||
WebClient.doListRooms();
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespClientUpdateRequired:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: missing features');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespWrongPassword:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: incorrect username or password');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespWouldOverwriteOldSession:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: duplicated user session');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespUserIsBanned:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: banned user');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespUsernameInvalid:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: invalid username');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespRegistrationRequired:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: registration required');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespClientIdRequired:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: missing client ID');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespContextError:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: server error');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespAccountNotActivated:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: account not activated');
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespClientUpdateRequired:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: missing features');
|
||||
break;
|
||||
default:
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTING, 'Login failed: unknown error ' + raw.responseCode);
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
doListRooms : function()
|
||||
{
|
||||
var CmdListRooms = new WebClient.pb.Command_ListRooms();
|
||||
|
||||
var sc = new WebClient.pb.SessionCommand({
|
||||
".Command_ListRooms.ext" : CmdListRooms
|
||||
});
|
||||
|
||||
this.sendSessionCommand(sc, function(raw) {
|
||||
// Command_ListRooms 's response will be received inside a sessionEvent
|
||||
});
|
||||
},
|
||||
|
||||
processSessionEvent : function (raw)
|
||||
{
|
||||
if(raw[".Event_ConnectionClosed.ext"]) {
|
||||
var message = '';
|
||||
switch(raw[".Event_ConnectionClosed.ext"]["reason"])
|
||||
{
|
||||
case WebClient.pb.Event_ConnectionClosed.CloseReason.USER_LIMIT_REACHED:
|
||||
message = 'The server has reached its maximum user capacity';
|
||||
break;
|
||||
case WebClient.pb.Event_ConnectionClosed.CloseReason.TOO_MANY_CONNECTIONS:
|
||||
message = 'There are too many concurrent connections from your address';
|
||||
break;
|
||||
case WebClient.pb.Event_ConnectionClosed.CloseReason.BANNED:
|
||||
message = 'You are banned';
|
||||
break;
|
||||
case WebClient.pb.Event_ConnectionClosed.CloseReason.SERVER_SHUTDOWN:
|
||||
message = 'Scheduled server shutdown';
|
||||
break;
|
||||
case WebClient.pb.Event_ConnectionClosed.CloseReason.USERNAMEINVALID:
|
||||
message = 'Invalid username';
|
||||
break;
|
||||
case WebClient.pb.Event_ConnectionClosed.CloseReason.LOGGEDINELSEWERE:
|
||||
message = 'You have been logged out due to logging in at another location';
|
||||
break;
|
||||
case WebClient.pb.Event_ConnectionClosed.CloseReason.OTHER:
|
||||
default:
|
||||
message = 'Unknown reason';
|
||||
break;
|
||||
}
|
||||
|
||||
if(this.options.connectionClosedCallback)
|
||||
this.options.connectionClosedCallback(raw[".Event_ConnectionClosed.ext"]["reason"], message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(raw[".Event_ServerMessage.ext"]) {
|
||||
if(this.options.serverMessageCallback)
|
||||
this.options.serverMessageCallback(raw[".Event_ServerMessage.ext"]["message"]);
|
||||
return;
|
||||
}
|
||||
|
||||
if(raw[".Event_ListRooms.ext"]) {
|
||||
var roomsList = raw[".Event_ListRooms.ext"]["roomList"];
|
||||
if(this.options.listRoomsCallback)
|
||||
this.options.listRoomsCallback(roomsList);
|
||||
if(this.options.autojoinrooms)
|
||||
{
|
||||
$.each(roomsList, function(index, room) {
|
||||
if(room.autoJoin)
|
||||
{
|
||||
var CmdJoinRoom = new WebClient.pb.Command_JoinRoom({
|
||||
"roomId" : room.roomId
|
||||
});
|
||||
|
||||
var sc = new WebClient.pb.SessionCommand({
|
||||
".Command_JoinRoom.ext" : CmdJoinRoom
|
||||
});
|
||||
|
||||
WebClient.sendSessionCommand(sc, WebClient.processJoinRoom);
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
processRoomEvent : function (raw)
|
||||
{
|
||||
if(raw[".Event_RoomSay.ext"]) {
|
||||
if(this.options.roomMessageCallback)
|
||||
this.options.roomMessageCallback(raw["roomId"], raw[".Event_RoomSay.ext"]);
|
||||
return;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
processJoinRoom : function(raw)
|
||||
{
|
||||
switch(raw["responseCode"])
|
||||
{
|
||||
case WebClient.pb.Response.ResponseCode.RespOk:
|
||||
var roomInfo = raw[".Response_JoinRoom.ext"]["roomInfo"];
|
||||
if(WebClient.options.joinRoomCallback)
|
||||
WebClient.options.joinRoomCallback(roomInfo);
|
||||
break;
|
||||
case WebClient.pb.Response.ResponseCode.RespNameNotFound:
|
||||
if(WebClient.options.errorCallback) WebClient.options.errorCallback(raw["responseCode"], "Failed to join the room: it doesn't exists on the server.");
|
||||
return;
|
||||
case WebClient.pb.Response.ResponseCode.RespContextError:
|
||||
if(WebClient.options.errorCallback) WebClient.options.errorCallback(raw["responseCode"], "The server thinks you are in the room but Cockatrice is unable to display it. Try restarting Cockatrice.");
|
||||
return;
|
||||
case WebClient.pb.Response.ResponseCode.RespUserLevelTooLow:
|
||||
if(WebClient.options.errorCallback) WebClient.options.errorCallback(raw["responseCode"], "You do not have the required permission to join this room.");
|
||||
return;
|
||||
default:
|
||||
if(WebClient.options.errorCallback) WebClient.options.errorCallback(raw["responseCode"], "Failed to join the room due to an unknown error: " + raw["responseCode"]);
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
connect : function(options) {
|
||||
jQuery.extend(this.options, options || {});
|
||||
|
||||
if(!this.initialized)
|
||||
this.initialize();
|
||||
|
||||
this.socket = new WebSocket('ws://' + this.options.host + ':' + this.options.port);
|
||||
this.socket.binaryType = "arraybuffer"; // We are talking binary
|
||||
this.setStatus(StatusEnum.CONNECTING, 'Connecting...');
|
||||
|
||||
this.socket.onclose = function() {
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTED, 'Connection closed');
|
||||
}
|
||||
|
||||
this.socket.onerror = function() {
|
||||
WebClient.setStatus(StatusEnum.DISCONNECTED, 'Connection failed');
|
||||
}
|
||||
|
||||
this.socket.onopen = function(){
|
||||
WebClient.setStatus(StatusEnum.CONNECTED, 'Connected, logging in...');
|
||||
WebClient.resetConnectionvars();
|
||||
WebClient.doLogin();
|
||||
}
|
||||
|
||||
this.socket.onmessage = function(event) {
|
||||
//console.log("Received " + event.data.byteLength + " bytes");
|
||||
|
||||
try {
|
||||
var msg = WebClient.pb.ServerMessage.decode(event.data);
|
||||
if(WebClient.options.debug)
|
||||
console.log(msg);
|
||||
} catch (err) {
|
||||
console.log("Processing failed:", err);
|
||||
if(WebClient.options.debug)
|
||||
{
|
||||
var view = new Uint8Array(event.data);
|
||||
var str = "";
|
||||
for(var i = 0; i < view.length; i++)
|
||||
{
|
||||
str += String.fromCharCode(view[i]);
|
||||
}
|
||||
console.log(str);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.messageType) {
|
||||
case WebClient.pb.ServerMessage.MessageType.RESPONSE:
|
||||
var response = msg.response;
|
||||
var cmdId = response.cmdId;
|
||||
|
||||
if(!WebClient.pendingCommands.hasOwnProperty(cmdId))
|
||||
return;
|
||||
WebClient.pendingCommands[cmdId](response);
|
||||
delete WebClient.pendingCommands[cmdId];
|
||||
break;
|
||||
case WebClient.pb.ServerMessage.MessageType.SESSION_EVENT:
|
||||
WebClient.processSessionEvent(msg.sessionEvent);
|
||||
break;
|
||||
case WebClient.pb.ServerMessage.MessageType.GAME_EVENT_CONTAINER:
|
||||
// TODO
|
||||
break;
|
||||
case WebClient.pb.ServerMessage.MessageType.ROOM_EVENT:
|
||||
WebClient.processRoomEvent(msg.roomEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
disconnect : function() {
|
||||
this.socket.close();
|
||||
},
|
||||
|
||||
roomSay : function(roomId, msg) {
|
||||
var CmdRoomSay = new WebClient.pb.Command_RoomSay({
|
||||
"message" : msg
|
||||
});
|
||||
|
||||
var sc = new WebClient.pb.RoomCommand({
|
||||
".Command_RoomSay.ext" : CmdRoomSay
|
||||
});
|
||||
|
||||
WebClient.sendRoomCommand(roomId, sc, function(raw) {
|
||||
switch(raw["responseCode"])
|
||||
{
|
||||
case WebClient.pb.Response.ResponseCode.RespChatFlood:
|
||||
console.log("room flood " + roomId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||