2023-08-01 15:08:31 +00:00
|
|
|
|
using Newtonsoft.Json;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
using PSLauncher.Properties;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.IO;
|
2023-08-01 15:08:31 +00:00
|
|
|
|
using System.Net.Http;
|
|
|
|
|
|
using System.Net.Http.Json;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
using System.Text;
|
2015-08-14 22:21:04 +00:00
|
|
|
|
using System.Threading.Tasks;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
|
|
|
|
|
|
namespace PSLauncher
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
public enum LaunchDomain
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
Live,
|
2023-08-01 15:08:31 +00:00
|
|
|
|
PSForever,
|
|
|
|
|
|
Dev,
|
|
|
|
|
|
DevSSL
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-14 22:21:04 +00:00
|
|
|
|
public enum GameState
|
|
|
|
|
|
{
|
|
|
|
|
|
Stopped,
|
2023-08-01 15:08:31 +00:00
|
|
|
|
Authenticating,
|
|
|
|
|
|
Validating,
|
2015-08-14 22:21:04 +00:00
|
|
|
|
Launching,
|
2016-06-19 20:02:10 +00:00
|
|
|
|
Running,
|
|
|
|
|
|
Stopping
|
2015-08-14 22:21:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
public partial class LauncherForm : Form
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
private HttpClient httpClient;
|
|
|
|
|
|
private Process psProcess;
|
2016-06-19 20:02:10 +00:00
|
|
|
|
|
2015-10-02 23:05:34 +00:00
|
|
|
|
bool bGameRunning = false;
|
2023-08-01 15:08:31 +00:00
|
|
|
|
int DEFAULT_WEB_TIMEOUT = 5;
|
2015-08-14 22:21:04 +00:00
|
|
|
|
GameState gameState = GameState.Stopped;
|
2023-08-01 15:08:31 +00:00
|
|
|
|
LaunchDomain domain = LaunchDomain.PSForever;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
System.Drawing.Size oldSize = new System.Drawing.Size(0, 0);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
|
|
|
|
|
Dictionary<LaunchDomain, string> domains = new Dictionary<LaunchDomain, string>()
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
{ LaunchDomain.Live, "https://lpj.daybreakgames.com/ps/live/" },
|
|
|
|
|
|
{ LaunchDomain.PSForever, "https://login.psforever.net/psf/live/" },
|
|
|
|
|
|
{ LaunchDomain.Dev, "http://localhost:9001/psf/live/" },
|
|
|
|
|
|
{ LaunchDomain.DevSSL, "http://localhost:9001/psf/live/" }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Dictionary<LaunchDomain, string> userAgents = new Dictionary<LaunchDomain, string>()
|
|
|
|
|
|
{
|
|
|
|
|
|
{ LaunchDomain.Live, "Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0" },
|
|
|
|
|
|
{ LaunchDomain.PSForever, string.Format("PSF Launcher v{0}", Program.launcherVersion) },
|
|
|
|
|
|
{ LaunchDomain.Dev, string.Format("PSF Launcher v{0}", Program.launcherVersion) },
|
|
|
|
|
|
{ LaunchDomain.DevSSL, string.Format("PSF Launcher v{0}", Program.launcherVersion) }
|
2015-08-14 17:18:12 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public LauncherForm()
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
//
|
|
|
|
|
|
// init form components
|
|
|
|
|
|
//
|
2015-08-14 17:18:12 +00:00
|
|
|
|
InitializeComponent();
|
2016-06-20 07:04:50 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
//
|
|
|
|
|
|
// init http client
|
|
|
|
|
|
//
|
2023-08-01 22:30:17 +00:00
|
|
|
|
httpClient = new HttpClient
|
2023-08-01 15:08:31 +00:00
|
|
|
|
{
|
|
|
|
|
|
BaseAddress = new Uri(domains[domain]),
|
|
|
|
|
|
Timeout = TimeSpan.FromSeconds(DEFAULT_WEB_TIMEOUT)
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
httpClient.DefaultRequestHeaders.Clear();
|
|
|
|
|
|
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(userAgents[domain]);
|
|
|
|
|
|
httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/json");
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// set form icon
|
|
|
|
|
|
//
|
2016-06-20 07:04:50 +00:00
|
|
|
|
this.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath);
|
|
|
|
|
|
|
2016-06-20 05:45:40 +00:00
|
|
|
|
#if DEBUG
|
2023-08-01 15:08:31 +00:00
|
|
|
|
//Settings.Default.Reset();
|
2016-06-20 05:45:40 +00:00
|
|
|
|
Console.SetOut(new Util.ControlWriter(this.ps_consoleOutput));
|
|
|
|
|
|
#endif
|
2017-03-19 19:58:15 +00:00
|
|
|
|
skipLauncher.Checked = Settings.Default.SkipLauncher;
|
2016-06-19 20:02:10 +00:00
|
|
|
|
|
2017-03-19 19:46:03 +00:00
|
|
|
|
// Load server
|
|
|
|
|
|
loadServerSelection();
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure selection is valid
|
|
|
|
|
|
if(Settings.Default.ServerSelection >= -1 && Settings.Default.ServerSelection < serverSelection.Items.Count)
|
|
|
|
|
|
serverSelection.SelectedIndex = Settings.Default.ServerSelection;
|
|
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
string psDefault = Util.getDefaultPlanetSideDirectory();
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
|
|
|
|
|
// first run with no settings or invalid starting path
|
2016-06-19 20:49:51 +00:00
|
|
|
|
if (Settings.Default.PSPath == "" || !Util.checkDirForPlanetSide(Settings.Default.PSPath))
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
Settings.Default.PSPath = psDefault;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
setConsoleWindowState(Settings.Default.OutputShown);
|
2015-10-02 23:05:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LauncherForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (this.bGameRunning && Settings.Default.OutputShown)
|
2015-10-02 23:05:34 +00:00
|
|
|
|
{
|
|
|
|
|
|
DialogResult res = MessageBox.Show( "Are you sure you want to exit while managing PlanetSide PID " + psProcess.Id + "?" +
|
|
|
|
|
|
Environment.NewLine + "You won't see any debugging output if you do.", "Confirm exit", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
|
|
|
|
|
|
|
|
|
|
|
if (res == DialogResult.No)
|
|
|
|
|
|
e.Cancel = true;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void stopLaunching()
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
setButtonState(GameState.Stopped);
|
|
|
|
|
|
progressShown(false);
|
2015-08-14 22:21:04 +00:00
|
|
|
|
|
|
|
|
|
|
gameState = GameState.Stopped;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
private void startAuthenticating()
|
|
|
|
|
|
{
|
|
|
|
|
|
setButtonState(GameState.Authenticating);
|
|
|
|
|
|
progressShown(true);
|
|
|
|
|
|
|
|
|
|
|
|
gameState = GameState.Authenticating;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
private void startLaunching()
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
setButtonState(GameState.Launching);
|
|
|
|
|
|
progressShown(true);
|
2015-08-14 22:21:04 +00:00
|
|
|
|
|
|
|
|
|
|
gameState = GameState.Launching;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
private void setButtonState(GameState state)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
this.SafeInvoke(a =>
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
switch (state)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case GameState.Stopped:
|
|
|
|
|
|
this.launchGame.BackColor = System.Drawing.Color.FromArgb(128, 255, 128);
|
|
|
|
|
|
this.launchGame.Enabled = true;
|
|
|
|
|
|
this.launchGame.Text = "Launch";
|
|
|
|
|
|
|
|
|
|
|
|
// allow modification if launcher is not skipped
|
|
|
|
|
|
if (!skipLauncher.Checked)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.username.Enabled = true;
|
|
|
|
|
|
this.password.Enabled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case GameState.Authenticating:
|
|
|
|
|
|
this.launchGame.BackColor = System.Drawing.Color.FromArgb(128, 128, 255);
|
|
|
|
|
|
this.launchGame.Enabled = false;
|
|
|
|
|
|
this.launchGame.Text = "Authenticating";
|
|
|
|
|
|
|
|
|
|
|
|
// disallow modification because we are launching
|
|
|
|
|
|
this.username.Enabled = false;
|
|
|
|
|
|
this.password.Enabled = false;
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case GameState.Validating:
|
|
|
|
|
|
this.launchGame.BackColor = System.Drawing.Color.FromArgb(128, 128, 255);
|
|
|
|
|
|
this.launchGame.Enabled = false;
|
|
|
|
|
|
this.launchGame.Text = "Validating";
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
case GameState.Launching:
|
|
|
|
|
|
this.launchGame.Enabled = false;
|
2023-08-01 15:08:31 +00:00
|
|
|
|
this.launchGame.Text = "Launching";
|
2016-06-19 20:02:10 +00:00
|
|
|
|
break;
|
2023-08-01 15:08:31 +00:00
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
case GameState.Running:
|
|
|
|
|
|
this.launchGame.BackColor = System.Drawing.Color.FromArgb(255, 128, 128);
|
|
|
|
|
|
this.launchGame.Enabled = true;
|
|
|
|
|
|
this.launchGame.Text = "Kill";
|
|
|
|
|
|
break;
|
2023-08-01 15:08:31 +00:00
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
case GameState.Stopping:
|
|
|
|
|
|
this.launchGame.Enabled = false;
|
|
|
|
|
|
this.launchGame.Text = "Killing...";
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
private void setButtonValidationState(int counter, int fileCount)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.SafeInvoke(a =>
|
|
|
|
|
|
{
|
|
|
|
|
|
this.launchGame.Text = string.Format("Validating {0}/{1}", counter, fileCount);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
private void setErrorMessage(string error)
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
this.SafeInvoke(a =>
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (error == "")
|
|
|
|
|
|
{
|
|
|
|
|
|
this.launchMessage.Visible = false;
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.launchMessage.Visible = true;
|
|
|
|
|
|
this.launchMessage.Text = error;
|
2016-06-19 20:02:10 +00:00
|
|
|
|
});
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
private void launchGame_Click(object sender, EventArgs e)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
if(gameState == GameState.Running) // kill command
|
|
|
|
|
|
{
|
|
|
|
|
|
psProcess.Kill();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2016-06-21 22:35:52 +00:00
|
|
|
|
setErrorMessage("");
|
|
|
|
|
|
|
|
|
|
|
|
if (Settings.Default.ClearOutputOnLaunch)
|
2016-06-19 20:02:10 +00:00
|
|
|
|
{
|
|
|
|
|
|
this.ps_consoleOutput.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string path = Settings.Default.PSPath;
|
|
|
|
|
|
string psExe = Path.Combine(path, SettingsForm.PS_EXE_NAME);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
|
|
|
|
|
if (!skipLauncher.Checked && (username.Text == String.Empty || password.Text == String.Empty))
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Username or password blank");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
if (!Util.checkDirForPlanetSide(path))
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2016-06-20 05:45:40 +00:00
|
|
|
|
setErrorMessage("Invalid " + SettingsForm.PS_EXE_NAME);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-03-19 19:46:03 +00:00
|
|
|
|
// Build arguments
|
|
|
|
|
|
List<string> arguments = new List<string>();
|
|
|
|
|
|
|
|
|
|
|
|
if (Settings.Default.CoreCombat)
|
|
|
|
|
|
arguments.Add("/CC");
|
|
|
|
|
|
|
|
|
|
|
|
if (Settings.Default.ExtraArgs != "")
|
|
|
|
|
|
arguments.Add(Settings.Default.ExtraArgs);
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
WriteClientINI();
|
|
|
|
|
|
|
|
|
|
|
|
if (skipLauncher.Checked)
|
2017-03-19 19:46:03 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
arguments.Add("/K:StagingTest");
|
|
|
|
|
|
|
|
|
|
|
|
LaunchStaging();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2023-08-02 19:25:33 +00:00
|
|
|
|
Launch(arguments);
|
2023-08-01 15:08:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// functions used only in this function
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
void WriteClientINI()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Rewrite client.ini if selected
|
|
|
|
|
|
if (!Settings.Default.GenerateClientINI) return;
|
|
|
|
|
|
|
2017-03-19 19:46:03 +00:00
|
|
|
|
string inipath = Path.Combine(Path.GetDirectoryName(psExe), "client.ini");
|
|
|
|
|
|
ClientINI ini = new ClientINI(inipath);
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
ini.writeEntries(Util.LoadServerList(), serverSelection.SelectedIndex);
|
|
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
catch (IOException exp)
|
2017-03-19 19:46:03 +00:00
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Failed to write INI file");
|
|
|
|
|
|
addLine(String.Format("ClientINI: error - '{0}' ({1})", exp.Message, inipath));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
void LaunchStaging()
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
// magic string to login to planetside from the actual game
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (!startPlanetSide(psExe, Path.GetDirectoryName(psExe), String.Join(" ", arguments)))
|
2016-06-21 22:35:52 +00:00
|
|
|
|
{
|
|
|
|
|
|
gameStopped();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
gameRunning();
|
|
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-02 19:25:33 +00:00
|
|
|
|
void Launch(List<string> _arguments)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
startLaunching();
|
2017-03-19 19:58:15 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
|
{
|
2023-08-02 19:25:33 +00:00
|
|
|
|
if (!this.doLogin(_arguments))
|
2016-06-21 22:35:52 +00:00
|
|
|
|
{
|
|
|
|
|
|
gameStopped();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
gameRunning();
|
|
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
});
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class DefaultResponse
|
2015-10-23 05:28:27 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
public int Status { get; set; }
|
|
|
|
|
|
};
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class ErrorResponse : DefaultResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
//[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
|
|
|
|
|
public string ErrorText { get; set; }
|
2015-10-23 05:28:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class VersionResponse : DefaultResponse
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
public Int64 ReleaseDate { get; set; }
|
|
|
|
|
|
public string VersionString { get; set; }
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class TokenResponse : DefaultResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
public string Token { get; set; }
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class ValidationResponse : DefaultResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
public string[] Files { get; set; }
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class GameTokenResponse : DefaultResponse
|
|
|
|
|
|
{
|
|
|
|
|
|
public string GameToken { get; set; }
|
|
|
|
|
|
}
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class LoginRequestBody
|
|
|
|
|
|
{
|
|
|
|
|
|
public string Username { get; set; }
|
|
|
|
|
|
public string Password { get; set; }
|
|
|
|
|
|
public string Launcher { get; set; }
|
|
|
|
|
|
public int Mode { get; set; }
|
|
|
|
|
|
}
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
class ValidateRequestBody
|
|
|
|
|
|
{
|
|
|
|
|
|
public string Launcher { get; set; }
|
|
|
|
|
|
public string Files { get; set; }
|
|
|
|
|
|
}
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
void handleErrorResponse(ref string _errorBody)
|
|
|
|
|
|
{
|
|
|
|
|
|
var errorResponse = JsonConvert.DeserializeObject<ErrorResponse>(_errorBody);
|
|
|
|
|
|
string errorMessage;
|
|
|
|
|
|
addLine("=====");
|
|
|
|
|
|
addLine("The launcher received an error:");
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
switch(errorResponse.Status)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 100:
|
|
|
|
|
|
errorMessage = "Launcher Update required.";
|
|
|
|
|
|
break;
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 101:
|
|
|
|
|
|
errorMessage = "Launcher is corrupted, please download the latest PSF Launcher.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 102:
|
|
|
|
|
|
errorMessage = "Launcher token expired, please retry.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 103:
|
|
|
|
|
|
errorMessage = "Gamefiles are corrupted, please replace them.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 104:
|
|
|
|
|
|
errorMessage = "Launcher is no longer supported, please download the latest PSF Launcher.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 200:
|
|
|
|
|
|
errorMessage = "This account does not yet support Launcher login, please sign in via \"Skip Launcher\" once.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 201:
|
|
|
|
|
|
errorMessage = "Wrong Username or Password.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 202:
|
|
|
|
|
|
errorMessage = "This account is inactive, please contact the PSF Support on Discord.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
case 300:
|
|
|
|
|
|
errorMessage = "There has been a database error, please try again later.";
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
default:
|
2023-08-02 19:25:33 +00:00
|
|
|
|
errorMessage = "Please report this error to the PSF Support on Discord\nError: " + errorResponse.Status;
|
2023-08-01 15:08:31 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
// print the launcher message
|
|
|
|
|
|
addLine(errorMessage);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
// print the message from the error response
|
|
|
|
|
|
if ( errorResponse.ErrorText.Length != 0 )
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine(errorResponse.ErrorText);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("=====");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void checkLauncherVersion()
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Checking for new PSF Launcher version...");
|
|
|
|
|
|
|
|
|
|
|
|
HttpResponseMessage respVersion;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
respVersion = httpClient.GetAsync("version").Result;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
catch
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("Error: Version GET did not return");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (!respVersion.IsSuccessStatusCode)
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Error: Version GET status " + respVersion.StatusCode);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
var result = respVersion.Content.ReadAsStringAsync().Result;
|
2023-08-02 19:25:33 +00:00
|
|
|
|
var versionResponse = JsonConvert.DeserializeObject<VersionResponse>(result);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (versionResponse.Status != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
handleErrorResponse(ref result);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var newestVersion = new List<string>(versionResponse.VersionString.Split('.'));
|
|
|
|
|
|
var localVersion = new List<string>(Program.launcherVersion.Split('.'));
|
|
|
|
|
|
|
|
|
|
|
|
if ( newestVersion.Count != localVersion.Count )
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("=====");
|
|
|
|
|
|
addLine("Could not compare launcher versions. Launching may fail.");
|
2023-08-02 19:25:33 +00:00
|
|
|
|
addLine(string.Format("Local version: v{0} - latest version: v{1}", localVersion, newestVersion));
|
|
|
|
|
|
addLine("Please update if there is a newer version of PSF Launcher.");
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("=====");
|
|
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool newerVersionAvailable = false;
|
|
|
|
|
|
for (int i = 0; i < newestVersion.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nv = int.Parse(newestVersion[i]);
|
|
|
|
|
|
var lv = int.Parse(localVersion[i]);
|
|
|
|
|
|
|
|
|
|
|
|
if (lv < nv)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
newerVersionAvailable = true;
|
|
|
|
|
|
break;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if ( newerVersionAvailable )
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
DateTime parsedTime = Util.UnixTimestampToDateTime(versionResponse.ReleaseDate);
|
2016-06-21 22:35:52 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("There is a newer version of the PSF Launcher. Launching may fail.");
|
|
|
|
|
|
|
|
|
|
|
|
addLine(
|
|
|
|
|
|
string.Format(
|
|
|
|
|
|
"Version information: v{0} released {1}",
|
|
|
|
|
|
versionResponse.VersionString,
|
|
|
|
|
|
parsedTime.ToLocalTime().ToLongDateString()
|
|
|
|
|
|
)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
addLine("=====");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("PSF Launcher is on the latest version.");
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("");
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
bool sendLoginData()
|
|
|
|
|
|
{
|
|
|
|
|
|
var username = this.username.Text;
|
|
|
|
|
|
var password = this.password.Text;
|
|
|
|
|
|
var passwordHash = Util.CalculateStringHash(EHashingAlgoType.SHA256, username + password);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
var loginRequestBody = new LoginRequestBody
|
|
|
|
|
|
{
|
|
|
|
|
|
Username = this.username.Text,
|
|
|
|
|
|
Password = passwordHash,
|
|
|
|
|
|
Launcher = Program.launcherHash,
|
|
|
|
|
|
Mode = 0
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
HttpResponseMessage respLogin;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
respLogin = httpClient.PostAsJsonAsync("login", loginRequestBody).Result;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Error: Login POST did not return");
|
|
|
|
|
|
addLine(e.InnerException.Message);
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
|
|
|
|
|
|
if (!respLogin.IsSuccessStatusCode)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("Error: Login GET status " + respLogin.StatusCode);
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
var result = respLogin.Content.ReadAsStringAsync().Result;
|
2023-08-02 19:25:33 +00:00
|
|
|
|
var loginResponse = JsonConvert.DeserializeObject<TokenResponse>(result);
|
2023-08-01 15:08:31 +00:00
|
|
|
|
|
|
|
|
|
|
if (loginResponse.Status != 0)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
handleErrorResponse(ref result);
|
2016-06-21 22:35:52 +00:00
|
|
|
|
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", loginResponse.Token);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
bool getFilesToValidate(ref List<string> _filesToValidate)
|
|
|
|
|
|
{
|
|
|
|
|
|
HttpResponseMessage respValidateGet;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
respValidateGet = httpClient.GetAsync("validate").Result;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
catch (Exception e)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("Error: Validate GET did not return");
|
|
|
|
|
|
addLine(e.Message);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (!respValidateGet.IsSuccessStatusCode)
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Error: Validate GET status " + respValidateGet.StatusCode);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
var result = respValidateGet.Content.ReadAsStringAsync().Result;
|
2023-08-02 19:25:33 +00:00
|
|
|
|
var validateGetResponse = JsonConvert.DeserializeObject<ValidationResponse>(result);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (validateGetResponse.Status != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
handleErrorResponse(ref result);
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_filesToValidate.AddRange(validateGetResponse.Files);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool validateFiles(List<string>_filesToValidate, ref string _fileHashResult)
|
|
|
|
|
|
{
|
|
|
|
|
|
string basePath = Settings.Default.PSPath;
|
|
|
|
|
|
List<string> fileHashes = new List<string>();
|
|
|
|
|
|
|
|
|
|
|
|
for (int index = 0; index < _filesToValidate.Count; index++)
|
|
|
|
|
|
{
|
|
|
|
|
|
setButtonValidationState(index + 1, _filesToValidate.Count);
|
|
|
|
|
|
|
|
|
|
|
|
string filePath = _filesToValidate[index];
|
|
|
|
|
|
|
|
|
|
|
|
// get absolute path
|
|
|
|
|
|
var absPath = Path.GetFullPath(Path.Combine(basePath, filePath));
|
|
|
|
|
|
|
|
|
|
|
|
// make sure path is within planetside directory
|
|
|
|
|
|
if (!absPath.StartsWith(basePath))
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("Error: Filepath for validation is outside of planetside directory");
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
FileStream fileHandle;
|
|
|
|
|
|
try
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
fileHandle = File.OpenRead(absPath);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
catch
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("Error: Required file not found: " + filePath);
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
fileHashes.Add(Util.CalculateFileHash(fileHandle));
|
2016-06-21 22:35:52 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
fileHandle.Close();
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
_fileHashResult = Util.CalculateStringHash(string.Join("", fileHashes));
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool sendValidationResult(string _hashResult)
|
|
|
|
|
|
{
|
|
|
|
|
|
var validateResponseBody = new ValidateRequestBody
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
Launcher = Program.launcherHash,
|
|
|
|
|
|
Files = _hashResult
|
|
|
|
|
|
};
|
2016-06-21 22:35:52 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
HttpResponseMessage respValidatePost;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
respValidatePost = httpClient.PostAsJsonAsync("validate", validateResponseBody).Result;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Error: Validate POST did not return");
|
2016-06-21 22:35:52 +00:00
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (!respValidatePost.IsSuccessStatusCode)
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Error: Validate POST status " + respValidatePost.StatusCode);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
var result = respValidatePost.Content.ReadAsStringAsync().Result;
|
2023-08-02 19:25:33 +00:00
|
|
|
|
var validatePostResponse = JsonConvert.DeserializeObject<TokenResponse>(result);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
if (validatePostResponse.Status != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
handleErrorResponse(ref result);
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// update to validated token
|
|
|
|
|
|
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", validatePostResponse.Token);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
bool getGameToken(ref string _gameToken)
|
|
|
|
|
|
{
|
|
|
|
|
|
HttpResponseMessage respGameToken;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
respGameToken = httpClient.GetAsync("gametoken").Result;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Error: GameToken GET did not return");
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
2023-08-01 15:08:31 +00:00
|
|
|
|
|
|
|
|
|
|
if (!respGameToken.IsSuccessStatusCode)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine("Error: GameToken GET status " + respGameToken.StatusCode);
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
var result = respGameToken.Content.ReadAsStringAsync().Result;
|
2023-08-02 19:25:33 +00:00
|
|
|
|
var gameTokenResponse = JsonConvert.DeserializeObject<GameTokenResponse>(result);
|
2023-08-01 15:08:31 +00:00
|
|
|
|
|
|
|
|
|
|
if (gameTokenResponse.Status != 0)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2023-08-01 15:08:31 +00:00
|
|
|
|
handleErrorResponse(ref result);
|
2016-06-21 22:35:52 +00:00
|
|
|
|
|
|
|
|
|
|
return false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
_gameToken = gameTokenResponse.GameToken;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-02 19:25:33 +00:00
|
|
|
|
bool doLogin(List<string> _arguments)
|
2023-08-01 15:08:31 +00:00
|
|
|
|
{
|
|
|
|
|
|
string path = Settings.Default.PSPath;
|
|
|
|
|
|
string psExe = Path.GetFullPath(Path.Combine(path, SettingsForm.PS_EXE_NAME));
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
// clear previous login token
|
|
|
|
|
|
httpClient.DefaultRequestHeaders.Authorization = null;
|
|
|
|
|
|
|
|
|
|
|
|
if ( !psExe.StartsWith(path) )
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Error: planetside.exe outside of planetside directory: " + psExe);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addLine("");
|
|
|
|
|
|
addLine("Start launching");
|
|
|
|
|
|
addLine("");
|
|
|
|
|
|
|
|
|
|
|
|
// start authentication
|
|
|
|
|
|
setButtonState(GameState.Authenticating);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// get current launcher version
|
|
|
|
|
|
//
|
|
|
|
|
|
checkLauncherVersion();
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// send login data
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( !sendLoginData() )
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// get file validation info
|
|
|
|
|
|
//
|
|
|
|
|
|
List<string> filesToValidate = new List<string>();
|
|
|
|
|
|
if ( !getFilesToValidate(ref filesToValidate) )
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// validate files
|
|
|
|
|
|
//
|
|
|
|
|
|
setButtonState(GameState.Validating);
|
|
|
|
|
|
|
|
|
|
|
|
string hashResult = "";
|
|
|
|
|
|
if ( !validateFiles(filesToValidate, ref hashResult) )
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// send validtation result
|
|
|
|
|
|
//
|
|
|
|
|
|
if ( !sendValidationResult(hashResult) )
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// finished validating
|
|
|
|
|
|
setButtonState(GameState.Launching);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
// get game token
|
|
|
|
|
|
//
|
|
|
|
|
|
string gameToken = "";
|
|
|
|
|
|
if ( !getGameToken(ref gameToken) )
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-02 19:25:33 +00:00
|
|
|
|
_arguments.Add("/K:" + gameToken);
|
2023-08-01 15:08:31 +00:00
|
|
|
|
|
2023-08-02 19:25:33 +00:00
|
|
|
|
return startPlanetSide(psExe, path, String.Join(" ", _arguments));
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-21 22:35:52 +00:00
|
|
|
|
bool startPlanetSide(string exe, string workingDir, string args)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
psProcess = new Process();
|
|
|
|
|
|
|
|
|
|
|
|
psProcess.StartInfo.WorkingDirectory = workingDir; // TODO: should this be where the launcher is for logging?
|
|
|
|
|
|
psProcess.StartInfo.FileName = exe;
|
|
|
|
|
|
psProcess.StartInfo.Arguments = args;
|
|
|
|
|
|
psProcess.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
|
psProcess.StartInfo.RedirectStandardError = true;
|
|
|
|
|
|
psProcess.StartInfo.UseShellExecute = false;
|
|
|
|
|
|
psProcess.Exited += new EventHandler(ps_Exited);
|
|
|
|
|
|
psProcess.OutputDataReceived += new DataReceivedEventHandler(ps_OutputDataReceived);
|
|
|
|
|
|
psProcess.EnableRaisingEvents = true;
|
|
|
|
|
|
|
2023-08-01 15:08:31 +00:00
|
|
|
|
addLine(String.Format("ProcessStart: \"{0}\" {1}", exe, args));
|
|
|
|
|
|
|
|
|
|
|
|
addLine("");
|
|
|
|
|
|
addLine("LAUNCHING");
|
|
|
|
|
|
addLine("");
|
2016-06-21 22:35:52 +00:00
|
|
|
|
|
|
|
|
|
|
if (!psProcess.Start())
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("ProcessStart: failed to start the planetside process! Make sure your planetside folder path is correct.");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addLine(String.Format("ProcessStart: planetside running as PID {0}", psProcess.Id));
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
|
|
|
|
|
psProcess.BeginErrorReadLine();
|
|
|
|
|
|
psProcess.BeginOutputReadLine();
|
|
|
|
|
|
|
2016-06-21 22:35:52 +00:00
|
|
|
|
return true;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ps_OutputDataReceived(object sender, DataReceivedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(e != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine(e.Data);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void addLine(String line)
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
this.SafeInvoke(a =>
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
ps_consoleOutput.AppendText(line + Environment.NewLine);
|
2016-06-19 20:02:10 +00:00
|
|
|
|
});
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void gameRunning()
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
setButtonState(GameState.Running);
|
|
|
|
|
|
progressShown(false);
|
2015-08-14 22:21:04 +00:00
|
|
|
|
|
2015-10-02 23:05:34 +00:00
|
|
|
|
bGameRunning = true;
|
2015-08-14 22:21:04 +00:00
|
|
|
|
gameState = GameState.Running;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void gameStopped()
|
|
|
|
|
|
{
|
2015-08-14 22:21:04 +00:00
|
|
|
|
this.stopLaunching();
|
2015-10-02 23:05:34 +00:00
|
|
|
|
bGameRunning = false;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ps_Exited(object sender, EventArgs e)
|
|
|
|
|
|
{
|
2016-06-19 20:49:51 +00:00
|
|
|
|
addLine(String.Format("ProcessEnd: exit code 0x{0}", psProcess.ExitCode.ToString("X8")));
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
gameStopped();
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
private void progressShown(bool shown)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.SafeInvoke(a =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (shown)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.spinner.Visible = true;
|
|
|
|
|
|
this.spinner.Enabled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
this.spinner.Visible = false;
|
|
|
|
|
|
this.spinner.Enabled = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
About a = new About();
|
|
|
|
|
|
a.StartPosition = FormStartPosition.CenterParent;
|
|
|
|
|
|
a.ShowDialog(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-03-19 19:46:03 +00:00
|
|
|
|
private void loginFormChangedUpdate()
|
2016-06-19 20:02:10 +00:00
|
|
|
|
{
|
|
|
|
|
|
if (gameState == GameState.Stopped)
|
|
|
|
|
|
{
|
2017-03-19 19:46:03 +00:00
|
|
|
|
if ((username.Text.Length > 0 && password.Text.Length > 0 || skipLauncher.Checked) &&
|
|
|
|
|
|
serverSelection.SelectedIndex != -1)
|
2016-06-19 20:02:10 +00:00
|
|
|
|
launchGame.Enabled = true;
|
|
|
|
|
|
else
|
|
|
|
|
|
launchGame.Enabled = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (skipLauncher.Checked)
|
|
|
|
|
|
{
|
|
|
|
|
|
Settings.Default.SkipLauncher = true;
|
|
|
|
|
|
username.Enabled = false;
|
|
|
|
|
|
password.Enabled = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Settings.Default.SkipLauncher = false;
|
|
|
|
|
|
username.Enabled = true;
|
|
|
|
|
|
password.Enabled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-03-19 19:46:03 +00:00
|
|
|
|
private void loginFormChanged(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
loginFormChangedUpdate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
private void setConsoleWindowState(bool open)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!open)
|
|
|
|
|
|
{
|
|
|
|
|
|
oldSize = this.Size;
|
|
|
|
|
|
|
|
|
|
|
|
this.hideShowOutput.Text = "vv Show vv";
|
2017-03-19 19:46:03 +00:00
|
|
|
|
this.MinimumSize = this.MaximumSize = new System.Drawing.Size(460, 160);
|
2016-06-19 20:02:10 +00:00
|
|
|
|
|
2017-03-19 19:46:03 +00:00
|
|
|
|
this.Size = new System.Drawing.Size(460, 160);
|
2016-06-19 20:02:10 +00:00
|
|
|
|
|
|
|
|
|
|
this.WindowState = FormWindowState.Normal;
|
|
|
|
|
|
this.MaximizeBox = false;
|
2016-06-19 20:49:51 +00:00
|
|
|
|
this.FormBorderStyle = FormBorderStyle.FixedSingle;
|
2016-06-19 20:02:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
this.hideShowOutput.Text = "^^ Hide ^^";
|
2017-03-19 19:46:03 +00:00
|
|
|
|
this.MinimumSize = new System.Drawing.Size(460, 350);
|
2016-06-19 20:02:10 +00:00
|
|
|
|
this.MaximumSize = new System.Drawing.Size(0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
if (oldSize.IsEmpty)
|
2016-06-19 20:49:51 +00:00
|
|
|
|
this.Size = new System.Drawing.Size(600, 500); // default size to expand to
|
2016-06-19 20:02:10 +00:00
|
|
|
|
else
|
|
|
|
|
|
this.Size = oldSize;
|
|
|
|
|
|
|
|
|
|
|
|
this.MaximizeBox = true;
|
2016-06-19 20:49:51 +00:00
|
|
|
|
this.FormBorderStyle = FormBorderStyle.Sizable;
|
2016-06-19 20:02:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
splitContainer1.Panel2Collapsed = !open;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LauncherForm_ResizeBegin(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
splitContainer1.Panel2.SuspendLayout();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LauncherForm_ResizeEnd(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Win32.SuspendPainting(splitContainer1.Panel2.Handle);
|
|
|
|
|
|
splitContainer1.Panel2.ResumeLayout();
|
|
|
|
|
|
Win32.ResumePainting(splitContainer1.Panel2.Handle);
|
|
|
|
|
|
this.Refresh();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void hideShowOutput_Click_1(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (splitContainer1.Panel2Collapsed)
|
|
|
|
|
|
{
|
|
|
|
|
|
Settings.Default.OutputShown = true;
|
|
|
|
|
|
setConsoleWindowState(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Settings.Default.OutputShown = false;
|
|
|
|
|
|
setConsoleWindowState(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-03-19 19:46:03 +00:00
|
|
|
|
private void loadServerSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
int index = serverSelection.SelectedIndex;
|
|
|
|
|
|
|
|
|
|
|
|
List<ServerEntry> entries = Util.LoadServerList();
|
|
|
|
|
|
serverSelection.Items.Clear();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (ServerEntry entry in entries)
|
|
|
|
|
|
{
|
|
|
|
|
|
serverSelection.Items.Add(entry.name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (entries.Count > 0 && index != -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (index + 1 >= entries.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
serverSelection.SelectedIndex = entries.Count - 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
serverSelection.SelectedIndex = index;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
loginFormChangedUpdate();
|
|
|
|
|
|
|
|
|
|
|
|
// Dont let us select a server without any servers!
|
|
|
|
|
|
serverSelection.Enabled = entries.Count != 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
SettingsForm a = new SettingsForm();
|
|
|
|
|
|
a.StartPosition = FormStartPosition.CenterParent;
|
|
|
|
|
|
a.ShowDialog(this);
|
2017-03-19 19:46:03 +00:00
|
|
|
|
|
|
|
|
|
|
loadServerSelection();
|
2016-06-19 20:02:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
private void selectAll_Click(object sender, EventArgs e)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2016-06-19 20:49:51 +00:00
|
|
|
|
this.ps_consoleOutput.Focus();
|
|
|
|
|
|
this.ps_consoleOutput.SelectAll();
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
private void copy_Click(object sender, EventArgs e)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2016-06-19 20:49:51 +00:00
|
|
|
|
this.ps_consoleOutput.Copy();
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
private void saveToFile_Click(object sender, EventArgs e)
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
2016-06-19 20:49:51 +00:00
|
|
|
|
SaveFileDialog saveFile = new SaveFileDialog();
|
2015-08-14 23:03:34 +00:00
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
saveFile.FileName = "";
|
|
|
|
|
|
saveFile.Filter = "Output file (*.txt) | *.txt";
|
|
|
|
|
|
saveFile.AddExtension = true;
|
|
|
|
|
|
saveFile.DefaultExt = ".txt";
|
2015-08-14 23:03:34 +00:00
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
DialogResult result = saveFile.ShowDialog();
|
2015-08-14 23:03:34 +00:00
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
if (result == DialogResult.OK)
|
|
|
|
|
|
{
|
|
|
|
|
|
FileStream f = File.OpenWrite(saveFile.FileName);
|
2015-08-14 23:03:34 +00:00
|
|
|
|
|
2016-06-19 20:49:51 +00:00
|
|
|
|
var encoder = new ASCIIEncoding();
|
|
|
|
|
|
var header = encoder.GetBytes(String.Format("{0} log output {1}" + Environment.NewLine, this.Text, DateTime.Now.ToString()));
|
|
|
|
|
|
var data = new ASCIIEncoding().GetBytes(this.ps_consoleOutput.Text);
|
|
|
|
|
|
|
|
|
|
|
|
f.Write(header, 0, header.Length);
|
|
|
|
|
|
f.Write(data, 0, data.Length);
|
|
|
|
|
|
f.Close();
|
|
|
|
|
|
}
|
2015-08-14 23:03:34 +00:00
|
|
|
|
}
|
2017-03-19 19:46:03 +00:00
|
|
|
|
|
|
|
|
|
|
private void serverSelection_SelectedIndexChanged(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Settings.Default.ServerSelection = serverSelection.SelectedIndex;
|
|
|
|
|
|
|
|
|
|
|
|
// Update the login form as well
|
|
|
|
|
|
loginFormChangedUpdate();
|
|
|
|
|
|
}
|
2015-08-14 23:03:34 +00:00
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|