Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f25137e
Add Pelican side-by-side RedSync BETA server (:2177)
cursoragent Jul 17, 2026
cdde233
Fix Deploy-BetaServer.ps1 to always use xerox.pri (no password prompt)
cursoragent Jul 17, 2026
26f164f
Add Pelican discovery script for proper beta server clone
cursoragent Jul 17, 2026
452bef7
Create RedSync BETA as a real Pelican/Wings server
cursoragent Jul 17, 2026
47dd91b
Wire Deploy-BetaServer.ps1 to Pelican panel creator
cursoragent Jul 17, 2026
2d73ec6
Fix Deploy-BetaServer: allow password SSH (drop BatchMode)
cursoragent Jul 17, 2026
1a2bc88
chmod check-pelican-beta.sh
cursoragent Jul 17, 2026
2159d15
Fix pelican beta create: PHP script readable by www-data
cursoragent Jul 17, 2026
a3389e0
Fix Wings start: use Daemon\DaemonServerRepository::power
cursoragent Jul 17, 2026
02a6806
Update create script start phase for DaemonServerRepository
cursoragent Jul 17, 2026
8f37fa6
Improve check-pelican-beta status dump
cursoragent Jul 17, 2026
e44206d
Add 2000 max players and launcher Players Online tab
cursoragent Jul 17, 2026
8635569
Add Wings recreate script so status ports 2079/2179 publish
cursoragent Jul 17, 2026
7b3d7e1
Fix status HTTP bind for Docker + restore Official helper
cursoragent Jul 17, 2026
4e91fae
Add Publish-Cdn.ps1 to rebuild and upload launcher to VPS media
cursoragent Jul 17, 2026
ef88417
CDN page: note Players Online tab, BETA, 2000 cap
cursoragent Jul 17, 2026
9d3a518
Fix Publish-Cdn.ps1 for Windows PowerShell 5 parsing
cursoragent Jul 17, 2026
a44ab6f
Fix launcher build: stop copying servers.json onto itself
cursoragent Jul 17, 2026
1843fef
Publish-Cdn: treat exe presence as build success
cursoragent Jul 17, 2026
92767db
Publish-Cdn: avoid CRLF breaking remote ls/curl check
cursoragent Jul 17, 2026
1f60895
Add fix-pelican-cache.sh for panel storage 500 errors
cursoragent Jul 17, 2026
ab0ae8b
Add show-admin-secrets.sh for Official/BETA admin join secrets
cursoragent Jul 17, 2026
84dd6cb
Add script to register XEROX as separate admin from XEROX710
cursoragent Jul 17, 2026
007614a
Add fix-pelican-beta-page.sh for panel load errors
cursoragent Jul 17, 2026
e261196
Fix Pelican log diagnostics for dated laravel-YYYY-MM-DD.log files
cursoragent Jul 17, 2026
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
20 changes: 20 additions & 0 deletions release/RedSyncLauncher/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,25 @@
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="#33a01420" />
</Style>

<Style Selector="TabControl.bw">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="0" />
</Style>
<Style Selector="TabControl.bw /template/ ItemsPresenter#PART_ItemsPresenter">
<Setter Property="Margin" Value="0,0,0,4" />
</Style>
<Style Selector="TabItem">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="11" />
<Setter Property="Foreground" Value="#8a3038" />
<Setter Property="Background" Value="#180608" />
<Setter Property="Padding" Value="14,8" />
<Setter Property="Margin" Value="0,0,6,0" />
</Style>
<Style Selector="TabItem:selected">
<Setter Property="Foreground" Value="#ffe0e0" />
<Setter Property="Background" Value="#3a0c12" />
</Style>
</Application.Styles>
</Application>
3 changes: 2 additions & 1 deletion release/RedSyncLauncher/Build-Launcher-Exe.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ try {
-p:IncludeNativeLibrariesForSelfExtract=true `
-o $out
Copy-Item (Join-Path $out "RedSyncLauncher.exe") $here -Force
Copy-Item (Join-Path $here "servers.json") $here -Force
# servers.json already lives next to the project; no copy needed
Write-Host "Built RedSyncLauncher.exe in $here"
exit 0
} finally {
Pop-Location
}
81 changes: 80 additions & 1 deletion release/RedSyncLauncher/LauncherPaths.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand All @@ -20,6 +22,7 @@ internal static class JsonUtil
internal static class LauncherPaths
{
public const int DefaultPort = 2077;
public const int DefaultMaxPlayers = 2000;
public const string AppName = "RedSync Launcher";

public static string AppRoot
Expand Down Expand Up @@ -93,13 +96,80 @@ public void Save()
}
}

internal sealed class ServerEntry
internal sealed class ServerEntry : INotifyPropertyChanged
{
private int _playersOnline = -1;
private int _maxPlayers = LauncherPaths.DefaultMaxPlayers;
private string _linkState = "…";

public string Name { get; set; } = "";
public string Host { get; set; } = "";
public int Port { get; set; } = LauncherPaths.DefaultPort;
public string Region { get; set; } = "-";
public string Description { get; set; } = "";

/// <summary>Configured capacity (default 2000). Overridden by live /status when available.</summary>
public int MaxPlayers
{
get => _maxPlayers;
set
{
if (_maxPlayers == value) return;
_maxPlayers = value;
OnPropertyChanged();
OnPropertyChanged(nameof(PlayersDisplay));
}
}

/// <summary>Optional status HTTP port. Default = game Port + 2.</summary>
public int? StatusPort { get; set; }

/// <summary>Optional full status URL (overrides Host/StatusPort).</summary>
public string? StatusUrl { get; set; }

[JsonIgnore]
public int PlayersOnline
{
get => _playersOnline;
set
{
if (_playersOnline == value) return;
_playersOnline = value;
OnPropertyChanged();
OnPropertyChanged(nameof(PlayersDisplay));
}
}

[JsonIgnore]
public string LinkState
{
get => _linkState;
set
{
if (_linkState == value) return;
_linkState = value;
OnPropertyChanged();
}
}

[JsonIgnore]
public string PlayersDisplay =>
PlayersOnline < 0 ? "— / " + MaxPlayers : $"{PlayersOnline} / {MaxPlayers}";

[JsonIgnore]
public int ResolvedStatusPort => StatusPort is > 0 ? StatusPort.Value : Port + 2;

public string ResolveStatusUrl()
{
if (!string.IsNullOrWhiteSpace(StatusUrl))
return StatusUrl.Trim();
return $"http://{Host}:{ResolvedStatusPort}/status";
}

public event PropertyChangedEventHandler? PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string? name = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

internal sealed class ServersFile
Expand All @@ -115,7 +185,15 @@ public static List<ServerEntry> Load()
{
var data = JsonSerializer.Deserialize<ServersFile>(File.ReadAllText(path), JsonUtil.Options);
if (data?.Servers is { Count: > 0 })
{
foreach (var s in data.Servers)
{
if (s.MaxPlayers <= 0)
s.MaxPlayers = LauncherPaths.DefaultMaxPlayers;
}

return data.Servers;
}
}
}
catch
Expand All @@ -131,6 +209,7 @@ public static List<ServerEntry> Load()
Host = "88.214.59.166",
Port = LauncherPaths.DefaultPort,
Region = "USA",
MaxPlayers = LauncherPaths.DefaultMaxPlayers,
Description = "Official RedSync co-op server. PvP, events, proximity voice.",
}
};
Expand Down
100 changes: 70 additions & 30 deletions release/RedSyncLauncher/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,41 +94,81 @@
</StackPanel>
</DockPanel>

<!-- Server browser panel -->
<!-- Server browser + players online -->
<Border Background="#b0080305" BorderBrush="#66b01420" BorderThickness="1" Padding="14,12">
<DockPanel>
<DockPanel DockPanel.Dock="Top" Margin="0,0,0,8">
<TextBlock Text="RELAY BROWSER" FontSize="13" FontWeight="Black" LetterSpacing="3"
Foreground="#e02028" />
<TextBlock Text="// OFFICIAL USA NODE LIVE" HorizontalAlignment="Right"
Foreground="#6a2028" FontSize="10" LetterSpacing="1"
VerticalAlignment="Center" />
</DockPanel>
<TextBlock x:Name="DescLabel" DockPanel.Dock="Bottom"
Text="Select a relay. Blackwall interference expected."
Foreground="#7a4048" FontSize="11" Margin="0,10,0,0" TextWrapping="Wrap" />
<DataGrid x:Name="ServerGrid"
AutoGenerateColumns="False"
IsReadOnly="True"
CanUserReorderColumns="False"
CanUserResizeColumns="True"
CanUserSortColumns="False"
GridLinesVisibility="Horizontal"
HeadersVisibility="Column"
SelectionMode="Single"
Background="Transparent"
Foreground="#e8d0d0"
BorderThickness="0"
RowBackground="#22080508"
DoubleTapped="OnServerDoubleTapped"
SelectionChanged="OnServerSelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="RELAY" Binding="{Binding Name}" Width="*" MinWidth="220" />
<DataGridTextColumn Header="ADDRESS" Binding="{Binding Host}" Width="180" />
<DataGridTextColumn Header="PORT" Binding="{Binding Port}" Width="80" />
<DataGridTextColumn Header="REGION" Binding="{Binding Region}" Width="90" />
</DataGrid.Columns>
</DataGrid>
<TabControl x:Name="MainTabs" Classes="bw">
<TabItem Header="RELAYS">
<DockPanel Margin="0,10,0,0">
<DockPanel DockPanel.Dock="Top" Margin="0,0,0,8">
<TextBlock Text="RELAY BROWSER" FontSize="13" FontWeight="Black" LetterSpacing="3"
Foreground="#e02028" />
<TextBlock Text="// OFFICIAL + BETA" HorizontalAlignment="Right"
Foreground="#6a2028" FontSize="10" LetterSpacing="1"
VerticalAlignment="Center" />
</DockPanel>
<DataGrid x:Name="ServerGrid"
AutoGenerateColumns="False"
IsReadOnly="True"
CanUserReorderColumns="False"
CanUserResizeColumns="True"
CanUserSortColumns="False"
GridLinesVisibility="Horizontal"
HeadersVisibility="Column"
SelectionMode="Single"
Background="Transparent"
Foreground="#e8d0d0"
BorderThickness="0"
RowBackground="#22080508"
DoubleTapped="OnServerDoubleTapped"
SelectionChanged="OnServerSelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="RELAY" Binding="{Binding Name}" Width="*" MinWidth="200" />
<DataGridTextColumn Header="ADDRESS" Binding="{Binding Host}" Width="160" />
<DataGridTextColumn Header="PORT" Binding="{Binding Port}" Width="70" />
<DataGridTextColumn Header="PLAYERS" Binding="{Binding PlayersDisplay}" Width="110" />
<DataGridTextColumn Header="REGION" Binding="{Binding Region}" Width="80" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</TabItem>
<TabItem Header="PLAYERS ONLINE">
<DockPanel Margin="0,10,0,0">
<DockPanel DockPanel.Dock="Top" Margin="0,0,0,8">
<TextBlock Text="LIVE HEADCOUNT" FontSize="13" FontWeight="Black" LetterSpacing="3"
Foreground="#e02028" />
<TextBlock x:Name="PlayersPollLabel" Text="// polling…" HorizontalAlignment="Right"
Foreground="#6a2028" FontSize="10" LetterSpacing="1"
VerticalAlignment="Center" />
</DockPanel>
<DataGrid x:Name="PlayersGrid"
AutoGenerateColumns="False"
IsReadOnly="True"
CanUserReorderColumns="False"
CanUserResizeColumns="True"
CanUserSortColumns="False"
GridLinesVisibility="Horizontal"
HeadersVisibility="Column"
SelectionMode="Single"
Background="Transparent"
Foreground="#e8d0d0"
BorderThickness="0"
RowBackground="#22080508"
DoubleTapped="OnServerDoubleTapped"
SelectionChanged="OnPlayersSelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Header="RELAY" Binding="{Binding Name}" Width="*" MinWidth="220" />
<DataGridTextColumn Header="PLAYING" Binding="{Binding PlayersDisplay}" Width="140" />
<DataGridTextColumn Header="LINK" Binding="{Binding LinkState}" Width="110" />
<DataGridTextColumn Header="REGION" Binding="{Binding Region}" Width="90" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</TabItem>
</TabControl>
</DockPanel>
</Border>
</DockPanel>
Expand Down
Loading