extend switch assist to 4-player doors

This commit is contained in:
Martin Michelsen
2024-03-14 00:05:51 -07:00
parent 0b80af3f41
commit e2d76f77be
12 changed files with 73 additions and 30 deletions
+1
View File
@@ -682,6 +682,7 @@ static void server_command_exit(shared_ptr<Client> c, const std::string&) {
G_UnusedHeader cmd = {0x73, 0x01, 0x0000};
c->channel.send(0x60, 0x00, cmd);
c->floor = 0;
c->recent_switch_flags.clear();
} else if (is_ep3(c->version())) {
c->channel.send(0xED, 0x00);
} else {
-1
View File
@@ -215,7 +215,6 @@ Client::Client(
}
this->config.specific_version = default_specific_version_for_version(version, -1);
this->last_switch_enabled_command.header.subcommand = 0;
memset(&this->next_connection_addr, 0, sizeof(this->next_connection_addr));
this->reschedule_save_game_data_event();
+1 -1
View File
@@ -250,7 +250,7 @@ public:
// Miscellaneous (used by chat commands)
uint32_t next_exp_value; // next EXP value to give
G_SwitchStateChanged_6x05 last_switch_enabled_command;
RecentSwitchFlags recent_switch_flags; // used for switch assist
bool can_chat;
struct PendingCharacterExport {
std::shared_ptr<const License> license;
+23
View File
@@ -1091,3 +1091,26 @@ SymbolChat::SymbolChat()
: spec(0),
corner_objects(0x00FF),
face_parts() {}
void RecentSwitchFlags::add(uint16_t flag_num) {
if ((flag_num != ((this->flag_nums >> 48) & 0xFFFF)) &&
(flag_num != ((this->flag_nums >> 32) & 0xFFFF)) &&
(flag_num != ((this->flag_nums >> 16) & 0xFFFF)) &&
(flag_num != (this->flag_nums & 0xFFFF))) {
this->flag_nums = this->flag_nums << 16 | flag_num;
}
}
string RecentSwitchFlags::enable_commands(uint8_t floor) const {
StringWriter w;
uint64_t flag_nums = this->flag_nums;
for (size_t z = 0; z < 4; z++) {
uint16_t flag_num = flag_nums;
if (flag_num == 0xFFFF) {
continue;
}
w.put(G_SwitchStateChanged_6x05{{0x05, 0x03, 0xFFFF}, 0, 0, flag_num, static_cast<uint8_t>(floor), 0x01});
flag_nums >>= 16;
}
return std::move(w.str());
}
+12
View File
@@ -733,3 +733,15 @@ struct SymbolChat {
SymbolChat();
} __attribute__((packed));
struct RecentSwitchFlags {
uint64_t flag_nums = 0xFFFFFFFFFFFFFFFF;
inline void clear() {
this->flag_nums = 0xFFFFFFFFFFFFFFFF;
}
void add(uint16_t flag_num);
std::string enable_commands(uint8_t floor) const;
};
+6 -8
View File
@@ -1946,15 +1946,13 @@ HandlerResult C_6x<void>(shared_ptr<ProxyServer::LinkedSession> ses, uint16_t, u
if (!data.empty()) {
if ((data[0] == 0x05) && ses->config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED)) {
auto& cmd = check_size_t<G_SwitchStateChanged_6x05>(data);
if (cmd.flags && cmd.header.object_id != 0xFFFF) {
if (ses->last_switch_enabled_command.header.subcommand == 0x05) {
ses->log.info("Switch assist: replaying previous enable command");
ses->server_channel.send(0x60, 0x00, &ses->last_switch_enabled_command,
sizeof(ses->last_switch_enabled_command));
ses->client_channel.send(0x60, 0x00, &ses->last_switch_enabled_command,
sizeof(ses->last_switch_enabled_command));
if ((cmd.flags & 1) && (cmd.header.object_id != 0xFFFF)) {
ses->recent_switch_flags.add(cmd.switch_flag_num);
string commands = ses->recent_switch_flags.enable_commands(ses->floor);
if (!commands.empty()) {
ses->server_channel.send(0x60, 0x00, commands);
ses->client_channel.send(0x60, 0x00, commands);
}
ses->last_switch_enabled_command = cmd;
}
} else if (data[0] == 0x21) {
-1
View File
@@ -537,7 +537,6 @@ ProxyServer::LinkedSession::LinkedSession(
lobby_mode(GameMode::NORMAL),
lobby_episode(Episode::EP1),
lobby_random_seed(0) {
this->last_switch_enabled_command.header.subcommand = 0;
memset(this->prev_server_command_bytes, 0, sizeof(this->prev_server_command_bytes));
}
+1 -1
View File
@@ -70,7 +70,7 @@ public:
Client::Config config;
// A null handler in here means to forward the response to the remote server
std::deque<std::function<void(uint32_t return_value, uint32_t checksum)>> function_call_return_handler_queue;
G_SwitchStateChanged_6x05 last_switch_enabled_command;
RecentSwitchFlags recent_switch_flags; // used for switch assist
ItemData next_drop_item;
uint32_t next_item_id;
+13 -11
View File
@@ -1364,8 +1364,9 @@ static void on_change_floor_6x1F(shared_ptr<Client> c, uint8_t command, uint8_t
} else {
const auto& cmd = check_size_t<G_SetPlayerFloor_6x1F>(data, size);
if (cmd.floor >= 0) {
if (cmd.floor >= 0 && c->floor != static_cast<uint32_t>(cmd.floor)) {
c->floor = cmd.floor;
c->recent_switch_flags.clear();
}
}
forward_subcommand(c, command, flag, data, size);
@@ -1373,8 +1374,9 @@ static void on_change_floor_6x1F(shared_ptr<Client> c, uint8_t command, uint8_t
static void on_change_floor_6x21(shared_ptr<Client> c, uint8_t command, uint8_t flag, void* data, size_t size) {
const auto& cmd = check_size_t<G_InterLevelWarp_6x21>(data, size);
if (cmd.floor >= 0) {
if (cmd.floor >= 0 && c->floor != static_cast<uint32_t>(cmd.floor)) {
c->floor = cmd.floor;
c->recent_switch_flags.clear();
}
forward_subcommand(c, command, flag, data, size);
}
@@ -1551,18 +1553,17 @@ static void on_switch_state_changed(shared_ptr<Client> c, uint8_t command, uint8
}
}
if (cmd.flags && cmd.header.object_id != 0xFFFF) {
if (!l->quest &&
c->config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED) &&
(c->last_switch_enabled_command.header.subcommand == 0x05)) {
c->log.info("[Switch assist] Replaying previous enable command");
if ((cmd.flags & 1) && cmd.header.object_id != 0xFFFF) {
c->recent_switch_flags.add(cmd.switch_flag_num);
if (!l->quest && c->config.check_flag(Client::Flag::SWITCH_ASSIST_ENABLED)) {
if (c->config.check_flag(Client::Flag::DEBUG_ENABLED)) {
send_text_message(c, "$C5Switch assist");
}
forward_subcommand(c, command, flag, &c->last_switch_enabled_command, sizeof(c->last_switch_enabled_command));
send_command_t(c, command, flag, c->last_switch_enabled_command);
string commands = c->recent_switch_flags.enable_commands(c->floor);
if (!commands.empty()) {
send_command(c, 0x60, 0x00, commands);
}
}
c->last_switch_enabled_command = cmd;
}
}
@@ -1587,8 +1588,9 @@ void on_movement_with_floor(shared_ptr<Client> c, uint8_t command, uint8_t flag,
}
c->x = cmd.x;
c->z = cmd.z;
if (cmd.floor >= 0) {
if (cmd.floor >= 0 && c->floor != static_cast<uint32_t>(cmd.floor)) {
c->floor = cmd.floor;
c->recent_switch_flags.clear();
}
forward_subcommand(c, command, flag, data, size);
}
+1
View File
@@ -2439,6 +2439,7 @@ void send_warp(Channel& ch, uint8_t client_id, uint32_t floor, bool is_private)
void send_warp(shared_ptr<Client> c, uint32_t floor, bool is_private) {
send_warp(c->channel, c->lobby_client_id, floor, is_private);
c->floor = floor;
c->recent_switch_flags.clear();
}
void send_warp(shared_ptr<Lobby> l, uint32_t floor, bool is_private) {