2012-02-06 22:00:24 +00:00
|
|
|
/*
|
Add ID codes for positive user identification, and minor fixups.
Users can specify an identification code when they connect (8-100 characters), only if they are using HTTPS. This code is combined with their nickname and a server-side secret, hashed with SHA-256, and condensed down to 64 bits by XORing every 8th byte with each other, and finally converted to base64 (with the trailing = removed). This code is displayed in a tooltip when hovering over the user's chat (TODO: mobile way to view it).
Sigils have been added to be displayed before the user's name in the chat. Admins get @, users with an ID code get +, and normal users get nothing. The IS_ADMIN field is now deprecated, as this can be determined from the user's sigil. It will be removed eventually, but is still being included in events even though the official client should not be using it anymore.
Kicks and bans are now always displayed to all users, even if the server isn't transmitting quit events normally.
2018-03-03 01:24:58 +00:00
|
|
|
* Copyright (c) 2012-2018, Andy Janata All rights reserved.
|
2012-02-02 22:47:23 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
|
|
|
* provided that the following conditions are met:
|
2012-02-06 22:00:24 +00:00
|
|
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions
|
|
|
|
* and the following disclaimer. * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the documentation and/or other
|
|
|
|
* materials provided with the distribution.
|
2012-02-02 22:47:23 +00:00
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
|
|
|
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2011-12-25 03:37:45 +00:00
|
|
|
/**
|
|
|
|
* Event handlers from long-poll operations.
|
|
|
|
*
|
2012-02-06 22:00:24 +00:00
|
|
|
* TODO possibly split this into multiple files.
|
|
|
|
*
|
|
|
|
* @author Andy Janata (ajanata@socialgamer.net)
|
2011-12-25 03:37:45 +00:00
|
|
|
*/
|
|
|
|
|
2012-03-13 04:05:43 +00:00
|
|
|
cah.longpoll.ErrorCodeHandlers[cah.$.ErrorCode.NOT_REGISTERED] = function(data) {
|
2011-12-25 03:37:45 +00:00
|
|
|
cah.longpoll.Resume = false;
|
|
|
|
cah.log.error("The server seems to have restarted. Any in-progress games have been lost.");
|
|
|
|
cah.log.error("You will need to refresh the page to start a new game.");
|
2012-01-19 08:34:55 +00:00
|
|
|
$("input").attr("disabled", "disabled");
|
2011-12-25 03:37:45 +00:00
|
|
|
};
|
|
|
|
|
2012-01-13 05:36:31 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.NEW_PLAYER] = function(data) {
|
2012-01-12 21:07:19 +00:00
|
|
|
// don't display our own join
|
2012-10-12 05:18:40 +01:00
|
|
|
if (data[cah.$.LongPollResponse.NICKNAME] != cah.nickname && !cah.hideConnectQuit) {
|
2012-03-13 04:05:43 +00:00
|
|
|
cah.log.status(data[cah.$.LongPollResponse.NICKNAME] + " has connected.");
|
2012-01-12 21:07:19 +00:00
|
|
|
}
|
2011-12-25 03:37:45 +00:00
|
|
|
};
|
|
|
|
|
2013-12-02 04:00:57 +00:00
|
|
|
// TODO Not sure why this isn't done with localizable strings in constants.
|
2012-01-13 05:36:31 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.PLAYER_LEAVE] = function(data) {
|
2012-01-06 23:53:04 +00:00
|
|
|
var friendly_reason = "Leaving";
|
2012-10-12 05:18:40 +01:00
|
|
|
var show = !cah.hideConnectQuit;
|
2012-03-13 04:05:43 +00:00
|
|
|
switch (data[cah.$.LongPollResponse.REASON]) {
|
2012-08-21 06:41:06 +01:00
|
|
|
case cah.$.DisconnectReason.BANNED:
|
|
|
|
friendly_reason = "Banned";
|
2012-10-12 05:18:40 +01:00
|
|
|
show = true;
|
2012-08-21 06:41:06 +01:00
|
|
|
break;
|
2013-12-02 04:00:57 +00:00
|
|
|
case cah.$.DisconnectReason.IDLE_TIMEOUT:
|
|
|
|
friendly_reason = "Kicked due to idle";
|
|
|
|
break;
|
2012-01-13 04:05:39 +00:00
|
|
|
case cah.$.DisconnectReason.KICKED:
|
2012-08-21 06:41:06 +01:00
|
|
|
friendly_reason = "Kicked by server administrator";
|
2012-10-12 05:18:40 +01:00
|
|
|
show = true;
|
2012-01-13 04:05:39 +00:00
|
|
|
break;
|
|
|
|
case cah.$.DisconnectReason.MANUAL:
|
2012-01-06 23:53:04 +00:00
|
|
|
friendly_reason = "Leaving";
|
|
|
|
break;
|
2012-01-13 04:05:39 +00:00
|
|
|
case cah.$.DisconnectReason.PING_TIMEOUT:
|
2012-01-06 23:53:04 +00:00
|
|
|
friendly_reason = "Ping timeout";
|
|
|
|
break;
|
|
|
|
}
|
2012-10-12 05:18:40 +01:00
|
|
|
if (show) {
|
|
|
|
cah.log.status(data[cah.$.LongPollResponse.NICKNAME] + " has disconnected (" + friendly_reason
|
|
|
|
+ ").");
|
|
|
|
}
|
2012-01-06 23:53:04 +00:00
|
|
|
};
|
|
|
|
|
2012-01-13 05:36:31 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.NOOP] = function(data) {
|
2011-12-25 03:37:45 +00:00
|
|
|
// pass
|
|
|
|
};
|
|
|
|
|
2012-01-31 07:52:45 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.KICKED] = function() {
|
|
|
|
cah.log.status("You have been kicked by the server administrator.");
|
|
|
|
cah.longpoll.Resume = false;
|
|
|
|
$("input").attr("disabled", "disabled");
|
|
|
|
$("#menubar_left").empty();
|
|
|
|
$("#main").empty();
|
|
|
|
$("#info_area").empty();
|
|
|
|
};
|
|
|
|
|
2012-08-21 06:41:06 +01:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.BANNED] = function() {
|
|
|
|
cah.log.status("You have been banned by the server administrator.");
|
|
|
|
cah.longpoll.Resume = false;
|
|
|
|
$("input").attr("disabled", "disabled");
|
|
|
|
$("#menubar_left").empty();
|
|
|
|
$("#main").empty();
|
|
|
|
$("#info_area").empty();
|
|
|
|
};
|
|
|
|
|
2012-01-13 05:36:31 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.CHAT] = function(data) {
|
2018-03-28 01:59:31 +01:00
|
|
|
cah.longpoll.showChat_(data, false);
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.FILTERED_CHAT] = function(data) {
|
|
|
|
cah.longpoll.showChat_(data, true);
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.showChat_ = function(data, wasFiltered) {
|
2012-08-21 04:03:52 +01:00
|
|
|
var clazz = undefined;
|
Add ID codes for positive user identification, and minor fixups.
Users can specify an identification code when they connect (8-100 characters), only if they are using HTTPS. This code is combined with their nickname and a server-side secret, hashed with SHA-256, and condensed down to 64 bits by XORing every 8th byte with each other, and finally converted to base64 (with the trailing = removed). This code is displayed in a tooltip when hovering over the user's chat (TODO: mobile way to view it).
Sigils have been added to be displayed before the user's name in the chat. Admins get @, users with an ID code get +, and normal users get nothing. The IS_ADMIN field is now deprecated, as this can be determined from the user's sigil. It will be removed eventually, but is still being included in events even though the official client should not be using it anymore.
Kicks and bans are now always displayed to all users, even if the server isn't transmitting quit events normally.
2018-03-03 01:24:58 +00:00
|
|
|
var idcode = data[cah.$.LongPollResponse.ID_CODE];
|
|
|
|
var title = cah.log.getTitleForIdCode(idcode);
|
|
|
|
var sigil = data[cah.$.LongPollResponse.SIGIL];
|
2012-10-12 05:18:40 +01:00
|
|
|
var from = data[cah.$.LongPollResponse.FROM];
|
2018-03-28 01:59:31 +01:00
|
|
|
var who = sigil + from;
|
2012-10-12 05:18:40 +01:00
|
|
|
var show = !cah.ignoreList[from];
|
2018-03-28 01:59:31 +01:00
|
|
|
var message = data[cah.$.LongPollResponse.MESSAGE];
|
2013-02-24 01:19:53 +00:00
|
|
|
var game = null;
|
Add ID codes for positive user identification, and minor fixups.
Users can specify an identification code when they connect (8-100 characters), only if they are using HTTPS. This code is combined with their nickname and a server-side secret, hashed with SHA-256, and condensed down to 64 bits by XORing every 8th byte with each other, and finally converted to base64 (with the trailing = removed). This code is displayed in a tooltip when hovering over the user's chat (TODO: mobile way to view it).
Sigils have been added to be displayed before the user's name in the chat. Admins get @, users with an ID code get +, and normal users get nothing. The IS_ADMIN field is now deprecated, as this can be determined from the user's sigil. It will be removed eventually, but is still being included in events even though the official client should not be using it anymore.
Kicks and bans are now always displayed to all users, even if the server isn't transmitting quit events normally.
2018-03-03 01:24:58 +00:00
|
|
|
if (sigil == cah.$.Sigil.ADMIN) {
|
2012-08-21 04:03:52 +01:00
|
|
|
clazz = "admin";
|
2012-10-12 05:18:40 +01:00
|
|
|
show = true;
|
2012-08-21 04:03:52 +01:00
|
|
|
}
|
2013-03-27 03:17:49 +00:00
|
|
|
if (data[cah.$.LongPollResponse.WALL]) {
|
|
|
|
// treat these specially
|
2018-03-28 01:59:31 +01:00
|
|
|
cah.log.everyWindow("Global message from " + who + ": " + message, clazz, false, title);
|
2013-03-27 03:17:49 +00:00
|
|
|
} else {
|
|
|
|
if (cah.$.LongPollResponse.GAME_ID in data) {
|
|
|
|
game = data[cah.$.LongPollResponse.GAME_ID];
|
|
|
|
}
|
2018-03-28 01:59:31 +01:00
|
|
|
if (wasFiltered) {
|
|
|
|
clazz = "error";
|
|
|
|
show = true;
|
|
|
|
// there might be a game id that we're not in
|
|
|
|
if (cah.$.LongPollResponse.GAME_ID in data) {
|
|
|
|
message = "(In game " + game + ") " + message;
|
|
|
|
// always show this in global chat since we're probably not in that game.
|
|
|
|
game = null;
|
|
|
|
}
|
|
|
|
message = "(Filtered) " + message;
|
|
|
|
}
|
2013-02-24 01:19:53 +00:00
|
|
|
|
2013-03-27 03:17:49 +00:00
|
|
|
// don't display our own chat
|
|
|
|
if (from != cah.nickname && show) {
|
2013-10-02 12:28:16 +01:00
|
|
|
if (data[cah.$.LongPollResponse.EMOTE]) {
|
2018-03-28 01:59:31 +01:00
|
|
|
cah.log.status_with_game(game, "* " + who + " " + message, clazz, false, title);
|
2013-10-02 12:28:16 +01:00
|
|
|
} else {
|
2018-03-28 01:59:31 +01:00
|
|
|
cah.log.status_with_game(game, "<" + who + "> " + message, clazz, false, title);
|
2013-10-02 12:28:16 +01:00
|
|
|
}
|
2013-03-27 03:17:49 +00:00
|
|
|
}
|
2011-12-25 03:37:45 +00:00
|
|
|
}
|
|
|
|
};
|
2012-01-18 05:58:09 +00:00
|
|
|
|
2012-01-25 00:20:43 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_LIST_REFRESH] = function(data) {
|
2012-02-06 22:00:24 +00:00
|
|
|
cah.GameList.instance.update();
|
2012-01-18 05:58:09 +00:00
|
|
|
};
|
2012-01-23 21:37:11 +00:00
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_PLAYER_JOIN] = function(data) {
|
2012-01-25 00:20:43 +00:00
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.playerJoin,
|
2012-01-27 02:07:39 +00:00
|
|
|
data[cah.$.LongPollResponse.NICKNAME],
|
|
|
|
"player join (if you just joined a game this may be OK)");
|
2012-01-23 21:37:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_PLAYER_LEAVE] = function(data) {
|
2012-01-25 00:20:43 +00:00
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.playerLeave,
|
|
|
|
data[cah.$.LongPollResponse.NICKNAME], "player leave");
|
2012-01-23 21:37:11 +00:00
|
|
|
};
|
2012-01-23 23:06:20 +00:00
|
|
|
|
2013-06-10 12:36:11 +01:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_SPECTATOR_JOIN] = function(data) {
|
2013-12-02 04:00:57 +00:00
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.spectatorJoin,
|
|
|
|
data[cah.$.LongPollResponse.NICKNAME],
|
|
|
|
"spectator join (if you just joined a game this may be OK)");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_SPECTATOR_LEAVE] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.spectatorLeave,
|
|
|
|
data[cah.$.LongPollResponse.NICKNAME], "spectator leave");
|
|
|
|
};
|
2013-06-10 12:36:11 +01:00
|
|
|
|
2012-01-23 23:06:20 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.HAND_DEAL] = function(data) {
|
2012-01-25 00:20:43 +00:00
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.dealtCards,
|
|
|
|
data[cah.$.LongPollResponse.HAND], "dealt cards");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_STATE_CHANGE] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers
|
|
|
|
.__gameEvent(data, cah.Game.prototype.stateChange, data, "state change");
|
|
|
|
};
|
|
|
|
|
2012-01-27 02:07:39 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_PLAYER_INFO_CHANGE] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.updateUserStatus,
|
|
|
|
data[cah.$.LongPollResponse.PLAYER_INFO], "player info change");
|
|
|
|
};
|
|
|
|
|
2012-01-27 23:41:57 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_ROUND_COMPLETE] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.roundComplete, data,
|
|
|
|
"round complete");
|
|
|
|
};
|
|
|
|
|
2012-01-31 00:35:06 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_WHITE_RESHUFFLE] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.reshuffle, "white",
|
|
|
|
"white reshuffle");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_BLACK_RESHUFFLE] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.reshuffle, "black",
|
|
|
|
"black reshuffle");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_JUDGE_LEFT] = function(data) {
|
2012-03-16 06:43:43 +00:00
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.judgeLeft, data, "judge left");
|
2012-01-31 00:35:06 +00:00
|
|
|
};
|
|
|
|
|
2012-03-16 03:06:23 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_OPTIONS_CHANGED] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.optionsChanged, data,
|
|
|
|
"options changed");
|
|
|
|
};
|
|
|
|
|
2012-03-16 23:59:50 +00:00
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.HURRY_UP] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.hurryUp, "", "hurry up");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_PLAYER_KICKED_IDLE] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.playerKickedIdle, data,
|
|
|
|
"idle kick");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_PLAYER_SKIPPED] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.playerSkipped, data,
|
|
|
|
"player skip");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.GAME_JUDGE_SKIPPED] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.judgeSkipped, "", "judge skip");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.KICKED_FROM_GAME_IDLE] = function(data) {
|
|
|
|
var game = cah.currentGames[data[cah.$.LongPollResponse.GAME_ID]];
|
|
|
|
if (game) {
|
|
|
|
game.dispose();
|
|
|
|
delete cah.currentGames[data[cah.$.LongPollResponse.GAME_ID]];
|
|
|
|
}
|
|
|
|
cah.GameList.instance.show();
|
2013-06-10 11:48:03 +01:00
|
|
|
cah.GameList.instance.update();
|
2012-03-16 23:59:50 +00:00
|
|
|
|
|
|
|
cah.log.error("You were kicked from game " + data[cah.$.LongPollResponse.GAME_ID]
|
|
|
|
+ " for being idle for too long.");
|
|
|
|
};
|
|
|
|
|
2012-01-25 00:20:43 +00:00
|
|
|
/**
|
|
|
|
* Helper for event handlers for game events.
|
|
|
|
*
|
|
|
|
* @param {Object}
|
|
|
|
* data Data from server
|
|
|
|
* @param {Function}
|
|
|
|
* func Function to call.
|
|
|
|
* @param {Object}
|
|
|
|
* funcData Data to be passed to the function.
|
|
|
|
* @param {String}
|
|
|
|
* errorStr To be displayed if this is for an unknown game.
|
|
|
|
*/
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent = function(data, func, funcData, errorStr) {
|
2012-01-23 23:06:20 +00:00
|
|
|
var gameId = data[cah.$.LongPollResponse.GAME_ID];
|
|
|
|
var game = cah.currentGames[gameId];
|
|
|
|
if (game) {
|
2012-01-25 00:20:43 +00:00
|
|
|
func.call(game, funcData);
|
2012-01-23 23:06:20 +00:00
|
|
|
} else {
|
2012-01-25 00:20:43 +00:00
|
|
|
cah.log.error("Received " + errorStr + " for unknown game id " + gameId);
|
2012-01-23 23:06:20 +00:00
|
|
|
}
|
|
|
|
};
|
2014-08-11 06:16:15 +01:00
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.CARDCAST_ADD_CARDSET] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.addCardcastDeck, data,
|
|
|
|
"add Cardcast");
|
|
|
|
};
|
|
|
|
|
|
|
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.CARDCAST_REMOVE_CARDSET] = function(data) {
|
|
|
|
cah.longpoll.EventHandlers.__gameEvent(data, cah.Game.prototype.removeCardcastDeck, data,
|
|
|
|
"remove Cardcast");
|
|
|
|
};
|