Skip to content

Conversation

@VMSolidus
Copy link
Member

This PR adds a new tab for "Classic Servers", which provides the list of all Space Station 13 servers for the user to search through. These servers can be connected to via simple button, though the user is required to have the Byond client installed. If they don't have it, they'll be prompted to install it from byond's website.

I have tested this PR and verified that it works.

AuroraThroughSteam.mp4

@VMSolidus
Copy link
Member Author

I had it do some final cleanup for the UI to make sure it looks the same as the regular Servers tab.
image

@VMSolidus
Copy link
Member Author

image

made it add alternating colors for the Classic Servers tab.

Copy link
Member

@DEATHB4DEFEAT DEATHB4DEFEAT left a comment

Choose a reason for hiding this comment

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

This is all notes for when I take over this PR, and this is all without the context of existing systems, I need to compare them later.

Copy link
Member

Choose a reason for hiding this comment

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

delete

## Strings for the "servers" tab

tab-servers-title = Servers
tab-servers-classic-title = Classic Servers
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
tab-servers-classic-title = Classic Servers
tab-servers-classic-title = BYOND Servers


tab-servers-title = Servers
tab-servers-classic-title = Classic Servers
tab-servers-classic-desc = All servers listed here connect via the BYOND client.
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this gets used

{
var response = await _http.GetStringAsync("http://www.byond.com/games/exadv1/spacestation13?format=text");
// Log.Information("BYOND Response: {Response}", response);
await File.WriteAllTextAsync("byond_dump.txt", response);
Copy link
Member

Choose a reason for hiding this comment

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

Very odd choice, and it doesn't look like this ever gets deleted

Comment on lines +51 to +147
private List<ClassicServerStatusData> ParseByondResponse(string response)
{
var list = new List<ClassicServerStatusData>();
using var reader = new StringReader(response);

string? line;
string? currentName = null;
string? currentUrl = null;
string? currentStatus = null;
int currentPlayers = 0;

// Simple state machine to parse the text format
// The format uses 'world/ID' blocks for servers.

bool inServerBlock = false;

while ((line = reader.ReadLine()) != null)
{
var trimmed = line.Trim();
if (string.IsNullOrWhiteSpace(trimmed)) continue;

if (trimmed.StartsWith("world/"))
{
// If we were parsing a server, save it
if (inServerBlock && currentUrl != null)
{
// Name might be missing, try to extract from status or use URL
var name = currentName ?? ExtractNameFromStatus(currentStatus) ?? "Unknown Server";
var roundTime = ExtractRoundTimeFromStatus(currentStatus);
list.Add(new ClassicServerStatusData(name, currentUrl, currentPlayers, CleanStatus(currentStatus, name) ?? "", roundTime ?? "In-Lobby"));
}

// Reset for new server
inServerBlock = true;
currentName = null;
currentUrl = null;
currentStatus = null;
currentPlayers = 0;
}
else if (inServerBlock)
{
if (trimmed.StartsWith("name ="))
{
currentName = ParseStringValue(trimmed);
}
else if (trimmed.StartsWith("url ="))
{
currentUrl = ParseStringValue(trimmed);
}
else if (trimmed.StartsWith("status ="))
{
currentStatus = ParseStringValue(trimmed);
}
else if (trimmed.StartsWith("players = list("))
{
// "players = list("Bob","Alice")"
// Just count the commas + 1, correcting for empty list "list()"
var content = trimmed.Substring("players = list(".Length);
if (content.EndsWith(")"))
{
content = content.Substring(0, content.Length - 1);
if (string.IsNullOrWhiteSpace(content))
{
currentPlayers = 0;
}
else
{
// A simple Count(',') + 1 is risky if names contain commas, but usually they are quoted.
// However, parsing full CSV is safer but 'Splitting by ",' might be enough?
// Let's iterate and count quoted segments.
// Or simpler: Splitting by ',' is mostly fine for SS13 ckeys.
currentPlayers = content.Split(',').Length;
}
}
}
else if (trimmed.StartsWith("players ="))
{
// Fallback for simple number if ever used
var parts = trimmed.Split('=');
if (parts.Length > 1 && int.TryParse(parts[1].Trim(), out var p))
{
currentPlayers = p;
}
}
}
}

// Add the last one if exists
if (inServerBlock && currentUrl != null)
{
var name = currentName ?? ExtractNameFromStatus(currentStatus) ?? "Unknown Server";
var roundTime = ExtractRoundTimeFromStatus(currentStatus);
list.Add(new ClassicServerStatusData(name, currentUrl, currentPlayers, CleanStatus(currentStatus, name) ?? "", roundTime ?? "In-Lobby"));
}

return list;
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this could all be made into a regex

Comment on lines +7 to +11
public string Name { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public int PlayerCount { get; set; }
public string Status { get; set; } = string.Empty;
public string RoundTime { get; set; } = string.Empty;
Copy link
Member

Choose a reason for hiding this comment

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

Do these not default to empty strings?

Comment on lines +46 to +74
// Prompt to download
// We can use the native MessageBox helper from Helpers if available or just open the link.
// Following the prompt instructions mostly literally: "prompted to install it first by going to this link"

// On Windows we can use the MessageBox to be nicer.
// NOTE: Helper MessageBox returns int, 1 is usually OK.
if (OperatingSystem.IsWindows())
{
var res = Helpers.MessageBoxHelper(
"BYOND not detected. You need the BYOND client to play Space Station 13. Go to download page?",
"BYOND Missing",
0x00000004 | 0x00000030); // MB_YESNO | MB_ICONWARNING

if (res == 6) // IDYES
{
Helpers.OpenUri(new Uri("https://www.byond.com/download/"));
}
}
else
{
// Non-windows, just open the link? Or maybe they have it via Wine?
// For now, let's open the link if we can't be sure, or maybe just try launching it?
// The prompt was "Check if they have BYOND... If not... prompt".
// Since I can't check on Linux easily, I'll assume they might not have it if I can't check.
// But actually, opening the URI is the best 'try'.
// Let's just try to open it on non-windows.
Helpers.OpenUri(new Uri(_server.Address));
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Use the existing in-app notification dialog helper instead of worrying about platform

Copy link
Member

Choose a reason for hiding this comment

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

And use the compiler flags for platform instead of ifs

Comment on lines +79 to +97
if (!OperatingSystem.IsWindows())
{
// On Linux/Mac, we can't easily check for BYOND (usually running under Wine).
// We'll return true to let the OS/Wine try to handle the protocol.
return true;
}

try
{
// Check for BYOND in Registry
// HKCU\Software\Dantom\BYOND is the standard key.
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Dantom\BYOND");
return key != null;
}
catch
{
return false;
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Ditto on the compiler flags. I can make a check for an xdg protocol for linux, mac will be left unhandled yet again, and I'll see if we can do this without a try/catch.

@DEATHB4DEFEAT DEATHB4DEFEAT self-assigned this Jan 20, 2026
@DEATHB4DEFEAT DEATHB4DEFEAT added Priority: 4-Low Should be resolved at some point Size: 2-Large For large issues/PRs Status: Needs Cleanup Someone has to clean this before merging Type: Feature Creation of or significant changes to a feature labels Jan 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority: 4-Low Should be resolved at some point Size: 2-Large For large issues/PRs Status: Needs Cleanup Someone has to clean this before merging Type: Feature Creation of or significant changes to a feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants