mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 23:17:06 +02:00
Mesh streaming pool (fixes loading crashes on older GPUs) - 1.0.0 forced MeshStreaming.PoolSize to 3.5 GiB on every card. An RX 580 crashed while loading with DXGI_ERROR_DEVICE_RESET, and the oversized pool is the likely cause. The pool is now a quarter of the largest hardware adapter's dedicated video memory, capped at 3.5 GiB; cards of 6 GB or less keep the game's own 520 MB. The card, its memory and the chosen size are logged once at startup. Remote players (busy servers) - Transform interpolate is inline plain arithmetic: 22 -> 5.8 ns per joint. It was 4% of a busy server's client frame, since every player within 200 m has the whole skeleton interpolated every frame. - Players out of the camera's view and more than 8 m away are sampled at 20 Hz, like far players. Their position still updates every frame for collision, sound and nametags, and a player coming into view is sampled that frame. Expression hooks (run for every expression the game executes) - No profiler zones in the expression hooks: taking a sample switched them on, inflating the very samples that measured the hooks. - The throwdown lab pump does one sorted lookup of the running graph and skips everything else for graphs it doesn't watch (graph_throttle gets throttled_graph for this). Settings and memory reads - Script gameplay-setting and native-setting gets are served from small per-thread caches, keyed on the asset/key address, its first 8 name bytes and a new profile::Store::changes() counter, instead of a store lookup each call. - Per-frame reads in the client tick, native settings and population controls use memory::peek instead of ReadProcessMemory. - Script error logging probes each argument pointer once.
181 lines
8.5 KiB
C++
181 lines
8.5 KiB
C++
#include "gui_internal.h"
|
|
|
|
#include <cmath>
|
|
#include <cstdint>
|
|
#include <span>
|
|
|
|
// The Steam panels: sign-in, password/Steam Guard prompts and the QR code.
|
|
namespace dingosdk::launcher_gui::detail {
|
|
namespace {
|
|
|
|
void wipe(std::span<char> buffer) { SecureZeroMemory(buffer.data(), buffer.size()); }
|
|
|
|
} // namespace
|
|
|
|
void open_sign_in(Launcher& launcher, Ui& ui, bool validate) {
|
|
ui.sign_in = true;
|
|
ui.sign_in_validate = validate;
|
|
ui.focus = true;
|
|
wipe(ui.password);
|
|
ui.username.fill(0);
|
|
const auto& saved = launcher.settings().steam_username;
|
|
std::copy_n(saved.begin(), std::min(saved.size(), ui.username.size() - 1), ui.username.begin());
|
|
}
|
|
|
|
void sign_in_window(Launcher& launcher, const Fonts& fonts, ImVec2 size, Ui& ui) {
|
|
const auto panel = begin_panel("##sign_in_panel", size, ImVec2(S(480), S(520)));
|
|
auto& settings = launcher.settings();
|
|
panel_title(fonts, "SIGN IN TO STEAM");
|
|
ImGui::PushTextWrapPos(0);
|
|
ImGui::TextDisabled("skate. is downloaded from Steam with DepotDownloader, so the account must own it. "
|
|
"Your password is passed straight to Steam and never saved.");
|
|
ImGui::PopTextWrapPos();
|
|
ImGui::Spacing();
|
|
const auto start = [&](bool qr) {
|
|
if (!qr) settings.steam_username = ui.username.data();
|
|
launcher.save();
|
|
launcher.download(ui.sign_in_validate, qr, qr ? std::string() : std::string(ui.password.data()));
|
|
wipe(ui.password);
|
|
ui.sign_in = false;
|
|
};
|
|
push_primary_button();
|
|
const bool qr = ImGui::Button("SCAN A QR CODE WITH THE STEAM APP", ImVec2(-1, S(46)));
|
|
pop_primary_button();
|
|
if (qr) start(true);
|
|
ImGui::Spacing();
|
|
ImGui::PushFont(fonts.caption);
|
|
ImGui::TextDisabled("OR SIGN IN WITH YOUR ACCOUNT");
|
|
ImGui::PopFont();
|
|
if (ui.focus) { ImGui::SetKeyboardFocusHere(); ui.focus = false; }
|
|
ImGui::SetNextItemWidth(-1);
|
|
ImGui::InputTextWithHint("##username", "Steam account name", ui.username.data(), ui.username.size(),
|
|
ImGuiInputTextFlags_CharsNoBlank);
|
|
ImGui::SetNextItemWidth(-1);
|
|
const bool entered = ImGui::InputTextWithHint("##password", "Password (empty if remembered)", ui.password.data(),
|
|
ui.password.size(), ImGuiInputTextFlags_Password | ImGuiInputTextFlags_EnterReturnsTrue);
|
|
ImGui::Checkbox("Remember me on this PC", &settings.steam_remember);
|
|
ImGui::Checkbox("Type a Steam Guard code instead of approving in the app", &settings.steam_prefer_code);
|
|
const std::string_view username(ui.username.data());
|
|
const bool valid = !username.empty() && username.find_first_not_of(
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_") == std::string_view::npos;
|
|
ImGui::SetCursorPosY(panel.y - S(24) - ImGui::GetFrameHeight());
|
|
if (ImGui::Button("CANCEL", ImVec2(S(110), 0))) { wipe(ui.password); ui.sign_in = false; }
|
|
ImGui::SameLine(panel.x - S(28) - S(130));
|
|
ImGui::BeginDisabled(!valid);
|
|
push_primary_button();
|
|
const bool sign_in = ImGui::Button("SIGN IN", ImVec2(S(130), 0));
|
|
pop_primary_button();
|
|
if (sign_in || (entered && valid)) start(false);
|
|
ImGui::EndDisabled();
|
|
ImGui::End();
|
|
}
|
|
|
|
void prompt_window(Launcher& launcher, const Fonts& fonts, ImVec2 size, const update::Prompt& prompt, Ui& ui) {
|
|
const auto panel = begin_panel("##prompt_panel", size, ImVec2(S(440), S(300)));
|
|
const bool password = prompt.kind == update::PromptKind::password;
|
|
panel_title(fonts, password ? "STEAM PASSWORD" : "STEAM GUARD");
|
|
ImGui::PushTextWrapPos(0);
|
|
if (prompt.retry) ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(color::danger), "That code was incorrect. Try again.");
|
|
switch (prompt.kind) {
|
|
case update::PromptKind::password:
|
|
ImGui::TextDisabled("Enter the password for %s.", launcher.settings().steam_username.c_str());
|
|
break;
|
|
case update::PromptKind::authenticator_code:
|
|
ImGui::TextDisabled("Enter the code shown in the Steam app on your phone (Steam Guard).");
|
|
break;
|
|
case update::PromptKind::email_code: {
|
|
const auto at = prompt.text.find("email at ");
|
|
ImGui::TextDisabled("Enter the code Steam emailed to %s.",
|
|
at == std::string::npos ? "you" : prompt.text.c_str() + at + 9);
|
|
break;
|
|
}
|
|
}
|
|
ImGui::PopTextWrapPos();
|
|
ImGui::Spacing();
|
|
if (ImGui::IsWindowAppearing()) ImGui::SetKeyboardFocusHere();
|
|
ImGui::SetNextItemWidth(-1);
|
|
bool submit = false;
|
|
if (password) {
|
|
submit = ImGui::InputText("##prompt_password", ui.password.data(), ui.password.size(),
|
|
ImGuiInputTextFlags_Password | ImGuiInputTextFlags_EnterReturnsTrue);
|
|
} else {
|
|
ImGui::PushFont(fonts.heading);
|
|
submit = ImGui::InputTextWithHint("##prompt_code", "XXXXX", ui.code.data(), ui.code.size(),
|
|
ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_EnterReturnsTrue);
|
|
ImGui::PopFont();
|
|
}
|
|
const char* value = password ? ui.password.data() : ui.code.data();
|
|
ImGui::SetCursorPosY(panel.y - S(24) - ImGui::GetFrameHeight());
|
|
if (ImGui::Button("CANCEL", ImVec2(S(110), 0))) {
|
|
wipe(ui.password);
|
|
ui.code.fill(0);
|
|
launcher.answer(std::nullopt);
|
|
}
|
|
ImGui::SameLine(panel.x - S(28) - S(130));
|
|
ImGui::BeginDisabled(!*value);
|
|
push_primary_button();
|
|
const bool proceed = ImGui::Button("CONTINUE", ImVec2(S(130), 0));
|
|
pop_primary_button();
|
|
if ((proceed || submit) && *value) {
|
|
launcher.answer(std::string(value));
|
|
wipe(ui.password);
|
|
ui.code.fill(0);
|
|
}
|
|
ImGui::EndDisabled();
|
|
ImGui::End();
|
|
}
|
|
|
|
void qr_window(Launcher& launcher, const Fonts& fonts, ImVec2 size, const std::vector<std::string>& rows) {
|
|
std::size_t first = SIZE_MAX, last = 0;
|
|
for (const auto& row : rows) {
|
|
const auto begin = row.find('#'), end = row.rfind('#');
|
|
if (begin != std::string::npos) { first = std::min(first, begin); last = std::max(last, end); }
|
|
}
|
|
if (first == SIZE_MAX) return;
|
|
const float columns = static_cast<float>(last - first + 1);
|
|
const float module = std::floor(S(230) / columns);
|
|
const float code = module * columns;
|
|
const float quiet = module * 3;
|
|
const auto panel = begin_panel("##qr_panel", size, ImVec2(S(440), code + quiet * 2 + S(200)));
|
|
panel_title(fonts, "SCAN WITH STEAM");
|
|
ImGui::PushTextWrapPos(0);
|
|
ImGui::TextDisabled("Open the Steam app on your phone, tap the shield (Steam Guard) and scan this code. "
|
|
"The account must own skate.");
|
|
ImGui::PopTextWrapPos();
|
|
auto* draw = ImGui::GetWindowDrawList();
|
|
const auto window = ImGui::GetWindowPos();
|
|
const ImVec2 origin(window.x + (panel.x - code - quiet * 2) * 0.5f, ImGui::GetCursorScreenPos().y + S(8));
|
|
draw->AddRectFilled(origin, ImVec2(origin.x + code + quiet * 2, origin.y + module * static_cast<float>(rows.size()) + quiet * 2),
|
|
rgba(255, 255, 255));
|
|
for (std::size_t y = 0; y < rows.size(); ++y)
|
|
for (std::size_t x = first; x <= last && x < rows[y].size(); ++x)
|
|
if (rows[y][x] == '#') {
|
|
const ImVec2 cell(origin.x + quiet + static_cast<float>(x - first) * module,
|
|
origin.y + quiet + static_cast<float>(y) * module);
|
|
draw->AddRectFilled(cell, ImVec2(cell.x + module, cell.y + module), rgba(0, 0, 0));
|
|
}
|
|
ImGui::SetCursorPosY(panel.y - S(24) - ImGui::GetFrameHeight());
|
|
ImGui::SetCursorPosX(panel.x - S(28) - S(110));
|
|
if (ImGui::Button("CANCEL", ImVec2(S(110), 0))) launcher.cancel();
|
|
ImGui::End();
|
|
}
|
|
|
|
// Shown once when the launcher opens without Steam, so nobody reaches the main
|
|
// menu as Unknown Player wondering why multiplayer is missing.
|
|
void steam_offline_window(const Fonts& fonts, ImVec2 size, Ui& ui) {
|
|
const auto panel = begin_panel("##steam_offline_panel", size, ImVec2(S(440), S(300)));
|
|
panel_title(fonts, "STEAM IS NOT RUNNING");
|
|
ImGui::PushTextWrapPos(0);
|
|
ImGui::TextDisabled("Steam is not running, or no account is signed in. PLAY still works, but Skate starts in "
|
|
"offline mode: you play as Unknown Player and multiplayer is hidden.");
|
|
ImGui::Spacing();
|
|
ImGui::TextDisabled("To play as your own account, start Steam, sign in, and open ReSkate again.");
|
|
ImGui::PopTextWrapPos();
|
|
ImGui::SetCursorPosY(panel.y - S(24) - ImGui::GetFrameHeight());
|
|
ImGui::SetCursorPosX(panel.x - S(28) - S(110));
|
|
if (ImGui::Button("OK", ImVec2(S(110), 0))) ui.steam_offline = false;
|
|
ImGui::End();
|
|
}
|
|
|
|
} // namespace dingosdk::launcher_gui::detail
|