Merge branch 'fuzziqersoftware:master' into master
This commit is contained in:
@@ -283,7 +283,7 @@ Some commands only work on the game server and not on the proxy server. The chat
|
||||
|
||||
* Information commands
|
||||
* `$li`: Shows basic information about the lobby or game you're in. If you're on the proxy server, shows information about your connection instead (remote Guild Card number, client ID, etc.).
|
||||
* `$ping` (game server only): Shows round-trip ping time from the server to you.
|
||||
* `$ping`: Shows round-trip ping time from the server to you. On the proxy server, shows the ping time from you to the proxy and from the proxy to the server.
|
||||
* `$matcount` (game server only): Shows how many of each type of material you've used.
|
||||
* `$what` (game server only): Shows the type, name, and stats of the nearest item on the ground.
|
||||
* `$where` (game server only): Shows your current floor number and coordinates. Mainly useful for debugging.
|
||||
|
||||
+10
-1
@@ -168,6 +168,15 @@ static void server_command_ping(shared_ptr<Client> c, const std::string&) {
|
||||
send_command(c, 0x1D, 0x00);
|
||||
}
|
||||
|
||||
static void proxy_command_ping(shared_ptr<ProxyServer::LinkedSession> ses, const std::string&) {
|
||||
ses->client_ping_start_time = now();
|
||||
ses->server_ping_start_time = now();
|
||||
|
||||
C_GuildCardSearch_40 cmd = {0x00010000, ses->remote_guild_card_number, ses->remote_guild_card_number};
|
||||
ses->client_channel.send(0x1D, 0x00);
|
||||
ses->server_channel.send(0x40, 0x00, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static void proxy_command_lobby_info(shared_ptr<ProxyServer::LinkedSession> ses, const std::string&) {
|
||||
string msg;
|
||||
// On non-masked-GC sessions (BB), there is no remote Guild Card number, so we
|
||||
@@ -1883,7 +1892,7 @@ static const unordered_map<string, ChatCommandDefinition> chat_commands({
|
||||
{"$password", {server_command_password, nullptr}},
|
||||
{"$patch", {server_command_patch, proxy_command_patch}},
|
||||
{"$persist", {server_command_persist, nullptr}},
|
||||
{"$ping", {server_command_ping, nullptr}},
|
||||
{"$ping", {server_command_ping, proxy_command_ping}},
|
||||
{"$playrec", {server_command_playrec, nullptr}},
|
||||
{"$qcall", {server_command_qcall, proxy_command_qcall}},
|
||||
{"$qcheck", {server_command_qcheck, nullptr}},
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
PROXY_RED_NAME_ENABLED = 0x0000200000000000,
|
||||
PROXY_BLANK_NAME_ENABLED = 0x0000400000000000,
|
||||
PROXY_BLOCK_FUNCTION_CALLS = 0x0000800000000000,
|
||||
PROXY_EP3_UNMASK_WHISPERS = 0x0008000000000000,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
||||
@@ -789,13 +789,16 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
ast.card_cost = ce->def.self_cost;
|
||||
ast.defined_max_hp = ast.max_hp;
|
||||
|
||||
size_t z;
|
||||
size_t z = 0;
|
||||
|
||||
uint16_t z_ref = pa.attacker_card_ref;
|
||||
// Note: The (z < 9) conditions in these two loops are not present in the
|
||||
// original code.
|
||||
for (z = 0;
|
||||
((target_card_ref != pa.attacker_card_ref) && (z < 9) && (pa.action_card_refs[z] != 0xFFFF));
|
||||
((target_card_ref != z_ref) && (z < 9) && ((z_ref = pa.action_card_refs[z]) != 0xFFFF));
|
||||
z++) {
|
||||
}
|
||||
|
||||
ast.action_cards_ap = 0;
|
||||
ast.action_cards_tp = 0;
|
||||
for (; (z < 9) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
|
||||
@@ -1142,6 +1142,13 @@ Action a_extract_bml("extract-bml", "\
|
||||
PC/BB format.\n",
|
||||
a_extract_archive_fn);
|
||||
|
||||
Action a_decode_sjis(
|
||||
"decode-sjis", nullptr, +[](Arguments& args) {
|
||||
string data = read_input_data(args);
|
||||
string result = tt_sjis_to_utf8(data);
|
||||
write_output_data(args, result.data(), result.size(), "txt");
|
||||
});
|
||||
|
||||
Action a_decode_text_archive(
|
||||
"decode-text-archive", nullptr, +[](Arguments& args) {
|
||||
string data = read_input_data(args);
|
||||
|
||||
@@ -75,6 +75,7 @@ constexpr uint32_t SUPPRESS_LOGIN = 0xAA0D0DAA;
|
||||
constexpr uint32_t SKIP_CARD = 0xAA0E0EAA;
|
||||
constexpr uint32_t EP3_INFINITE_MESETA = 0xAA0F0FAA;
|
||||
constexpr uint32_t EP3_INFINITE_TIME = 0xAA1010AA;
|
||||
constexpr uint32_t EP3_UNMASK_WHISPERS = 0xAA1111AA;
|
||||
} // namespace ProxyOptionsMenuItemID
|
||||
|
||||
namespace TeamRewardMenuItemID {
|
||||
|
||||
+53
-11
@@ -119,6 +119,12 @@ static HandlerResult C_05(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
|
||||
}
|
||||
|
||||
static HandlerResult C_1D(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string&) {
|
||||
if (ses->client_ping_start_time) {
|
||||
uint64_t ping_usecs = now() - ses->client_ping_start_time;
|
||||
ses->client_ping_start_time = 0;
|
||||
double ping_ms = static_cast<double>(ping_usecs) / 1000.0;
|
||||
send_text_message_printf(ses->client_channel, "To proxy: %gms", ping_ms);
|
||||
}
|
||||
return ses->config.check_flag(Client::Flag::PROXY_SUPPRESS_CLIENT_PINGS)
|
||||
? HandlerResult::Type::SUPPRESS
|
||||
: HandlerResult::Type::FORWARD;
|
||||
@@ -554,31 +560,58 @@ static HandlerResult S_V123_04(shared_ptr<ProxyServer::LinkedSession> ses, uint1
|
||||
}
|
||||
|
||||
static HandlerResult S_V123_06(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string& data) {
|
||||
bool modified = false;
|
||||
if (ses->license) {
|
||||
auto& cmd = check_size_t<SC_TextHeader_01_06_11_B0_EE>(data, 0xFFFF);
|
||||
if (cmd.guild_card_number == ses->remote_guild_card_number) {
|
||||
cmd.guild_card_number = ses->license->serial_number;
|
||||
return HandlerResult::Type::MODIFIED;
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return HandlerResult::Type::FORWARD;
|
||||
|
||||
// If the session is Ep3, and Unmask Whispers is on, and there's enough data,
|
||||
// and the message has private_flags, and the private_flags say that you
|
||||
// shouldn't see the message, then change the private_flags
|
||||
if (is_ep3(ses->version()) &&
|
||||
ses->config.check_flag(Client::Flag::PROXY_EP3_UNMASK_WHISPERS) &&
|
||||
(data.size() >= 12) &&
|
||||
(data[sizeof(SC_TextHeader_01_06_11_B0_EE)] != '\t') &&
|
||||
(data[sizeof(SC_TextHeader_01_06_11_B0_EE)] & (1 << ses->lobby_client_id))) {
|
||||
data[sizeof(SC_TextHeader_01_06_11_B0_EE)] &= ~(1 << ses->lobby_client_id);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
return modified ? HandlerResult::Type::MODIFIED : HandlerResult::Type::FORWARD;
|
||||
}
|
||||
|
||||
template <typename CmdT>
|
||||
static HandlerResult S_41(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, uint32_t, string& data) {
|
||||
bool modified = false;
|
||||
if (ses->license) {
|
||||
auto& cmd = check_size_t<CmdT>(data);
|
||||
if (cmd.searcher_guild_card_number == ses->remote_guild_card_number) {
|
||||
cmd.searcher_guild_card_number = ses->license->serial_number;
|
||||
modified = true;
|
||||
}
|
||||
if (cmd.result_guild_card_number == ses->remote_guild_card_number) {
|
||||
cmd.result_guild_card_number = ses->license->serial_number;
|
||||
modified = true;
|
||||
if ((cmd.searcher_guild_card_number == ses->remote_guild_card_number) &&
|
||||
(cmd.result_guild_card_number == ses->remote_guild_card_number) &&
|
||||
ses->server_ping_start_time) {
|
||||
uint64_t ping_usecs = now() - ses->server_ping_start_time;
|
||||
ses->server_ping_start_time = 0;
|
||||
double ping_ms = static_cast<double>(ping_usecs) / 1000.0;
|
||||
send_text_message_printf(ses->client_channel, "To server: %gms", ping_ms);
|
||||
return HandlerResult::Type::SUPPRESS;
|
||||
|
||||
} else {
|
||||
bool modified = false;
|
||||
if (cmd.searcher_guild_card_number == ses->remote_guild_card_number) {
|
||||
cmd.searcher_guild_card_number = ses->license->serial_number;
|
||||
modified = true;
|
||||
}
|
||||
if (cmd.result_guild_card_number == ses->remote_guild_card_number) {
|
||||
cmd.result_guild_card_number = ses->license->serial_number;
|
||||
modified = true;
|
||||
}
|
||||
return modified ? HandlerResult::Type::MODIFIED : HandlerResult::Type::FORWARD;
|
||||
}
|
||||
} else {
|
||||
return HandlerResult::Type::FORWARD;
|
||||
}
|
||||
return modified ? HandlerResult::Type::MODIFIED : HandlerResult::Type::FORWARD;
|
||||
}
|
||||
|
||||
constexpr on_command_t S_DGX_41 = &S_41<S_GuildCardSearchResult_DC_V3_41>;
|
||||
@@ -1012,6 +1045,15 @@ static HandlerResult S_6x(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t,
|
||||
return HandlerResult::Type::SUPPRESS;
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((static_cast<uint8_t>(data[0]) == 0xBD) &&
|
||||
ses->config.check_flag(Client::Flag::PROXY_EP3_UNMASK_WHISPERS) &&
|
||||
is_ep3(ses->version())) {
|
||||
auto& cmd = check_size_t<G_WordSelectDuringBattle_GC_Ep3_6xBD>(data);
|
||||
if (cmd.private_flags & (1 << ses->lobby_client_id)) {
|
||||
cmd.private_flags &= ~(1 << ses->lobby_client_id);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ public:
|
||||
bool is_in_game;
|
||||
bool is_in_quest;
|
||||
uint8_t difficulty;
|
||||
uint64_t client_ping_start_time = 0;
|
||||
uint64_t server_ping_start_time = 0;
|
||||
|
||||
std::shared_ptr<PSOBBMultiKeyDetectorEncryption> detector_crypt;
|
||||
|
||||
|
||||
+10
-1
@@ -69,6 +69,8 @@ static shared_ptr<const Menu> proxy_options_menu_for_client(shared_ptr<const Cli
|
||||
"Infinite Meseta", "Fix Meseta value\nat 1,000,000");
|
||||
add_option(ProxyOptionsMenuItemID::EP3_INFINITE_TIME, Client::Flag::PROXY_EP3_INFINITE_TIME_ENABLED,
|
||||
"Infinite time", "Disable overall and\nper-phase time limits\nin battle");
|
||||
add_option(ProxyOptionsMenuItemID::EP3_UNMASK_WHISPERS, Client::Flag::PROXY_EP3_UNMASK_WHISPERS,
|
||||
"Unmask whispers", "Show contents of\nwhisper messages even\nif they are not for\nyou");
|
||||
}
|
||||
}
|
||||
add_bool_option(ProxyOptionsMenuItemID::BLOCK_EVENTS, (c->config.override_lobby_event != 0xFF),
|
||||
@@ -2229,6 +2231,9 @@ static void on_10(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
case ProxyOptionsMenuItemID::EP3_INFINITE_TIME:
|
||||
c->config.toggle_flag(Client::Flag::PROXY_EP3_INFINITE_TIME_ENABLED);
|
||||
goto resend_proxy_options_menu;
|
||||
case ProxyOptionsMenuItemID::EP3_UNMASK_WHISPERS:
|
||||
c->config.toggle_flag(Client::Flag::PROXY_EP3_UNMASK_WHISPERS);
|
||||
goto resend_proxy_options_menu;
|
||||
case ProxyOptionsMenuItemID::BLOCK_EVENTS:
|
||||
c->config.override_lobby_event = (c->config.override_lobby_event == 0xFF) ? 0x00 : 0xFF;
|
||||
goto resend_proxy_options_menu;
|
||||
@@ -3172,7 +3177,11 @@ static void on_06(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
}
|
||||
for (size_t x = 0; x < l->max_clients; x++) {
|
||||
if (l->clients[x]) {
|
||||
send_chat_message(l->clients[x], c->license->serial_number, from_name, text, private_flags);
|
||||
if (private_flags & (1 << x)) {
|
||||
send_chat_message(l->clients[x], c->license->serial_number, from_name, "(whisper)", private_flags);
|
||||
} else {
|
||||
send_chat_message(l->clients[x], c->license->serial_number, from_name, text, private_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& watcher_l : l->watcher_lobbies) {
|
||||
|
||||
@@ -1637,7 +1637,57 @@ static void on_ep3_private_word_select_bb_bank_action(shared_ptr<Client> c, uint
|
||||
}
|
||||
|
||||
} else if (is_ep3(c->version())) {
|
||||
forward_subcommand(c, command, flag, data, size);
|
||||
|
||||
const auto& cmd = check_size_t<G_WordSelectDuringBattle_GC_Ep3_6xBD>(data, size);
|
||||
G_WordSelectDuringBattle_GC_Ep3_6xBD masked_cmd = {
|
||||
{0xBD, sizeof(G_WordSelectDuringBattle_GC_Ep3_6xBD) >> 2, cmd.header.client_id},
|
||||
0x0001,
|
||||
0x0001,
|
||||
// "Please use the Whispers function."
|
||||
{0x00C1, 0x02C7, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
|
||||
0x0000,
|
||||
0x0000,
|
||||
cmd.private_flags,
|
||||
{0, 0, 0}};
|
||||
|
||||
auto send_to_client = [&](shared_ptr<Client> lc) -> void {
|
||||
if (cmd.private_flags & (1 << lc->lobby_client_id)) {
|
||||
send_command_t(lc, command, flag, masked_cmd);
|
||||
} else {
|
||||
send_command_t(lc, command, flag, cmd);
|
||||
}
|
||||
};
|
||||
|
||||
if (command_is_private(command)) {
|
||||
if (flag >= l->max_clients) {
|
||||
return;
|
||||
}
|
||||
auto target = l->clients[flag];
|
||||
if (target) {
|
||||
send_to_client(target);
|
||||
}
|
||||
} else {
|
||||
for (auto& lc : l->clients) {
|
||||
if (lc && (lc != c) && is_ep3(lc->version())) {
|
||||
send_to_client(lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& watcher_lobby : l->watcher_lobbies) {
|
||||
for (auto& target : watcher_lobby->clients) {
|
||||
if (target && is_ep3(target->version())) {
|
||||
send_command(target, command, flag, data, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (l->battle_record && l->battle_record->battle_in_progress()) {
|
||||
auto type = ((command & 0xF0) == 0xC0)
|
||||
? Episode3::BattleRecord::Event::Type::EP3_GAME_COMMAND
|
||||
: Episode3::BattleRecord::Event::Type::GAME_COMMAND;
|
||||
l->battle_record->add_command(type, data, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <initializer_list>
|
||||
#include <phosg/Encoding.hh>
|
||||
#include <phosg/Strings.hh>
|
||||
#include <stdexcept>
|
||||
@@ -58,6 +59,12 @@ struct parray {
|
||||
parray(ItemT v) {
|
||||
this->clear(v);
|
||||
}
|
||||
parray(std::initializer_list<ItemT> init_items) {
|
||||
for (size_t z = 0; z < init_items.size(); z++) {
|
||||
this->items[z] = std::data(init_items)[z];
|
||||
}
|
||||
this->clear_after(init_items.size());
|
||||
}
|
||||
template <typename ArgT = ItemT>
|
||||
requires(std::is_arithmetic_v<ArgT> || is_converted_endian_sc_v<ArgT>)
|
||||
parray() {
|
||||
|
||||
Reference in New Issue
Block a user