2015-08-14 17:18:12 +00:00
|
|
|
|
using Microsoft.Win32;
|
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
using PSLauncher.Properties;
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Collections.Specialized;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Net;
|
2015-08-14 23:03:34 +00:00
|
|
|
|
using System.Runtime.InteropServices;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Threading;
|
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,
|
|
|
|
|
|
PSForever
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-14 22:21:04 +00:00
|
|
|
|
public enum GameState
|
|
|
|
|
|
{
|
|
|
|
|
|
Stopped,
|
|
|
|
|
|
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
|
|
|
|
|
|
{
|
|
|
|
|
|
Process psProcess;
|
|
|
|
|
|
string USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0";
|
2016-06-19 20:02:10 +00:00
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
int DEFAULT_WEB_TIMEOUT = 5000;
|
2015-10-02 23:05:34 +00:00
|
|
|
|
bool bGameRunning = false;
|
2015-08-14 22:21:04 +00:00
|
|
|
|
GameState gameState = GameState.Stopped;
|
2016-06-19 20:02:10 +00:00
|
|
|
|
System.Drawing.Size oldSize = new System.Drawing.Size(0, 0);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
|
|
|
|
|
LaunchDomain domain = LaunchDomain.Live;
|
|
|
|
|
|
|
|
|
|
|
|
Dictionary<LaunchDomain, string> domains = new Dictionary<LaunchDomain, string>()
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
{ LaunchDomain.Live, "https://lpj.daybreakgames.com/ps/live" },
|
|
|
|
|
|
{ LaunchDomain.PSForever, "https://login.psforever.net/" }
|
2015-08-14 17:18:12 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
public LauncherForm()
|
|
|
|
|
|
{
|
|
|
|
|
|
InitializeComponent();
|
2016-06-19 20:02:10 +00:00
|
|
|
|
|
|
|
|
|
|
if (Debugger.IsAttached)
|
|
|
|
|
|
Settings.Default.Reset();
|
|
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
string psDefault = getDefaultDirectory();
|
|
|
|
|
|
|
|
|
|
|
|
// first run with no settings or invalid starting path
|
|
|
|
|
|
if (Settings.Default.PSPath == "" || !checkDirForPlanetSide(Settings.Default.PSPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
Settings.Default.PSPath = psDefault;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
setConsoleWindowState(Settings.Default.OutputShown);
|
|
|
|
|
|
skipLauncher.Checked = Settings.Default.SkipLauncher;
|
2015-10-02 23:05:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void LauncherForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (this.bGameRunning)
|
|
|
|
|
|
{
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
case GameState.Launching:
|
|
|
|
|
|
this.launchGame.Enabled = false;
|
|
|
|
|
|
this.launchGame.Text = "Launching...";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case GameState.Running:
|
|
|
|
|
|
this.launchGame.BackColor = System.Drawing.Color.FromArgb(255, 128, 128);
|
|
|
|
|
|
this.launchGame.Enabled = true;
|
|
|
|
|
|
this.launchGame.Text = "Kill";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case GameState.Stopped:
|
|
|
|
|
|
this.launchGame.BackColor = System.Drawing.Color.FromArgb(128, 255, 128);
|
|
|
|
|
|
this.launchGame.Enabled = true;
|
|
|
|
|
|
this.launchGame.Text = "Launch";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case GameState.Stopping:
|
|
|
|
|
|
this.launchGame.Enabled = false;
|
|
|
|
|
|
this.launchGame.Text = "Killing...";
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void button2_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
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-19 20:02:10 +00:00
|
|
|
|
if(Settings.Default.ClearOutputOnLaunch)
|
|
|
|
|
|
{
|
|
|
|
|
|
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:02:10 +00:00
|
|
|
|
if (!checkDirForPlanetSide(path))
|
2015-08-14 17:18:12 +00:00
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Invalid planetside exe");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (skipLauncher.Checked)
|
|
|
|
|
|
{
|
|
|
|
|
|
// magic string to login to planetside from the actual game
|
2016-06-19 20:02:10 +00:00
|
|
|
|
startPlanetSide(psExe, Path.GetDirectoryName(psExe), "/K:StagingTest " + Settings.Default.ExtraArgs);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
startLaunching();
|
|
|
|
|
|
|
2015-08-14 22:21:04 +00:00
|
|
|
|
Task.Factory.StartNew(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
this.doLogin();
|
|
|
|
|
|
});
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-10-23 05:28:27 +00:00
|
|
|
|
HttpWebResponse netGetSession(string endpoint, CookieContainer cookies)
|
|
|
|
|
|
{
|
|
|
|
|
|
string hostname = domains[domain];
|
|
|
|
|
|
HttpWebRequest req = WebRequest.Create(hostname + endpoint) as HttpWebRequest;
|
|
|
|
|
|
req.CookieContainer = cookies;
|
|
|
|
|
|
req.CookieContainer.MaxCookieSize = 4000;
|
|
|
|
|
|
req.Method = "GET";
|
|
|
|
|
|
req.UserAgent = USER_AGENT;
|
|
|
|
|
|
req.Timeout = DEFAULT_WEB_TIMEOUT;
|
|
|
|
|
|
|
|
|
|
|
|
return req.GetResponse() as HttpWebResponse;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
void doLogin()
|
|
|
|
|
|
{
|
|
|
|
|
|
long ts = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
|
|
|
|
|
|
|
2016-06-19 20:02:10 +00:00
|
|
|
|
string path = Settings.Default.PSPath;
|
|
|
|
|
|
string psExe = Path.Combine(path, SettingsForm.PS_EXE_NAME);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Step 1: Establish Session ID
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
String endpoint = domains[domain];
|
|
|
|
|
|
CookieContainer reqCookies = new CookieContainer();
|
2015-10-23 05:28:27 +00:00
|
|
|
|
HttpWebRequest req;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
HttpWebResponse r;
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2015-10-23 05:28:27 +00:00
|
|
|
|
r = netGetSession("/?t=43323", reqCookies);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
catch (WebException x)
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Failed to gather initial session: " + x.Message);
|
2015-10-23 05:28:27 +00:00
|
|
|
|
|
|
|
|
|
|
if (x.Status != WebExceptionStatus.TrustFailure)
|
|
|
|
|
|
{
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DialogResult res = MessageBox.Show("DBG's HTTPS certificate has failed to verify. This means that their certificate has expired " +
|
|
|
|
|
|
"or you may be getting Man-in-the-middled (attacked). If you are under attack, your credentials could be lost. Continue regardless?",
|
|
|
|
|
|
"Certificate error", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
|
|
|
|
|
|
|
|
|
|
|
if (res != DialogResult.Yes)
|
|
|
|
|
|
{
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// WARNING: once we hit yes, all further SSL errors will be ignored
|
|
|
|
|
|
// https://stackoverflow.com/questions/2675133/c-sharp-ignore-certificate-errors
|
|
|
|
|
|
ServicePointManager.ServerCertificateValidationCallback +=
|
|
|
|
|
|
(sender, cert, chain, sslPolicyErrors) => true;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
r = netGetSession("/?t=43323", reqCookies);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (WebException x2)
|
|
|
|
|
|
{
|
|
|
|
|
|
addLine("Failed to gather initial session: " + x2.Message);
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Note: we must manually add secure cookies and CookieContainer is crap
|
|
|
|
|
|
// See http://thomaskrehbiel.com/post/1690-cookiecontainer_httpwebrequest_and_secure_cookies/
|
|
|
|
|
|
|
|
|
|
|
|
reqCookies.Add(new Uri(endpoint), r.Cookies);
|
|
|
|
|
|
|
|
|
|
|
|
addLine("PSWeb: session started");
|
|
|
|
|
|
r.Close();
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Step 2: Try logging in
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
req = WebRequest.Create(endpoint + "/login?t=43323") as HttpWebRequest;
|
|
|
|
|
|
req.CookieContainer = reqCookies;
|
|
|
|
|
|
req.Method = "POST";
|
|
|
|
|
|
req.UserAgent = USER_AGENT;
|
|
|
|
|
|
req.Timeout = DEFAULT_WEB_TIMEOUT;
|
|
|
|
|
|
req.Headers.Add("X-Requested-With", "XMLHttpRequest");
|
|
|
|
|
|
req.Headers.Add("Origin", "https://lp.soe.com");
|
|
|
|
|
|
|
|
|
|
|
|
req.ContentType = "application/x-www-form-urlencoded";
|
|
|
|
|
|
req.Referer = endpoint + "/?t=43323";
|
|
|
|
|
|
|
|
|
|
|
|
NameValueCollection query = new NameValueCollection();
|
|
|
|
|
|
query.Add("username", username.Text);
|
|
|
|
|
|
query.Add("password", password.Text);
|
|
|
|
|
|
query.Add("rememberPassword", "false");
|
|
|
|
|
|
query.Add("ts", ts.ToString());
|
|
|
|
|
|
|
|
|
|
|
|
var postdata = Encoding.ASCII.GetBytes(query.ToQueryString());
|
|
|
|
|
|
//addLine(query.ToQueryString());
|
|
|
|
|
|
|
|
|
|
|
|
req.ContentLength = postdata.Length;
|
|
|
|
|
|
|
|
|
|
|
|
using (var stream = req.GetRequestStream())
|
|
|
|
|
|
{
|
|
|
|
|
|
stream.Write(postdata, 0, postdata.Length);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
r = req.GetResponse() as HttpWebResponse;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (WebException x)
|
|
|
|
|
|
{
|
|
|
|
|
|
string txt;
|
|
|
|
|
|
|
|
|
|
|
|
using (HttpWebResponse respExcept = (HttpWebResponse)x.Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (respExcept != null && respExcept.GetResponseStream().CanRead)
|
|
|
|
|
|
{
|
|
|
|
|
|
StreamReader r2 = new StreamReader(respExcept.GetResponseStream());
|
|
|
|
|
|
txt = r2.ReadToEnd();
|
|
|
|
|
|
respExcept.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
txt = "";
|
|
|
|
|
|
addLine("Login failed: " + x.Message);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string errorDetail = "";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
JObject obj2 = JObject.Parse(txt);
|
|
|
|
|
|
errorDetail = (string)obj2["errorDetail"];
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Newtonsoft.Json.JsonException x2)
|
|
|
|
|
|
{
|
|
|
|
|
|
errorDetail = "Json parse error: " + x2.Message;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (errorDetail == "INVALID_ACCOUNT_ID")
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Unknown username");
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (errorDetail == "RESET_ACCOUNT_PASSWORD")
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Your account needs a password reset");
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (errorDetail == "PASSWORD_MISMATCH")
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Bad password");
|
|
|
|
|
|
}
|
|
|
|
|
|
else // unrecognized!
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Unknown error - see output window");
|
|
|
|
|
|
addLine("Login failure: " + x.Status);
|
|
|
|
|
|
addLine("Error: " + errorDetail);
|
|
|
|
|
|
addLine(txt);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!r.GetResponseStream().CanRead)
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Unknown error - see output window");
|
|
|
|
|
|
addLine("No login response received");
|
|
|
|
|
|
addLine("Status: " + r.StatusCode);
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
StreamReader reader = new StreamReader(r.GetResponseStream());
|
|
|
|
|
|
string text = reader.ReadToEnd();
|
|
|
|
|
|
|
|
|
|
|
|
//addLine(r.Headers["Set-Cookie"]);
|
|
|
|
|
|
reqCookies.Add(new Uri(endpoint), r.Cookies);
|
|
|
|
|
|
|
|
|
|
|
|
string result = "";
|
|
|
|
|
|
r.Close();
|
|
|
|
|
|
addLine("PSWeb: logged in");
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
JObject obj = JObject.Parse(text);
|
|
|
|
|
|
result = (string)obj["result"];
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Newtonsoft.Json.JsonException x2)
|
|
|
|
|
|
{
|
|
|
|
|
|
result = "Json parse error: " + x2.Message;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (result != "SUCCESS")
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Unknown error - see output window");
|
|
|
|
|
|
addLine("Bad login response: " + result);
|
|
|
|
|
|
addLine("Status: " + r.StatusCode);
|
|
|
|
|
|
addLine(text);
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Step 3: Fetch the login token
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
req = WebRequest.Create(endpoint + "/get_play_session?t=43323") as HttpWebRequest;
|
|
|
|
|
|
req.CookieContainer = reqCookies;
|
|
|
|
|
|
req.Method = "GET";
|
|
|
|
|
|
req.UserAgent = USER_AGENT;
|
|
|
|
|
|
req.Timeout = DEFAULT_WEB_TIMEOUT;
|
|
|
|
|
|
req.Headers.Add("Origin", "https://lp.soe.com");
|
|
|
|
|
|
req.Referer = endpoint + "/login?t=43323";
|
|
|
|
|
|
req.Headers.Add("X-Requested-With", "XMLHttpRequest");
|
|
|
|
|
|
req.Accept = "*/*";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
r = req.GetResponse() as HttpWebResponse;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (WebException x)
|
|
|
|
|
|
{
|
|
|
|
|
|
string txt;
|
|
|
|
|
|
|
|
|
|
|
|
using (HttpWebResponse respExcept = (HttpWebResponse)x.Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (respExcept != null && respExcept.GetResponseStream().CanRead)
|
|
|
|
|
|
{
|
|
|
|
|
|
StreamReader r2 = new StreamReader(respExcept.GetResponseStream());
|
|
|
|
|
|
txt = r2.ReadToEnd();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
txt = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string errorDetail = "";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
JObject obj2 = JObject.Parse(txt);
|
|
|
|
|
|
errorDetail = (string)obj2["result"];
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Newtonsoft.Json.JsonException x2)
|
|
|
|
|
|
{
|
|
|
|
|
|
errorDetail = "Json parse error: " + x2.Message;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (errorDetail == "RE_LOGIN")
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Failed to fetch token: bad login");
|
|
|
|
|
|
}
|
|
|
|
|
|
else // unrecognized!
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Unknown error - see output window");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addLine("Get token failure: " + x.Status);
|
|
|
|
|
|
addLine("Error: " + errorDetail);
|
|
|
|
|
|
addLine(txt);
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!r.GetResponseStream().CanRead)
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Unknown error - see output window");
|
|
|
|
|
|
addLine("No login response received");
|
|
|
|
|
|
addLine("Status: " + r.StatusCode);
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
reader = new StreamReader(r.GetResponseStream());
|
|
|
|
|
|
text = reader.ReadToEnd();
|
|
|
|
|
|
|
|
|
|
|
|
result = "";
|
|
|
|
|
|
r.Close();
|
|
|
|
|
|
|
|
|
|
|
|
string token = "";
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
JObject obj = JObject.Parse(text);
|
|
|
|
|
|
result = (string)obj["result"];
|
2015-10-23 05:28:27 +00:00
|
|
|
|
token = (string)obj["launchArgs"];
|
|
|
|
|
|
addLine(text);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
catch (Newtonsoft.Json.JsonException x2)
|
|
|
|
|
|
{
|
|
|
|
|
|
result = "Json parse error: " + x2.Message;
|
|
|
|
|
|
token = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (result != "SUCCESS")
|
|
|
|
|
|
{
|
|
|
|
|
|
setErrorMessage("Failed to get token");
|
|
|
|
|
|
addLine("Bad token response: " + result);
|
|
|
|
|
|
addLine("Status: " + r.StatusCode);
|
|
|
|
|
|
addLine(text);
|
|
|
|
|
|
stopLaunching();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
addLine("PSWeb: got launch args " + token);
|
|
|
|
|
|
|
|
|
|
|
|
string launch_args = token;
|
2016-06-19 20:02:10 +00:00
|
|
|
|
string ExtraLaunchArgs = Settings.Default.ExtraArgs;
|
2015-08-14 17:18:12 +00:00
|
|
|
|
|
|
|
|
|
|
if (ExtraLaunchArgs != String.Empty)
|
|
|
|
|
|
launch_args += " " + ExtraLaunchArgs;
|
|
|
|
|
|
|
|
|
|
|
|
startPlanetSide(psExe, path, launch_args);
|
2016-06-19 20:02:10 +00:00
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void startPlanetSide(string exe, string workingDir, string args)
|
|
|
|
|
|
{
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
2015-08-14 22:21:04 +00:00
|
|
|
|
addLine("ProcessStart: \"" + exe + "\" " + args);
|
2015-08-14 17:18:12 +00:00
|
|
|
|
psProcess.Start();
|
|
|
|
|
|
|
|
|
|
|
|
psProcess.BeginErrorReadLine();
|
|
|
|
|
|
psProcess.BeginOutputReadLine();
|
|
|
|
|
|
|
|
|
|
|
|
gameRunning();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
{
|
|
|
|
|
|
gameStopped();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Form1_Load(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
this.launchGame.Visible = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
this.spinner.Visible = false;
|
|
|
|
|
|
this.spinner.Enabled = false;
|
|
|
|
|
|
this.launchGame.Visible = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
About a = new About();
|
|
|
|
|
|
a.StartPosition = FormStartPosition.CenterParent;
|
|
|
|
|
|
a.ShowDialog(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void loginFormChanged(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (gameState == GameState.Stopped)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (username.Text.Length > 0 && password.Text.Length > 0 || skipLauncher.Checked)
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void setConsoleWindowState(bool open)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!open)
|
|
|
|
|
|
{
|
|
|
|
|
|
oldSize = this.Size;
|
|
|
|
|
|
|
|
|
|
|
|
this.hideShowOutput.Text = "vv Show vv";
|
|
|
|
|
|
this.MinimumSize = this.MaximumSize = new System.Drawing.Size(400, 160);
|
|
|
|
|
|
|
|
|
|
|
|
this.Size = new System.Drawing.Size(400, 190);
|
|
|
|
|
|
|
|
|
|
|
|
this.WindowState = FormWindowState.Normal;
|
|
|
|
|
|
this.MaximizeBox = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
this.hideShowOutput.Text = "^^ Hide ^^";
|
|
|
|
|
|
this.MinimumSize = new System.Drawing.Size(400, 350);
|
|
|
|
|
|
this.MaximumSize = new System.Drawing.Size(0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
if (oldSize.IsEmpty)
|
|
|
|
|
|
this.Size = new System.Drawing.Size(400, 500); // default size to expand to
|
|
|
|
|
|
else
|
|
|
|
|
|
this.Size = oldSize;
|
|
|
|
|
|
|
|
|
|
|
|
this.MaximizeBox = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
SettingsForm a = new SettingsForm();
|
|
|
|
|
|
a.StartPosition = FormStartPosition.CenterParent;
|
|
|
|
|
|
a.ShowDialog(this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-08-14 17:18:12 +00:00
|
|
|
|
private static string getDefaultDirectory()
|
|
|
|
|
|
{
|
|
|
|
|
|
RegistryKey key = null;
|
|
|
|
|
|
string psFolder = "";
|
|
|
|
|
|
|
|
|
|
|
|
// non-steam install
|
|
|
|
|
|
key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\App Paths\LaunchPad.exe");
|
|
|
|
|
|
|
|
|
|
|
|
if (key != null && key.GetValue("") != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
String defaultDirectory;
|
|
|
|
|
|
defaultDirectory = key.GetValue("").ToString();
|
|
|
|
|
|
defaultDirectory = Path.GetDirectoryName(defaultDirectory);
|
|
|
|
|
|
|
|
|
|
|
|
// verify that we aren't mistakingly returning a PlanetSide 2 directory...
|
|
|
|
|
|
if (Directory.Exists(defaultDirectory) && checkDirForPlanetSide(defaultDirectory))
|
|
|
|
|
|
return defaultDirectory;
|
|
|
|
|
|
|
|
|
|
|
|
// try to go up a directory and find the PlanetSide folder
|
|
|
|
|
|
string upOne = Directory.GetParent(defaultDirectory).FullName;
|
|
|
|
|
|
psFolder = Path.Combine(upOne, "Planetside");
|
|
|
|
|
|
|
|
|
|
|
|
if (Directory.Exists(psFolder) && checkDirForPlanetSide(psFolder))
|
|
|
|
|
|
return psFolder;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// worth a shot!
|
|
|
|
|
|
psFolder = Path.Combine(ProgramFilesx86(), "Sony\\PlanetSide");
|
|
|
|
|
|
|
|
|
|
|
|
if (Directory.Exists(psFolder) && checkDirForPlanetSide(psFolder))
|
|
|
|
|
|
return psFolder;
|
|
|
|
|
|
|
|
|
|
|
|
// HACK: our last attempt. Should work on Win7 and above with and updated launcher
|
|
|
|
|
|
psFolder = "C:\\Users\\Public\\Sony Online Entertainment\\Installed Games\\Planetside";
|
|
|
|
|
|
|
|
|
|
|
|
if (Directory.Exists(psFolder) && checkDirForPlanetSide(psFolder))
|
|
|
|
|
|
return psFolder;
|
|
|
|
|
|
|
|
|
|
|
|
// give up
|
|
|
|
|
|
return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static bool checkDirForPlanetSide(string dir)
|
|
|
|
|
|
{
|
2016-06-19 20:02:10 +00:00
|
|
|
|
return File.Exists(Path.Combine(dir, SettingsForm.PS_EXE_NAME));
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static string ProgramFilesx86()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (8 == IntPtr.Size
|
|
|
|
|
|
|| (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"))))
|
|
|
|
|
|
{
|
|
|
|
|
|
return Environment.GetEnvironmentVariable("ProgramFiles(x86)");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Environment.GetEnvironmentVariable("ProgramFiles");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static class QueryExtensions
|
|
|
|
|
|
{
|
|
|
|
|
|
public static string ToQueryString(this NameValueCollection nvc)
|
|
|
|
|
|
{
|
|
|
|
|
|
IEnumerable<string> segments = from key in nvc.AllKeys
|
|
|
|
|
|
from value in nvc.GetValues(key)
|
|
|
|
|
|
select string.Format("{0}={1}", key, value);
|
|
|
|
|
|
return string.Join("&", segments);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2015-08-14 23:03:34 +00:00
|
|
|
|
public static class Win32
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
public const int WM_SETREDRAW = 0x0b;
|
|
|
|
|
|
|
|
|
|
|
|
[DllImport("user32.dll")]
|
|
|
|
|
|
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
|
|
|
|
|
|
|
|
|
|
|
|
public static void SuspendPainting(IntPtr hWnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
SendMessage(hWnd, WM_SETREDRAW, (IntPtr)0, IntPtr.Zero);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void ResumePainting(IntPtr hWnd)
|
|
|
|
|
|
{
|
|
|
|
|
|
SendMessage(hWnd, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2015-08-14 17:18:12 +00:00
|
|
|
|
}
|