Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial Sail implementation #790

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ jobs:
- name: Build 2Ship
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DBUILD_NETWORKING=1
cmake --build build-cmake --config Release --parallel 10
(cd build-cmake && cpack)

Expand Down Expand Up @@ -259,6 +259,7 @@ jobs:
SDL2-2.30.3
tinyxml2-10.0.0
libzip-1.10.1
SDL2_net-2.2.0
- name: Install latest SDL
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
Expand All @@ -285,6 +286,18 @@ jobs:
cmake ..
make
sudo make install
- name: Install latest SDL_net
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "SDL2_net-2.2.0" ]; then
wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz
tar -xzf SDL2_net-2.2.0.tar.gz
fi
cd SDL2_net-2.2.0
./configure
make -j 10
sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Install libzip without crypto
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
Expand All @@ -307,7 +320,7 @@ jobs:
- name: Build 2Ship
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_REMOTE_CONTROL=1
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_NETWORKING=1
cmake --build build-cmake --config Release -j3
(cd build-cmake && cpack -G External)

Expand Down Expand Up @@ -367,7 +380,7 @@ jobs:
VCPKG_ROOT: ${{github.workspace}}/vcpkg
run: |
set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH"
cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DBUILD_NETWORKING=1
cmake --build build-windows --config Release --parallel 10

(cd build-windows && cpack)
Expand Down
6 changes: 0 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
endif()
endif()

if (CMAKE_SYSTEM_NAME MATCHES "Windows|Linux")
if(NOT DEFINED BUILD_CROWD_CONTROL)
set(BUILD_CROWD_CONTROL OFF)
endif()
endif()

# Enable the Gfx debugger in LUS to use libgfxd from ZAPDTR
set(GFX_DEBUG_DISASSEMBLER ON)

Expand Down
118 changes: 117 additions & 1 deletion mm/2s2h/BenGui/SearchableMenuItems.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "variables.h"
#include <variant>
#include <tuple>
#include "ShipUtils.h"
#include "2s2h/Network/Sail.h"

extern "C" {
#include "functions.h"
Expand Down Expand Up @@ -50,6 +52,8 @@ typedef enum {
DISABLE_FOR_FRAME_ADVANCE_OFF,
DISABLE_FOR_WARP_POINT_NOT_SET,
DISABLE_FOR_INTRO_SKIP_OFF,
DISABLE_FOR_SAIL_FORM_INVALID,
DISABLE_FOR_SAIL_ENABLED,
} DisableOption;

struct widgetInfo;
Expand All @@ -73,6 +77,8 @@ typedef enum {
WIDGET_CVAR_COMBOBOX,
WIDGET_CVAR_SLIDER_INT,
WIDGET_CVAR_SLIDER_FLOAT,
WIDGET_CVAR_INPUT_STRING,
WIDGET_CVAR_INPUT_INT,
WIDGET_BUTTON,
WIDGET_COLOR_24, // color picker without alpha
WIDGET_COLOR_32, // color picker with alpha
Expand Down Expand Up @@ -347,7 +353,16 @@ static std::map<DisableOption, disabledInfo> disabledMap = {
"Warp Point Not Saved" } },
{ DISABLE_FOR_INTRO_SKIP_OFF,
{ [](disabledInfo& info) -> bool { return !CVarGetInteger("gEnhancements.Cutscenes.SkipIntroSequence", 0); },
"Intro Skip Not Selected" } }
"Intro Skip Not Selected" } },
{ DISABLE_FOR_SAIL_FORM_INVALID,
{ [](disabledInfo& info) -> bool {
return !(!isStringEmpty(CVarGetString("gNetwork.Sail.Host", "127.0.0.1")) &&
CVarGetInteger("gNetwork.Sail.Port", 43384) > 1024 &&
CVarGetInteger("gNetwork.Sail.Port", 43384) < 65535);
},
"Invalid Host/Port" } },
{ DISABLE_FOR_SAIL_ENABLED,
{ [](disabledInfo& info) -> bool { return Sail::Instance->isEnabled; }, "Sail is Enabled" } },
Comment on lines +357 to +365
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use of Sail:: needs to be wrapped in an ifdef to prevent compile errors with networking off. Not sure if it makes sense to just ifdef out the two disable options all together, or just force the return value to false.

};

std::unordered_map<int32_t, const char*> menuThemeOptions = {
Expand Down Expand Up @@ -764,6 +779,78 @@ void AddSettings() {
} },
} } });

#ifdef ENABLE_NETWORKING
// Network
settingsSidebar.push_back(
{ "Network",
3,
{ {
{ .widgetName = "Sail", .widgetType = WIDGET_SEPARATOR_TEXT },
{ "Host",
"gNetwork.Sail.Host",
"",
WIDGET_CVAR_INPUT_STRING,
{ .defaultVariant = "127.0.0.1" },
{},
[](widgetInfo& info) {
if (disabledMap.at(DISABLE_FOR_SAIL_ENABLED).active) {
info.activeDisables.push_back(DISABLE_FOR_SAIL_ENABLED);
}
} },
{ "Port",
"gNetwork.Sail.Port",
"",
WIDGET_CVAR_INPUT_INT,
{ .defaultVariant = 43384 },
{},
[](widgetInfo& info) {
if (disabledMap.at(DISABLE_FOR_SAIL_ENABLED).active) {
info.activeDisables.push_back(DISABLE_FOR_SAIL_ENABLED);
}
} },
{ "Connect",
"",
"Connect/Disconnect to the Sail server.",
WIDGET_BUTTON,
{},
[](widgetInfo& info) {
if (Sail::Instance->isEnabled) {
CVarClear("gNetwork.Sail.Enabled");
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
Sail::Instance->Disable();
} else {
CVarSetInteger("gNetwork.Sail.Enabled", 1);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
Sail::Instance->Enable();
}
},
[](widgetInfo& info) {
if (Sail::Instance->isEnabled) {
info.widgetName = "Disconnect";
} else {
info.widgetName = "Connect";
}
if (disabledMap.at(DISABLE_FOR_SAIL_FORM_INVALID).active)
info.activeDisables.push_back(DISABLE_FOR_SAIL_FORM_INVALID);
} },
{ "Connected",
"",
"Displays the current connection status.",
WIDGET_TEXT,
{},
{},
[](widgetInfo& info) {
if (Sail::Instance->isEnabled && Sail::Instance->isConnected) {
info.widgetName = "Connected";
} else if (Sail::Instance->isEnabled) {
info.widgetName = "Connecting...";
} else {
info.isHidden = true;
}
} },
} } });
#endif

if (CVarGetInteger("gSettings.SidebarSearch", 0)) {
settingsSidebar.insert(settingsSidebar.begin() + searchSidebarIndex, searchSidebarEntry);
}
Expand Down Expand Up @@ -1813,6 +1900,35 @@ void SearchMenuGetItem(widgetInfo& widget) {
}
}
break;
case WIDGET_CVAR_INPUT_STRING: {
if (UIWidgets::CVarInputString(
widget.widgetName.c_str(), widget.widgetCVar,
{
.color = menuTheme[menuThemeIndex],
.tooltip = widget.widgetTooltip,
.disabled = disabledValue,
.disabledTooltip = disabledTooltip,
.defaultValue = std::get<const char*>(widget.widgetOptions.defaultVariant),
})) {
if (widget.widgetCallback != nullptr) {
widget.widgetCallback(widget);
}
}
} break;
case WIDGET_CVAR_INPUT_INT: {
if (UIWidgets::CVarInputInt(widget.widgetName.c_str(), widget.widgetCVar,
{
.color = menuTheme[menuThemeIndex],
.tooltip = widget.widgetTooltip,
.disabled = disabledValue,
.disabledTooltip = disabledTooltip,
.defaultValue = std::get<int32_t>(widget.widgetOptions.defaultVariant),
})) {
if (widget.widgetCallback != nullptr) {
widget.widgetCallback(widget);
}
}
} break;
case WIDGET_SLIDER_INT: {
int32_t* pointer = std::get<int32_t*>(widget.widgetOptions.valuePointer);
if (pointer == nullptr) {
Expand Down
105 changes: 105 additions & 0 deletions mm/2s2h/BenGui/UIWidgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,111 @@ bool CVarColorPicker(const char* label, const char* cvarName, Color_RGBA8 defaul
return changed;
}

void PushStyleInput(const ImVec4& color) {
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(color.x, color.y, color.z, 1.0f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(color.x, color.y, color.z, 1.0f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(color.x, color.y, color.z, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(color.x, color.y, color.z, 1.0f));
ImGui::PushStyleColor(ImGuiCol_SliderGrab, ImVec4(1.0, 1.0, 1.0, 0.4f));
ImGui::PushStyleColor(ImGuiCol_SliderGrabActive, ImVec4(1.0, 1.0, 1.0, 0.5f));
ImGui::PushStyleVar(ImGuiStyleVar_GrabRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10.0f, 8.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
}

void PopStyleInput() {
ImGui::PopStyleVar(4);
ImGui::PopStyleColor(6);
}

// Reference: imgui-src/misc/cpp/imgui_stdlib.cpp
int InputTextResizeCallback(ImGuiInputTextCallbackData* data) {
std::string* value = (std::string*)data->UserData;
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
value->resize(data->BufTextLen);
data->Buf = (char*)value->c_str();
}
return 0;
}

bool InputString(const char* label, std::string* value, const InputStringOptions& options) {
bool dirty = false;
ImGui::PushID(label);
ImGui::BeginGroup();
std::string invisibleLabelStr = "##" + std::string(label);
const char* invisibleLabel = invisibleLabelStr.c_str();
PushStyleInput(options.color);
ImGui::BeginDisabled(options.disabled);
if (options.labelPosition != LabelPosition::None) {
ImGui::Text(label);
}
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputText(invisibleLabel, (char*)value->c_str(), value->capacity() + 1,
ImGuiInputTextFlags_CallbackResize, InputTextResizeCallback, value)) {
dirty = true;
}
ImGui::EndDisabled();
if (options.disabled && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) &&
strcmp(options.disabledTooltip, "") != 0) {
ImGui::SetTooltip("%s", WrappedText(options.disabledTooltip).c_str());
} else if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(options.tooltip, "") != 0) {
ImGui::SetTooltip("%s", WrappedText(options.tooltip).c_str());
}
PopStyleInput();
ImGui::EndGroup();
ImGui::PopID();
return dirty;
}

bool CVarInputString(const char* label, const char* cvarName, const InputStringOptions& options) {
std::string value = CVarGetString(cvarName, options.defaultValue);
bool dirty = InputString(label, &value, options);
if (dirty) {
CVarSetString(cvarName, value.c_str());
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
return dirty;
}

bool InputInt(const char* label, int32_t* value, const InputIntOptions& options) {
bool dirty = false;
ImGui::PushID(label);
ImGui::BeginGroup();
std::string invisibleLabelStr = "##" + std::string(label);
const char* invisibleLabel = invisibleLabelStr.c_str();
PushStyleInput(options.color);
ImGui::BeginDisabled(options.disabled);
if (options.labelPosition != LabelPosition::None) {
ImGui::Text(label);
}
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt(invisibleLabel, value, NULL, NULL)) {
dirty = true;
}
ImGui::EndDisabled();
if (options.disabled && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) &&
strcmp(options.disabledTooltip, "") != 0) {
ImGui::SetTooltip("%s", WrappedText(options.disabledTooltip).c_str());
} else if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled) && strcmp(options.tooltip, "") != 0) {
ImGui::SetTooltip("%s", WrappedText(options.tooltip).c_str());
}
PopStyleInput();
ImGui::EndGroup();
ImGui::PopID();
return dirty;
}

bool CVarInputInt(const char* label, const char* cvarName, const InputIntOptions& options) {
int32_t value = CVarGetInteger(cvarName, options.defaultValue);
bool dirty = InputInt(label, &value, options);
if (dirty) {
CVarSetInteger(cvarName, value);
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick();
}
return dirty;
}

void DrawFlagArray32(const std::string& name, uint32_t& flags) {
ImGui::PushID(name.c_str());
for (int32_t flagIndex = 0; flagIndex < 32; flagIndex++) {
Expand Down
27 changes: 27 additions & 0 deletions mm/2s2h/BenGui/UIWidgets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,33 @@ namespace UIWidgets {
bool SliderFloat(const char* label, float* value, float min, float max, const FloatSliderOptions& options = {});
bool CVarSliderFloat(const char* label, const char* cvarName, float min, float max, const float defaultValue, const FloatSliderOptions& options = {});
bool CVarColorPicker(const char* label, const char* cvarName, Color_RGBA8 defaultColor);

struct InputStringOptions {
const ImVec4 color = Colors::Gray;
const char* tooltip = "";
bool disabled = false;
const char* disabledTooltip = "";
const char* placeholder = "";
const char* defaultValue = ""; // Only applicable to CVarInputString
LabelPosition labelPosition = LabelPosition::Above;
};

struct InputIntOptions {
const ImVec4 color = Colors::Gray;
const char* tooltip = "";
bool disabled = false;
const char* disabledTooltip = "";
const char* placeholder = "";
int32_t defaultValue = 0; // Only applicable to CVarInputInt
LabelPosition labelPosition = LabelPosition::Above;
};

void PushStyleInput(const ImVec4& color = Colors::Indigo);
void PopStyleInput();
bool InputString(const char* label, std::string* value, const InputStringOptions& options = {});
bool CVarInputString(const char* label, const char* cvarName, const InputStringOptions& options = {});
bool InputInt(const char* label, int32_t* value, const InputIntOptions& options = {});
bool CVarInputInt(const char* label, const char* cvarName, const InputIntOptions& options = {});
void DrawFlagArray32(const std::string& name, uint32_t& flags);
void DrawFlagArray16(const std::string& name, uint16_t& flags);
void DrawFlagArray8(const std::string& name, uint8_t& flags);
Expand Down
Loading
Loading