add player notifications on proxy server
This commit is contained in:
@@ -37,6 +37,7 @@ ClientOptions::ClientOptions()
|
|||||||
save_files(false),
|
save_files(false),
|
||||||
enable_chat_commands(true),
|
enable_chat_commands(true),
|
||||||
enable_chat_filter(true),
|
enable_chat_filter(true),
|
||||||
|
enable_player_notifications(false),
|
||||||
suppress_remote_login(false),
|
suppress_remote_login(false),
|
||||||
zero_remote_guild_card(false),
|
zero_remote_guild_card(false),
|
||||||
ep3_infinite_meseta(false),
|
ep3_infinite_meseta(false),
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ struct ClientOptions {
|
|||||||
bool save_files;
|
bool save_files;
|
||||||
bool enable_chat_commands;
|
bool enable_chat_commands;
|
||||||
bool enable_chat_filter;
|
bool enable_chat_filter;
|
||||||
|
bool enable_player_notifications;
|
||||||
bool suppress_remote_login;
|
bool suppress_remote_login;
|
||||||
bool zero_remote_guild_card;
|
bool zero_remote_guild_card;
|
||||||
bool ep3_infinite_meseta;
|
bool ep3_infinite_meseta;
|
||||||
|
|||||||
+15
-14
@@ -57,20 +57,21 @@ namespace PatchesMenuItemID {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace ProxyOptionsMenuItemID {
|
namespace ProxyOptionsMenuItemID {
|
||||||
constexpr uint32_t GO_BACK = 0xAAFFFFAA;
|
constexpr uint32_t GO_BACK = 0xAAFFFFAA;
|
||||||
constexpr uint32_t CHAT_COMMANDS = 0xAA0000AA;
|
constexpr uint32_t CHAT_COMMANDS = 0xAA0000AA;
|
||||||
constexpr uint32_t CHAT_FILTER = 0xAA1111AA;
|
constexpr uint32_t CHAT_FILTER = 0xAA1111AA;
|
||||||
constexpr uint32_t INFINITE_HP = 0xAA2222AA;
|
constexpr uint32_t PLAYER_NOTIFICATIONS = 0xAA2222AA;
|
||||||
constexpr uint32_t INFINITE_TP = 0xAA3333AA;
|
constexpr uint32_t INFINITE_HP = 0xAA3333AA;
|
||||||
constexpr uint32_t SWITCH_ASSIST = 0xAA4444AA;
|
constexpr uint32_t INFINITE_TP = 0xAA4444AA;
|
||||||
constexpr uint32_t BLOCK_EVENTS = 0xAA5555AA;
|
constexpr uint32_t SWITCH_ASSIST = 0xAA5555AA;
|
||||||
constexpr uint32_t BLOCK_PATCHES = 0xAA6666AA;
|
constexpr uint32_t BLOCK_EVENTS = 0xAA6666AA;
|
||||||
constexpr uint32_t SAVE_FILES = 0xAA7777AA;
|
constexpr uint32_t BLOCK_PATCHES = 0xAA7777AA;
|
||||||
constexpr uint32_t RED_NAME = 0xAA8888AA;
|
constexpr uint32_t SAVE_FILES = 0xAA8888AA;
|
||||||
constexpr uint32_t BLANK_NAME = 0xAA9999AA;
|
constexpr uint32_t RED_NAME = 0xAA9999AA;
|
||||||
constexpr uint32_t SUPPRESS_LOGIN = 0xAAAAAAAA;
|
constexpr uint32_t BLANK_NAME = 0xAAAAAAAA;
|
||||||
constexpr uint32_t SKIP_CARD = 0xAABBBBAA;
|
constexpr uint32_t SUPPRESS_LOGIN = 0xAABBBBAA;
|
||||||
constexpr uint32_t EP3_INFINITE_MESETA = 0xAACCCCAA;
|
constexpr uint32_t SKIP_CARD = 0xAACCCCAA;
|
||||||
|
constexpr uint32_t EP3_INFINITE_MESETA = 0xAADDDDAA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -116,7 +116,9 @@ static HandlerResult S_invalid(shared_ptr<ServerState>,
|
|||||||
|
|
||||||
static HandlerResult C_05(shared_ptr<ServerState>,
|
static HandlerResult C_05(shared_ptr<ServerState>,
|
||||||
ProxyServer::LinkedSession& session, uint16_t, uint32_t, string&) {
|
ProxyServer::LinkedSession& session, uint16_t, uint32_t, string&) {
|
||||||
session.disconnect_action = ProxyServer::LinkedSession::DisconnectAction::SHORT_TIMEOUT;
|
session.disconnect_action = session.version == GameVersion::BB
|
||||||
|
? ProxyServer::LinkedSession::DisconnectAction::MEDIUM_TIMEOUT
|
||||||
|
: ProxyServer::LinkedSession::DisconnectAction::SHORT_TIMEOUT;
|
||||||
return HandlerResult::Type::FORWARD;
|
return HandlerResult::Type::FORWARD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1307,14 +1309,18 @@ static HandlerResult S_65_67_68_EB(shared_ptr<ServerState>,
|
|||||||
if (index >= session.lobby_players.size()) {
|
if (index >= session.lobby_players.size()) {
|
||||||
session.log.warning("Ignoring invalid player index %zu at position %zu", index, x);
|
session.log.warning("Ignoring invalid player index %zu at position %zu", index, x);
|
||||||
} else {
|
} else {
|
||||||
|
string name = encode_sjis(cmd.entries[x].disp.name);
|
||||||
|
|
||||||
if (session.license && (cmd.entries[x].lobby_data.guild_card == session.remote_guild_card_number)) {
|
if (session.license && (cmd.entries[x].lobby_data.guild_card == session.remote_guild_card_number)) {
|
||||||
cmd.entries[x].lobby_data.guild_card = session.license->serial_number;
|
cmd.entries[x].lobby_data.guild_card = session.license->serial_number;
|
||||||
num_replacements++;
|
num_replacements++;
|
||||||
modified = true;
|
modified = true;
|
||||||
|
} else if (session.options.enable_player_notifications && command != 0x67) {
|
||||||
|
send_text_message_printf(session.client_channel, "$C6Join: %zu / %" PRIu32 "\n%s",
|
||||||
|
index, cmd.entries[x].lobby_data.guild_card.load(), name.c_str());
|
||||||
}
|
}
|
||||||
auto& p = session.lobby_players[index];
|
auto& p = session.lobby_players[index];
|
||||||
p.guild_card_number = cmd.entries[x].lobby_data.guild_card;
|
p.guild_card_number = cmd.entries[x].lobby_data.guild_card;
|
||||||
string name = encode_sjis(cmd.entries[x].disp.name);
|
|
||||||
p.name = name;
|
p.name = name;
|
||||||
p.section_id = cmd.entries[x].disp.section_id;
|
p.section_id = cmd.entries[x].disp.section_id;
|
||||||
p.char_class = cmd.entries[x].disp.char_class;
|
p.char_class = cmd.entries[x].disp.char_class;
|
||||||
@@ -1463,6 +1469,10 @@ static HandlerResult S_66_69_E9(shared_ptr<ServerState>,
|
|||||||
session.log.warning("Lobby leave command references missing position");
|
session.log.warning("Lobby leave command references missing position");
|
||||||
} else {
|
} else {
|
||||||
auto& p = session.lobby_players[index];
|
auto& p = session.lobby_players[index];
|
||||||
|
if (session.options.enable_player_notifications) {
|
||||||
|
send_text_message_printf(session.client_channel, "$C4Leave: %zu / %" PRIu32 "\n%s",
|
||||||
|
index, p.guild_card_number, p.name.c_str());
|
||||||
|
}
|
||||||
p.guild_card_number = 0;
|
p.guild_card_number = 0;
|
||||||
p.name.clear();
|
p.name.clear();
|
||||||
session.log.info("Removed lobby player (%zu)", index);
|
session.log.info("Removed lobby player (%zu)", index);
|
||||||
|
|||||||
+18
-12
@@ -35,11 +35,6 @@ using namespace std::placeholders;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const uint32_t LICENSED_SESSION_TIMEOUT_USECS = 5 * 60 * 1000000; // 5 minutes
|
|
||||||
static const uint32_t UNLICENSED_SESSION_TIMEOUT_USECS = 10 * 1000000; // 10 seconds
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ProxyServer::ProxyServer(
|
ProxyServer::ProxyServer(
|
||||||
shared_ptr<struct event_base> base,
|
shared_ptr<struct event_base> base,
|
||||||
shared_ptr<ServerState> state)
|
shared_ptr<ServerState> state)
|
||||||
@@ -635,7 +630,6 @@ void ProxyServer::LinkedSession::dispatch_on_timeout(
|
|||||||
|
|
||||||
|
|
||||||
void ProxyServer::LinkedSession::on_timeout() {
|
void ProxyServer::LinkedSession::on_timeout() {
|
||||||
this->log.info("Session timed out");
|
|
||||||
this->server->delete_session(this->id);
|
this->server->delete_session(this->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,9 +666,6 @@ void ProxyServer::LinkedSession::on_error(Channel& ch, short events) {
|
|||||||
session->send_to_game_server("The server has\ndisconnected.");
|
session->send_to_game_server("The server has\ndisconnected.");
|
||||||
}
|
}
|
||||||
session->disconnect();
|
session->disconnect();
|
||||||
if (session->disconnect_action == ProxyServer::LinkedSession::DisconnectAction::CLOSE_IMMEDIATELY) {
|
|
||||||
session->server->delete_session(session->id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -758,6 +749,22 @@ void ProxyServer::LinkedSession::send_to_game_server(const char* error_message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t ProxyServer::LinkedSession::timeout_for_disconnect_action(
|
||||||
|
DisconnectAction action) {
|
||||||
|
switch (action) {
|
||||||
|
case DisconnectAction::LONG_TIMEOUT:
|
||||||
|
return 5 * 60 * 1000 * 1000; // 5 minutes
|
||||||
|
case DisconnectAction::MEDIUM_TIMEOUT:
|
||||||
|
return 30 * 1000 * 1000; // 30 seconds
|
||||||
|
case DisconnectAction::SHORT_TIMEOUT:
|
||||||
|
return 10 * 1000 * 1000; // 10 seconds
|
||||||
|
case DisconnectAction::CLOSE_IMMEDIATELY:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
throw logic_error("disconnect action does not have a timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ProxyServer::LinkedSession::disconnect() {
|
void ProxyServer::LinkedSession::disconnect() {
|
||||||
// Disconnect both ends
|
// Disconnect both ends
|
||||||
this->client_channel.disconnect();
|
this->client_channel.disconnect();
|
||||||
@@ -765,9 +772,8 @@ void ProxyServer::LinkedSession::disconnect() {
|
|||||||
|
|
||||||
// Set a timeout to delete the session entirely (in case the client doesn't
|
// Set a timeout to delete the session entirely (in case the client doesn't
|
||||||
// reconnect)
|
// reconnect)
|
||||||
bool use_long_timeout = (this->license.get() && (this->disconnect_action == DisconnectAction::LONG_TIMEOUT));
|
struct timeval tv = usecs_to_timeval(this->timeout_for_disconnect_action(
|
||||||
struct timeval tv = usecs_to_timeval(use_long_timeout
|
this->disconnect_action));
|
||||||
? LICENSED_SESSION_TIMEOUT_USECS : UNLICENSED_SESSION_TIMEOUT_USECS);
|
|
||||||
event_add(this->timeout_event.get(), &tv);
|
event_add(this->timeout_event.get(), &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -49,6 +49,7 @@ public:
|
|||||||
|
|
||||||
enum class DisconnectAction {
|
enum class DisconnectAction {
|
||||||
LONG_TIMEOUT = 0,
|
LONG_TIMEOUT = 0,
|
||||||
|
MEDIUM_TIMEOUT,
|
||||||
SHORT_TIMEOUT,
|
SHORT_TIMEOUT,
|
||||||
CLOSE_IMMEDIATELY,
|
CLOSE_IMMEDIATELY,
|
||||||
};
|
};
|
||||||
@@ -146,6 +147,7 @@ public:
|
|||||||
std::shared_ptr<PSOBBMultiKeyDetectorEncryption> detector_crypt);
|
std::shared_ptr<PSOBBMultiKeyDetectorEncryption> detector_crypt);
|
||||||
void connect();
|
void connect();
|
||||||
|
|
||||||
|
static uint64_t timeout_for_disconnect_action(DisconnectAction action);
|
||||||
static void dispatch_on_timeout(evutil_socket_t fd, short what, void* ctx);
|
static void dispatch_on_timeout(evutil_socket_t fd, short what, void* ctx);
|
||||||
static void on_input(Channel& ch, uint16_t, uint32_t, std::string& msg);
|
static void on_input(Channel& ch, uint16_t, uint32_t, std::string& msg);
|
||||||
static void on_error(Channel& ch, short events);
|
static void on_error(Channel& ch, short events);
|
||||||
@@ -155,7 +157,6 @@ public:
|
|||||||
|
|
||||||
void send_to_game_server(const char* error_message = nullptr);
|
void send_to_game_server(const char* error_message = nullptr);
|
||||||
void disconnect();
|
void disconnect();
|
||||||
|
|
||||||
bool is_connected() const;
|
bool is_connected() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ static const unordered_map<uint32_t, const char16_t*> proxy_options_menu_descrip
|
|||||||
{ProxyOptionsMenuItemID::GO_BACK, u"Return to the\nproxy menu"},
|
{ProxyOptionsMenuItemID::GO_BACK, u"Return to the\nproxy menu"},
|
||||||
{ProxyOptionsMenuItemID::CHAT_COMMANDS, u"Enable chat\ncommands"},
|
{ProxyOptionsMenuItemID::CHAT_COMMANDS, u"Enable chat\ncommands"},
|
||||||
{ProxyOptionsMenuItemID::CHAT_FILTER, u"Enable escape\nsequences in\nchat messages\nand info board"},
|
{ProxyOptionsMenuItemID::CHAT_FILTER, u"Enable escape\nsequences in\nchat messages\nand info board"},
|
||||||
|
{ProxyOptionsMenuItemID::PLAYER_NOTIFICATIONS, u"Show a message\nwhen other players\njoin or leave"},
|
||||||
{ProxyOptionsMenuItemID::INFINITE_HP, u"Enable automatic HP\nrestoration when\nyou are hit by an\nenemy or trap\n\nCannot revive you\nfrom one-hit kills"},
|
{ProxyOptionsMenuItemID::INFINITE_HP, u"Enable automatic HP\nrestoration when\nyou are hit by an\nenemy or trap\n\nCannot revive you\nfrom one-hit kills"},
|
||||||
{ProxyOptionsMenuItemID::INFINITE_TP, u"Enable automatic TP\nrestoration when\nyou cast any\ntechnique"},
|
{ProxyOptionsMenuItemID::INFINITE_TP, u"Enable automatic TP\nrestoration when\nyou cast any\ntechnique"},
|
||||||
{ProxyOptionsMenuItemID::SWITCH_ASSIST, u"Automatically try\nto unlock 2-player\ndoors when you step\non both switches\nsequentially"},
|
{ProxyOptionsMenuItemID::SWITCH_ASSIST, u"Automatically try\nto unlock 2-player\ndoors when you step\non both switches\nsequentially"},
|
||||||
@@ -105,6 +106,7 @@ static vector<MenuItem> proxy_options_menu_for_client(
|
|||||||
|
|
||||||
add_option(ProxyOptionsMenuItemID::CHAT_COMMANDS, c->options.enable_chat_commands, u"Chat commands");
|
add_option(ProxyOptionsMenuItemID::CHAT_COMMANDS, c->options.enable_chat_commands, u"Chat commands");
|
||||||
add_option(ProxyOptionsMenuItemID::CHAT_FILTER, c->options.enable_chat_filter, u"Chat filter");
|
add_option(ProxyOptionsMenuItemID::CHAT_FILTER, c->options.enable_chat_filter, u"Chat filter");
|
||||||
|
add_option(ProxyOptionsMenuItemID::PLAYER_NOTIFICATIONS, c->options.enable_player_notifications, u"Player notifs");
|
||||||
if (!(c->flags & Client::Flag::IS_EPISODE_3)) {
|
if (!(c->flags & Client::Flag::IS_EPISODE_3)) {
|
||||||
add_option(ProxyOptionsMenuItemID::INFINITE_HP, c->options.infinite_hp, u"Infinite HP");
|
add_option(ProxyOptionsMenuItemID::INFINITE_HP, c->options.infinite_hp, u"Infinite HP");
|
||||||
add_option(ProxyOptionsMenuItemID::INFINITE_TP, c->options.infinite_tp, u"Infinite TP");
|
add_option(ProxyOptionsMenuItemID::INFINITE_TP, c->options.infinite_tp, u"Infinite TP");
|
||||||
@@ -1785,6 +1787,9 @@ static void on_10(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
|||||||
case ProxyOptionsMenuItemID::CHAT_FILTER:
|
case ProxyOptionsMenuItemID::CHAT_FILTER:
|
||||||
c->options.enable_chat_filter = !c->options.enable_chat_filter;
|
c->options.enable_chat_filter = !c->options.enable_chat_filter;
|
||||||
goto resend_proxy_options_menu;
|
goto resend_proxy_options_menu;
|
||||||
|
case ProxyOptionsMenuItemID::PLAYER_NOTIFICATIONS:
|
||||||
|
c->options.enable_player_notifications = !c->options.enable_player_notifications;
|
||||||
|
goto resend_proxy_options_menu;
|
||||||
case ProxyOptionsMenuItemID::INFINITE_HP:
|
case ProxyOptionsMenuItemID::INFINITE_HP:
|
||||||
c->options.infinite_hp = !c->options.infinite_hp;
|
c->options.infinite_hp = !c->options.infinite_hp;
|
||||||
goto resend_proxy_options_menu;
|
goto resend_proxy_options_menu;
|
||||||
|
|||||||
Reference in New Issue
Block a user