diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml
index 9121f86..33efe49 100644
--- a/.github/workflows/nuget-publish.yml
+++ b/.github/workflows/nuget-publish.yml
@@ -1,4 +1,5 @@
on:
+ workflow_dispatch:
push:
tags:
- '*'
diff --git a/.github/workflows/publish-client.yml b/.github/workflows/publish-client.yml
new file mode 100644
index 0000000..8074118
--- /dev/null
+++ b/.github/workflows/publish-client.yml
@@ -0,0 +1,78 @@
+name: publish-client-multi-platform
+
+on:
+ workflow_dispatch:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ build-library:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: '3.1'
+
+ # Lib
+ - name: Build and Pack Library
+ run: |
+ dotnet build Palworld.RESTSharp/Palworld.RESTSharp.csproj --configuration Release
+ dotnet pack Palworld.RESTSharp/Palworld.RESTSharp.csproj --configuration Release --output nupkg
+
+ # add as artifact
+ - name: Upload NuGet Package
+ uses: actions/upload-artifact@v2
+ with:
+ name: nuget-package
+ path: nupkg
+
+ build-windows-client-x64:
+ needs: build-library
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: '8.0' # my pref
+
+ - name: Restore and Build Client Application
+ run: |
+ dotnet restore Palworld.RESTSharp.Client/Palworld.RESTSharp.Client.csproj
+ dotnet publish Palworld.RESTSharp.Client/Palworld.RESTSharp.Client.csproj -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o publish/win-x64
+
+ - name: Upload WinForms Application
+ uses: actions/upload-artifact@v2
+ with:
+ name: windows-client
+ path: publish/win-x64
+
+ build-windows-client-x32:
+ needs: build-library
+ runs-on: windows-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Setup .NET Core
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: '8.0' # my pref
+
+ - name: Restore and Build Client Application
+ run: |
+ dotnet restore Palworld.RESTSharp.Client/Palworld.RESTSharp.Client.csproj
+ dotnet publish Palworld.RESTSharp.Client/Palworld.RESTSharp.Client.csproj -c Release -r win-x86 --self-contained true -p:PublishSingleFile=true -o publish/win-x86
+
+ - name: Upload WinForms Application
+ uses: actions/upload-artifact@v2
+ with:
+ name: windows-client
+ path: publish/win-x64
\ No newline at end of file
diff --git a/LICENSE.txt b/LICENSE.txt
index 8aa2645..c74e89c 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) [year] [fullname]
+Copyright (c) 2024 BalphagoreVR
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/Palworld.RESTSharp.Client/FormMain.Designer.cs b/Palworld.RESTSharp.Client/FormMain.Designer.cs
index 285862a..bbe4008 100644
--- a/Palworld.RESTSharp.Client/FormMain.Designer.cs
+++ b/Palworld.RESTSharp.Client/FormMain.Designer.cs
@@ -32,15 +32,18 @@ private void InitializeComponent()
panelResponse = new Panel();
statusStrip1 = new StatusStrip();
connectionStatus = new ToolStripStatusLabel();
+ stsPlayerCount = new ToolStripStatusLabel();
+ stsServerUptimeAndFPS = new ToolStripStatusLabel();
tAPIOptions = new TreeView();
label1 = new Label();
btnExecute = new Button();
pageConfigure = new Panel();
+ txtConfigPassword = new TextBox();
+ cbTrackMetrics = new CheckBox();
label4 = new Label();
txtconfigURL = new TextBox();
btnSaveConfig = new Button();
label3 = new Label();
- txtConfigPassword = new TextBox();
panelRequestParameters = new Panel();
lblHeader = new Label();
statusStrip1.SuspendLayout();
@@ -57,7 +60,8 @@ private void InitializeComponent()
//
// statusStrip1
//
- statusStrip1.Items.AddRange(new ToolStripItem[] { connectionStatus });
+ statusStrip1.GripStyle = ToolStripGripStyle.Visible;
+ statusStrip1.Items.AddRange(new ToolStripItem[] { connectionStatus, stsPlayerCount, stsServerUptimeAndFPS });
statusStrip1.Location = new Point(0, 376);
statusStrip1.Name = "statusStrip1";
statusStrip1.Size = new Size(992, 22);
@@ -70,6 +74,17 @@ private void InitializeComponent()
connectionStatus.Size = new Size(97, 17);
connectionStatus.Text = "Not Connected...";
//
+ // stsPlayerCount
+ //
+ stsPlayerCount.Name = "stsPlayerCount";
+ stsPlayerCount.Size = new Size(0, 17);
+ stsPlayerCount.TextAlign = ContentAlignment.MiddleRight;
+ //
+ // stsServerUptimeAndFPS
+ //
+ stsServerUptimeAndFPS.Name = "stsServerUptimeAndFPS";
+ stsServerUptimeAndFPS.Size = new Size(0, 17);
+ //
// tAPIOptions
//
tAPIOptions.Dock = DockStyle.Left;
@@ -100,17 +115,37 @@ private void InitializeComponent()
//
// pageConfigure
//
+ pageConfigure.Controls.Add(txtConfigPassword);
+ pageConfigure.Controls.Add(cbTrackMetrics);
pageConfigure.Controls.Add(label4);
pageConfigure.Controls.Add(txtconfigURL);
pageConfigure.Controls.Add(btnSaveConfig);
pageConfigure.Controls.Add(label3);
- pageConfigure.Controls.Add(txtConfigPassword);
pageConfigure.Location = new Point(222, 0);
pageConfigure.Name = "pageConfigure";
pageConfigure.Size = new Size(770, 376);
pageConfigure.TabIndex = 7;
pageConfigure.Paint += pageConfigure_Paint;
//
+ // txtConfigPassword
+ //
+ txtConfigPassword.Location = new Point(68, 38);
+ txtConfigPassword.Name = "txtConfigPassword";
+ txtConfigPassword.PasswordChar = '*';
+ txtConfigPassword.Size = new Size(683, 23);
+ txtConfigPassword.TabIndex = 12;
+ //
+ // cbTrackMetrics
+ //
+ cbTrackMetrics.AutoSize = true;
+ cbTrackMetrics.Location = new Point(7, 66);
+ cbTrackMetrics.Name = "cbTrackMetrics";
+ cbTrackMetrics.Size = new Size(132, 19);
+ cbTrackMetrics.TabIndex = 11;
+ cbTrackMetrics.Text = "Show Server Metrics";
+ cbTrackMetrics.UseVisualStyleBackColor = true;
+ cbTrackMetrics.CheckedChanged += cbTrackMetrics_CheckedChanged;
+ //
// label4
//
label4.AutoSize = true;
@@ -124,12 +159,13 @@ private void InitializeComponent()
//
txtconfigURL.Location = new Point(68, 8);
txtconfigURL.Name = "txtconfigURL";
+ txtconfigURL.PlaceholderText = "http://127.0.0.1:8000";
txtconfigURL.Size = new Size(683, 23);
txtconfigURL.TabIndex = 9;
//
// btnSaveConfig
//
- btnSaveConfig.Location = new Point(5, 66);
+ btnSaveConfig.Location = new Point(5, 89);
btnSaveConfig.Name = "btnSaveConfig";
btnSaveConfig.Size = new Size(112, 23);
btnSaveConfig.TabIndex = 8;
@@ -146,13 +182,6 @@ private void InitializeComponent()
label3.TabIndex = 1;
label3.Text = "Password";
//
- // txtConfigPassword
- //
- txtConfigPassword.Location = new Point(68, 37);
- txtConfigPassword.Name = "txtConfigPassword";
- txtConfigPassword.Size = new Size(683, 23);
- txtConfigPassword.TabIndex = 0;
- //
// panelRequestParameters
//
panelRequestParameters.BorderStyle = BorderStyle.Fixed3D;
@@ -186,7 +215,7 @@ private void InitializeComponent()
Controls.Add(panelResponse);
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "FormMain";
- Text = "Palworld REST API Test Client";
+ Text = "Palworld RESTSharp Client";
Load += Form1_Load;
statusStrip1.ResumeLayout(false);
statusStrip1.PerformLayout();
@@ -206,11 +235,14 @@ private void InitializeComponent()
private Button btnExecute;
private Panel pageConfigure;
private Label label3;
- private TextBox txtConfigPassword;
private Label label4;
private TextBox txtconfigURL;
private Button btnSaveConfig;
private Panel panelRequestParameters;
private Label lblHeader;
+ private ToolStripStatusLabel stsPlayerCount;
+ private ToolStripStatusLabel stsServerUptimeAndFPS;
+ private CheckBox cbTrackMetrics;
+ private TextBox txtConfigPassword;
}
}
diff --git a/Palworld.RESTSharp.Client/FormMain.cs b/Palworld.RESTSharp.Client/FormMain.cs
index cb994f9..c607dba 100644
--- a/Palworld.RESTSharp.Client/FormMain.cs
+++ b/Palworld.RESTSharp.Client/FormMain.cs
@@ -203,7 +203,7 @@ private void tAPIOptions_AfterSelectAsync(object sender, TreeViewEventArgs e)
txtReasonMessage = new TextBox();
lblReason = new Label() { Text = "Shutdown Message" };
Label lblDelay = new Label() { Text = "Delay (Seconds)" };
-
+
txtReasonMessage.Dock = DockStyle.Top;
txtReasonMessage.PlaceholderText = "Enter reason for shutdown";
panelRequestParameters.Controls.Add(txtReasonMessage);
@@ -278,8 +278,10 @@ private async void btnSaveConfig_Click(object sender, EventArgs e)
this.Text = _defaultTitle;
_connected = true;
this.Text = _defaultTitle + $" - {serverInfo.serverName}";
+
+ UpdateServerMetricCounterAsync();
}
- else
+ else // Disconnected
{
txtconfigURL.ReadOnly = false;
txtConfigPassword.ReadOnly = false;
@@ -290,14 +292,31 @@ private async void btnSaveConfig_Click(object sender, EventArgs e)
this.Text = _defaultTitle;
}
}
- catch(PalworldRESTSharpClientUnauthorizedException pex)
+ catch (PalworldRESTSharpClientUnauthorizedException pex)
{
MessageBox.Show(pex.Message, "Invalid Password");
}
- catch(Exception ex)
+ catch (Exception ex)
{
- MessageBox.Show(ex.Message,"Error connecting");
+ MessageBox.Show(ex.Message, "Error connecting");
+ }
+ }
+
+ private async Task UpdateServerMetricCounterAsync()
+ {
+ while (_connected && cbTrackMetrics.Checked)
+ {
+ ServerMetric serverMetric = await palworldRESTAPIClient.GetServerMetricsASync();
+ if (serverMetric != null)
+ {
+ stsPlayerCount.Text = $"Players: {serverMetric.totalPlayers}/{serverMetric.maxPlayers}";
+ stsServerUptimeAndFPS.Text = $"Uptime: {serverMetric.GetUptimeString()} | FPS: {serverMetric.serverFPS}";
+ }
+ await Task.Delay(1000);
}
+
+ stsPlayerCount.Text = "";
+ stsServerUptimeAndFPS.Text = "";
}
private async void Execute()
@@ -370,6 +389,9 @@ private async void Execute()
lbServerMetrics.Items.Add($"Frame Rate: {serverMetric.serverFrameRate}");
lbServerMetrics.Items.Add($"Max Players: {serverMetric.maxPlayers}");
lbServerMetrics.Items.Add($"Uptime: {serverMetric.upTime}");
+
+ stsPlayerCount.Text = $"Players: {serverMetric.totalPlayers}/{serverMetric.maxPlayers}";
+ stsServerUptimeAndFPS.Text = $"Uptime: {serverMetric.GetUptimeString()} | FPS: {serverMetric.serverFPS}";
panelResponse.Controls.Add(lbServerMetrics);
}
@@ -511,7 +533,7 @@ private async void Execute()
break;
}
}
- catch(Exception ex)
+ catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\n\nException:\n{ex.StackTrace}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
@@ -523,5 +545,19 @@ private async void btnExecute_Click(object sender, EventArgs e)
connectionStatus.Text = "Executed";
}
+
+ private void cbTrackMetrics_CheckedChanged(object sender, EventArgs e)
+ {
+ if (cbTrackMetrics.Checked)
+ {
+ // Show user a warning and prompt to continue or cancel.
+ DialogResult result = MessageBox.Show("Tracking server metrics will periodically poll the REST API resulting in excessive log spam in the server console. Do you want to continue?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
+
+ if (result == DialogResult.No)
+ {
+ cbTrackMetrics.Checked = false;
+ }
+ }
+ }
}
}
diff --git a/Palworld.RESTSharp.Client/FormMain.resx b/Palworld.RESTSharp.Client/FormMain.resx
index 2b28b88..78420fc 100644
--- a/Palworld.RESTSharp.Client/FormMain.resx
+++ b/Palworld.RESTSharp.Client/FormMain.resx
@@ -120,6 +120,9 @@
17, 17
+
+ True
+
diff --git a/Palworld.RESTSharp.sln b/Palworld.RESTSharp.sln
index facf02d..aed41fb 100644
--- a/Palworld.RESTSharp.sln
+++ b/Palworld.RESTSharp.sln
@@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Palworld.RESTSharp.Client",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{541EFF06-8B59-48BB-8C93-7B8DC7DA4089}"
ProjectSection(SolutionItems) = preProject
+ LICENSE.txt = LICENSE.txt
.github\workflows\nuget-publish.yml = .github\workflows\nuget-publish.yml
+ .github\workflows\publish-client.yml = .github\workflows\publish-client.yml
README.md = README.md
RestSharpLogo-128.png = RestSharpLogo-128.png
RestSharpLogo-32.png = RestSharpLogo-32.png
diff --git a/Palworld.RESTSharp/Models/ServerInfo.cs b/Palworld.RESTSharp/Models/ServerInfo.cs
index 04a2ea1..b092473 100644
--- a/Palworld.RESTSharp/Models/ServerInfo.cs
+++ b/Palworld.RESTSharp/Models/ServerInfo.cs
@@ -23,7 +23,10 @@ public class ServerInfo
[JsonProperty("description")]
public string description { get; set; }
-
+ ///
+ /// Returns the string representation of the server info.
+ ///
+ /// Server name, version, and description in a single line.
public override string ToString() => $"[{serverName}][{version}][{description}]";
}
}
diff --git a/Palworld.RESTSharp/Models/ServerMetric.cs b/Palworld.RESTSharp/Models/ServerMetric.cs
index 413e09e..ff988ad 100644
--- a/Palworld.RESTSharp/Models/ServerMetric.cs
+++ b/Palworld.RESTSharp/Models/ServerMetric.cs
@@ -33,12 +33,17 @@ public class ServerMetric
[JsonProperty("uptime")]
public int upTime { get; set; }
+ ///
+ /// Gets the uptime of the server expressed in hours, minutes, and seconds.
+ ///
+ ///
public string GetUptimeString()
{
+ int days = upTime / 86400;
int hours = upTime / 3600;
int minutes = (upTime % 3600) / 60;
int seconds = upTime % 60;
- return $"{hours}h {minutes}m {seconds}s";
+ return $"{days}d {hours}h {minutes}m {seconds}s";
}
}
}