Skip to content

Commit

Permalink
extend switch assist to 4-player doors
Browse files Browse the repository at this point in the history
  • Loading branch information
fuzziqersoftware committed Mar 14, 2024
1 parent 0b80af3 commit e2d76f7
Show file tree
Hide file tree
Showing 12 changed files with 73 additions and 30 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ There are many options available when starting a proxy session. All options are
* **Block pings**: blocks automatic pings sent by the client, and responds to ping commands from the server automatically. This works around a bug in Sylverant's login server.
* **Infinite HP**: automatically heals you whenever you get hit. An attack that kills you in one hit will still kill you, however.
* **Infinite TP**: automatically restores your TP whenever you use any technique.
* **Switch assist**: attempts to unlock doors that require two players in a one-player game.
* **Switch assist**: attempts to unlock doors that require two or four players in a one-player game.
* **Infinite Meseta** (Episode 3 only): gives you 1,000,000 Meseta, regardless of the value sent by the remote server.
* **Block events**: disables holiday events sent by the remote server.
* **Block patches**: prevents any B2 (patch) commands from reaching the client.
Expand Down Expand Up @@ -449,7 +449,7 @@ Some commands only work on the game server and not on the proxy server. The chat
* `$secid <section-id>`: Sets your override section ID. After running this command, any games you create will use your override section ID for rare drops instead of your character's actual section ID. If you're in a game and you are the leader of the game, this also immediately changes the item tables used by the server when creating items. To revert to your actual section id, run `$secid` with no name after it. On the proxy server, this will not work if the remote server controls item drops (e.g. on BB, or on Schtserv with server drops enabled). If the server does not allow cheat mode anywhere (that is, "CheatModeBehavior" is "Off" in config.json), this command does nothing.
* `$rand <seed>`: Sets your override random seed (specified as a 32-bit hex value). This will make any games you create use the given seed for rare enemies. This also makes item drops deterministic in Blue Burst games hosted by newserv. On the proxy server, this command can cause desyncs with other players in the same game, since they will not see the overridden random seed. To remove the override, run `$rand` with no arguments. If the server does not allow cheat mode anywhere (that is, "CheatModeBehavior" is "Off" in config.json), this command does nothing.
* `$ln [name-or-type]`: Sets the lobby number. Visible only to you. This command exists because some non-lobby maps can be loaded as lobbies with invalid lobby numbers. See the "GC lobby types" and "Ep3 lobby types" entries in the information menu for acceptable values here. Note that non-lobby maps do not have a lobby counter, so there's no way to exit the lobby without using either `$ln` again or `$exit`. On the game server, `$ln` reloads the lobby immediately; on the proxy server, it doesn't take effect until you load another lobby yourself (which means you'll like have to use `$exit` to escape). Run this command with no argument to return to the default lobby.
* `$swa`: Enables or disables switch assist. When enabled, the server will attempt to automatically unlock two-player doors in non-quest games if you step on both switches sequentially.
* `$swa`: Enables or disables switch assist. When enabled, the server will attempt to automatically unlock two-player and four-player doors in non-quest games if you step on all the required switches sequentially.
* `$exit`: If you're in a lobby, sends you to the main menu (which ends your proxy session, if you're in one). If you're in a game or spectator team, sends you to the lobby (but does not end your proxy session if you're in one). Does nothing if you're in a non-Episode 3 game and no quest is in progress.
* `$patch <name>`: Run a patch on your client. `<name>` must exactly match the name of a patch on the server.

Expand Down
1 change: 1 addition & 0 deletions src/ChatCommands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 0 additions & 1 deletion src/Client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion src/Client.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
23 changes: 23 additions & 0 deletions src/PlayerSubordinates.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 12 additions & 0 deletions src/PlayerSubordinates.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
14 changes: 6 additions & 8 deletions src/ProxyCommands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
1 change: 0 additions & 1 deletion src/ProxyServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down
2 changes: 1 addition & 1 deletion src/ProxyServer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
24 changes: 13 additions & 11 deletions src/ReceiveSubcommands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1364,17 +1364,19 @@ 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);
}

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);
}
Expand Down Expand Up @@ -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;
}
}

Expand All @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions src/SendCommands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
18 changes: 13 additions & 5 deletions tests/GC-PoisonRoom.test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6244,6 +6244,8 @@ I 56327 2024-03-03 23:40:27 - [Commands] Received from C-2 (Jess) (version=GC_V3
0010 | 00 00 00 00 |
I 56327 2024-03-03 23:40:27 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 5A 42 00 00 00 00 65 00 03 01 | ` ZB e
I 56327 2024-03-03 23:40:27 - [Commands] Sending to C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 FF FF 00 00 00 00 65 00 03 01 | ` e
I 56327 2024-03-03 23:40:27 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 42 03 00 00 89 8E 65 C4 32 06 7B 43 | ` B e 2 {C
I 56327 2024-03-03 23:40:27 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
Expand All @@ -6260,7 +6262,8 @@ I 56327 2024-03-03 23:40:27 - [Commands] Received from C-2 (Jess) (version=GC_V3
0000 | 60 00 10 00 05 03 59 42 00 00 00 00 64 00 03 01 | ` YB d
I 56327 2024-03-03 23:40:27 - [C-2] [Switch assist] Replaying previous enable command
I 56327 2024-03-03 23:40:27 - [Commands] Sending to C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 5A 42 00 00 00 00 65 00 03 01 | ` ZB e
0000 | 60 00 1C 00 05 03 FF FF 00 00 00 00 64 00 03 01 | ` d
0010 | 05 03 FF FF 00 00 00 00 65 00 03 01 | e
I 56327 2024-03-03 23:40:28 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 0B 03 58 42 01 00 00 00 58 02 00 00 | ` XB X
I 56327 2024-03-03 23:40:28 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
Expand Down Expand Up @@ -11671,7 +11674,9 @@ I 56327 2024-03-03 23:45:37 - [Commands] Received from C-2 (Jess) (version=GC_V3
0000 | 60 00 10 00 05 03 08 42 00 00 00 00 6C 00 03 01 | ` B l
I 56327 2024-03-03 23:45:37 - [C-2] [Switch assist] Replaying previous enable command
I 56327 2024-03-03 23:45:37 - [Commands] Sending to C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 59 42 00 00 00 00 64 00 03 01 | ` YB d
0000 | 60 00 28 00 05 03 FF FF 00 00 00 00 6C 00 03 01 | ` ( l
0010 | 05 03 FF FF 00 00 00 00 64 00 03 01 05 03 FF FF | d
0020 | 00 00 00 00 65 00 03 01 | e
I 56327 2024-03-03 23:45:37 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 59 42 00 00 00 00 64 00 03 00 | ` YB d
I 56327 2024-03-03 23:45:38 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
Expand Down Expand Up @@ -15242,7 +15247,7 @@ I 56327 2024-03-03 23:49:06 - [Commands] Received from C-2 (Jess) (version=GC_V3
0000 | 60 00 10 00 05 03 66 43 00 00 00 00 68 00 04 01 | ` fC h
I 56327 2024-03-03 23:49:06 - [C-2] [Switch assist] Replaying previous enable command
I 56327 2024-03-03 23:49:06 - [Commands] Sending to C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 08 42 00 00 00 00 6C 00 03 01 | ` B l
0000 | 60 00 10 00 05 03 FF FF 00 00 00 00 68 00 04 01 | ` h
I 56327 2024-03-03 23:49:06 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 42 03 00 00 AB 88 9B C3 D3 0F 10 44 | ` B D
I 56327 2024-03-03 23:49:06 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
Expand All @@ -15267,7 +15272,8 @@ I 56327 2024-03-03 23:49:08 - [Commands] Received from C-2 (Jess) (version=GC_V3
0000 | 60 00 10 00 05 03 65 43 00 00 00 00 67 00 04 01 | ` eC g
I 56327 2024-03-03 23:49:08 - [C-2] [Switch assist] Replaying previous enable command
I 56327 2024-03-03 23:49:08 - [Commands] Sending to C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 66 43 00 00 00 00 68 00 04 01 | ` fC h
0000 | 60 00 1C 00 05 03 FF FF 00 00 00 00 67 00 04 01 | ` g
0010 | 05 03 FF FF 00 00 00 00 68 00 04 01 | h
I 56327 2024-03-03 23:49:08 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 0B 03 3B 43 01 00 00 00 3B 03 00 00 | ` ;C ;
I 56327 2024-03-03 23:49:08 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
Expand Down Expand Up @@ -16093,7 +16099,9 @@ I 56327 2024-03-03 23:50:04 - [Commands] Received from C-2 (Jess) (version=GC_V3
0000 | 60 00 10 00 05 03 41 43 00 00 00 00 66 00 04 01 | ` AC f
I 56327 2024-03-03 23:50:04 - [C-2] [Switch assist] Replaying previous enable command
I 56327 2024-03-03 23:50:04 - [Commands] Sending to C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 65 43 00 00 00 00 67 00 04 01 | ` eC g
0000 | 60 00 28 00 05 03 FF FF 00 00 00 00 66 00 04 01 | ` ( f
0010 | 05 03 FF FF 00 00 00 00 67 00 04 01 05 03 FF FF | g
0020 | 00 00 00 00 68 00 04 01 | h
I 56327 2024-03-03 23:50:04 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
0000 | 60 00 10 00 05 03 65 43 00 00 00 00 67 00 04 00 | ` eC g
I 56327 2024-03-03 23:50:04 - [Commands] Received from C-2 (Jess) (version=GC_V3 command=60 flag=00)
Expand Down

0 comments on commit e2d76f7

Please sign in to comment.