mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-06-07 04:07:32 -04:00
258 lines
11 KiB
C++
258 lines
11 KiB
C++
#include "Anchor.h"
|
|
#include <libultraship/libultraship.h>
|
|
#include "soh/SohGui/SohGui.hpp"
|
|
#include "soh/SohGui/SohMenu.h"
|
|
#include "soh/util.h"
|
|
|
|
namespace SohGui {
|
|
extern std::shared_ptr<SohMenu> mSohMenu;
|
|
extern std::shared_ptr<AnchorRoomWindow> mAnchorRoomWindow;
|
|
} // namespace SohGui
|
|
|
|
static const char* pvpModes[3] = { "Off", "On", "On + Friendly Fire" };
|
|
static std::vector<const char*> teleportModes = { "None", "Team Only", "All" };
|
|
static std::vector<const char*> showLocationsModes = { "None", "Team Only", "All" };
|
|
|
|
void AnchorMainMenu(WidgetInfo& info) {
|
|
auto anchor = Anchor::Instance;
|
|
|
|
std::string host = CVarGetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.hm64.org");
|
|
uint16_t port = CVarGetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383);
|
|
std::string anchorTeamId = CVarGetString(CVAR_REMOTE_ANCHOR("TeamId"), "default");
|
|
std::string anchorRoomId = CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), "");
|
|
std::string anchorName = CVarGetString(CVAR_REMOTE_ANCHOR("Name"), "");
|
|
bool isFormValid = !SohUtils::IsStringEmpty(host) && port > 1024 && port < 65535 &&
|
|
!SohUtils::IsStringEmpty(anchorRoomId) && !SohUtils::IsStringEmpty(anchorName);
|
|
|
|
ImGui::SeparatorText("Connection Settings");
|
|
|
|
ImGui::BeginDisabled(anchor->isEnabled);
|
|
ImGui::Text("Host & Port");
|
|
if (UIWidgets::InputString("##Host", &host,
|
|
UIWidgets::InputOptions()
|
|
.Size(ImGui::GetContentRegionAvail() -
|
|
ImVec2((ImGui::GetFontSize() * 5 + ImGui::GetStyle().ItemSpacing.x), 0))
|
|
.Color(THEME_COLOR))) {
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("Host"), host.c_str());
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
UIWidgets::PushStyleInput(THEME_COLOR);
|
|
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 5);
|
|
if (ImGui::InputScalar("##Port", ImGuiDataType_U16, &port)) {
|
|
CVarSetInteger(CVAR_REMOTE_ANCHOR("Port"), port);
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
UIWidgets::PopStyleInput();
|
|
|
|
ImGui::Text("Name");
|
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
if (UIWidgets::InputString("##Name", &anchorName, UIWidgets::InputOptions().Color(THEME_COLOR))) {
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("Name"), anchorName.c_str());
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
ImGui::Text("Room ID");
|
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
if (UIWidgets::InputString("##RoomId", &anchorRoomId,
|
|
UIWidgets::InputOptions().IsSecret(anchor->isEnabled).Color(THEME_COLOR))) {
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), anchorRoomId.c_str());
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
ImGui::Text("Team ID (Items & Flags Shared)");
|
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
if (UIWidgets::InputString("##TeamId", &anchorTeamId, UIWidgets::InputOptions().Color(THEME_COLOR))) {
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("TeamId"), anchorTeamId.c_str());
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
ImGui::Spacing();
|
|
|
|
if (UIWidgets::Button("Restore Defaults", UIWidgets::ButtonOptions()
|
|
.Size(ImVec2(ImGui::GetContentRegionAvail().x / 2, 0))
|
|
.Color(UIWidgets::Colors::Red))) {
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.hm64.org");
|
|
CVarSetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383);
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("TeamId"), "default");
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), "");
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("Name"), "");
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if (UIWidgets::Button("Global Room", UIWidgets::ButtonOptions()
|
|
.Color(UIWidgets::Colors::Blue)
|
|
.Tooltip("Always-online public room so you don't have to experience "
|
|
"Hyrule alone. PVP and syncing are disabled."))) {
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("Host"), "anchor.hm64.org");
|
|
CVarSetInteger(CVAR_REMOTE_ANCHOR("Port"), 43383);
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("TeamId"), "default");
|
|
CVarSetString(CVAR_REMOTE_ANCHOR("RoomId"), "soh-global");
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
}
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
ImGui::Spacing();
|
|
|
|
ImGui::BeginDisabled(!isFormValid);
|
|
const char* buttonLabel = anchor->isEnabled ? "Disable" : "Enable";
|
|
UIWidgets::PushStyleButton(anchor->isEnabled ? UIWidgets::ColorValues.at(UIWidgets::Colors::Red)
|
|
: UIWidgets::ColorValues.at(UIWidgets::Colors::Green));
|
|
if (ImGui::Button(buttonLabel, ImVec2(-1.0f, 0.0f))) {
|
|
if (anchor->isEnabled) {
|
|
CVarClear(CVAR_REMOTE_ANCHOR("Enabled"));
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
anchor->Disable();
|
|
} else {
|
|
CVarSetInteger(CVAR_REMOTE_ANCHOR("Enabled"), 1);
|
|
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
|
anchor->Enable();
|
|
}
|
|
}
|
|
UIWidgets::PopStyleButton();
|
|
ImGui::EndDisabled();
|
|
ImGui::Spacing();
|
|
|
|
if (!anchor->isEnabled) {
|
|
return;
|
|
}
|
|
|
|
if (!anchor->isConnected) {
|
|
ImGui::Text("Connecting...");
|
|
return;
|
|
}
|
|
|
|
ImGui::SeparatorText("Current Room");
|
|
ImGui::Text("%s Connected", ICON_FA_CHECK);
|
|
|
|
if (IS_ARCHIPELAGO)
|
|
ImGui::BeginDisabled();
|
|
|
|
UIWidgets::PushStyleButton(THEME_COLOR);
|
|
if (ImGui::Button("Request Team State")) {
|
|
anchor->SendPacket_RequestTeamState();
|
|
}
|
|
UIWidgets::Tooltip("Try this if you are missing items or flags that your team members have collected");
|
|
UIWidgets::PopStyleButton();
|
|
|
|
if (IS_ARCHIPELAGO)
|
|
ImGui::EndDisabled();
|
|
|
|
ImGui::SameLine();
|
|
|
|
UIWidgets::WindowButton("Toggle Anchor Room Window", CVAR_WINDOW("AnchorRoom"), SohGui::mAnchorRoomWindow);
|
|
if (!SohGui::mAnchorRoomWindow->IsVisible()) {
|
|
SohGui::mAnchorRoomWindow->DrawElement();
|
|
}
|
|
}
|
|
|
|
void AnchorAdminMenu(WidgetInfo& info) {
|
|
auto anchor = Anchor::Instance;
|
|
bool isGlobalRoom = (std::string("soh-global") == CVarGetString(CVAR_REMOTE_ANCHOR("RoomId"), ""));
|
|
|
|
if (!anchor->isEnabled || !anchor->isConnected || anchor->roomState.ownerClientId != anchor->ownClientId ||
|
|
isGlobalRoom) {
|
|
return;
|
|
}
|
|
|
|
ImGui::SeparatorText("Room Settings (Admin Only)");
|
|
|
|
UIWidgets::PushStyleButton(THEME_COLOR);
|
|
if (ImGui::Button("Clear All Team State")) {
|
|
std::set<std::string> teams;
|
|
for (auto& [clientId, client] : Anchor::Instance->clients) {
|
|
teams.insert(client.teamId);
|
|
}
|
|
for (auto& team : teams) {
|
|
anchor->SendPacket_ClearTeamState(team);
|
|
}
|
|
}
|
|
UIWidgets::PopStyleButton();
|
|
|
|
if (UIWidgets::CVarCombobox("PvP Mode:", CVAR_REMOTE_ANCHOR("RoomSettings.PvpMode"), pvpModes,
|
|
UIWidgets::ComboboxOptions()
|
|
.DefaultIndex(1)
|
|
.LabelPosition(UIWidgets::LabelPositions::Above)
|
|
.Color(THEME_COLOR))) {
|
|
anchor->SendPacket_UpdateRoomState();
|
|
}
|
|
if (UIWidgets::CVarCombobox("Show Locations For:", CVAR_REMOTE_ANCHOR("RoomSettings.ShowLocationsMode"),
|
|
showLocationsModes,
|
|
UIWidgets::ComboboxOptions()
|
|
.DefaultIndex(1)
|
|
.LabelPosition(UIWidgets::LabelPositions::Above)
|
|
.Color(THEME_COLOR))) {
|
|
anchor->SendPacket_UpdateRoomState();
|
|
}
|
|
if (UIWidgets::CVarCombobox("Allow Teleporting To:", CVAR_REMOTE_ANCHOR("RoomSettings.TeleportMode"), teleportModes,
|
|
UIWidgets::ComboboxOptions()
|
|
.DefaultIndex(1)
|
|
.LabelPosition(UIWidgets::LabelPositions::Above)
|
|
.Color(THEME_COLOR))) {
|
|
anchor->SendPacket_UpdateRoomState();
|
|
}
|
|
|
|
if (IS_ARCHIPELAGO) {
|
|
CVarSetInteger(CVAR_REMOTE_ANCHOR("RoomSettings.SyncItemsAndFlags"), 0);
|
|
ImGui::BeginDisabled();
|
|
}
|
|
|
|
if (UIWidgets::CVarCheckbox("Sync Items & Flags", CVAR_REMOTE_ANCHOR("RoomSettings.SyncItemsAndFlags"),
|
|
UIWidgets::CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) {
|
|
anchor->SendPacket_UpdateRoomState();
|
|
}
|
|
|
|
if (IS_ARCHIPELAGO) {
|
|
ImGui::EndDisabled();
|
|
}
|
|
}
|
|
|
|
void AnchorInstructionsMenu(WidgetInfo& info) {
|
|
auto anchor = Anchor::Instance;
|
|
|
|
ImGui::SeparatorText("Usage Instructions");
|
|
|
|
ImGui::TextWrapped("1. All players involved should start at the file select screen");
|
|
|
|
ImGui::TextWrapped("2. Come up with a unique Room ID (this is basically your password) and enter it, along with "
|
|
"your desired player name and team ID and click Enable");
|
|
|
|
ImGui::TextWrapped("3. The host should configure the randomizer settings and generate a seed, then share the newly "
|
|
"generated JSON spoiler file with other players.");
|
|
|
|
ImGui::TextWrapped("4. All players should load the same JSON spoiler file (drag it into SoH window), make sure "
|
|
"seed icons match, then create a new file.");
|
|
|
|
ImGui::TextWrapped("5. All players should now load into their game. IMPORTANT! If using an existing save/seed "
|
|
"ensure the player with the most progress loads the file first.");
|
|
|
|
ImGui::TextWrapped("6. After everyone has loaded in, verify on the network tab that it doesn't warn about anyone "
|
|
"being on a wrong version or seed.");
|
|
|
|
ImGui::Spacing();
|
|
|
|
ImGui::TextWrapped(
|
|
"Note: Team ID is used to group players together in the same team, sharing items and flags. Make sure all "
|
|
"players who want to share progress use the same Team ID. All players with the same Team ID should be using "
|
|
"the same randomizer seed, while players on different teams can use different seeds.");
|
|
}
|
|
|
|
#ifdef ENABLE_REMOTE_CONTROL
|
|
void RegisterAnchorMenu() {
|
|
WidgetPath path = { "Network", "Anchor", SECTION_COLUMN_1 };
|
|
SohGui::mSohMenu->AddWidget(path, "AnchorMainMenu", WIDGET_CUSTOM)
|
|
.CustomFunction(AnchorMainMenu)
|
|
.HideInSearch(true);
|
|
path.column = SECTION_COLUMN_2;
|
|
SohGui::mSohMenu->AddWidget(path, "AnchorAdminMenu", WIDGET_CUSTOM)
|
|
.CustomFunction(AnchorAdminMenu)
|
|
.HideInSearch(true);
|
|
SohGui::mSohMenu->AddWidget(path, "AnchorInstructionsMenu", WIDGET_CUSTOM)
|
|
.CustomFunction(AnchorInstructionsMenu)
|
|
.HideInSearch(true);
|
|
}
|
|
|
|
static RegisterMenuInitFunc menuInitFunc(RegisterAnchorMenu);
|
|
#endif
|