--- /dev/null
+using System;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading.Tasks;
+using Impostor.Client.Core.Events;
+using Impostor.Shared.Innersloth;
+using ErrorEventArgs = Impostor.Client.Core.Events.ErrorEventArgs;
+
+namespace Impostor.Client.Core
+{
+ public class AmongUsModifier
+ {
+ private const string RegionName = "Impostor";
+
+ private readonly string _amongUsDir;
+ private readonly string _regionFile;
+
+ public AmongUsModifier()
+ {
+ var appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "..\\LocalLow");
+ var amongUsDir = Path.Combine(appData, "Innersloth", "Among Us");
+
+ _amongUsDir = amongUsDir;
+ _regionFile = Path.Combine(amongUsDir, "regionInfo.dat");
+ }
+
+ public async Task SaveIp(string ip)
+ {
+ // Filter out whitespace.
+ ip = ip.Trim();
+
+ // Check if a valid IP address was entered.
+ if (!IPAddress.TryParse(ip, out var ipAddress))
+ {
+ // Attempt to resolve DNS.
+ try
+ {
+ var hostAddresses = await Dns.GetHostAddressesAsync(ip);
+ if (hostAddresses.Length == 0)
+ {
+ OnError("Invalid IP Address entered");
+ return;
+ }
+
+ // Use first IPv4 result.
+ ipAddress = hostAddresses.First(x => x.AddressFamily == AddressFamily.InterNetwork);
+ }
+ catch (SocketException)
+ {
+ OnError("Failed to resolve hostname.");
+ return;
+ }
+ }
+
+ // Only IPv4.
+ if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
+ {
+ OnError("Invalid IP Address entered, only IPv4 is allowed.");
+ return;
+ }
+
+ WriteIp(ipAddress);
+ }
+
+ /// <summary>
+ /// Writes an IP Address to the Among Us region file.
+ /// </summary>
+ /// <param name="ipAddress">The IPv4 address to write.</param>
+ private void WriteIp(IPAddress ipAddress)
+ {
+ if (ipAddress == null ||
+ ipAddress.AddressFamily != AddressFamily.InterNetwork)
+ {
+ throw new ArgumentException(nameof(ipAddress));
+ }
+
+ if (!Directory.Exists(_amongUsDir))
+ {
+ OnError("Among Us directory was not found, is it installed? Try running it once.");
+ return;
+ }
+
+ using (var file = File.Open(_regionFile, FileMode.Create, FileAccess.Write))
+ using (var writer = new BinaryWriter(file))
+ {
+ var ip = ipAddress.ToString();
+ var region = new RegionInfo(RegionName, ip, new[]
+ {
+ new ServerInfo($"{RegionName}-Master-1", ip, 22023)
+ });
+
+ region.Serialize(writer);
+
+ OnSaved(ip);
+ }
+ }
+
+ /// <summary>
+ /// Loads the existing IP Address from the Among Us region file
+ /// if it was set by Impostor before.
+ /// </summary>
+ public bool TryLoadIp(out string ipAddress)
+ {
+ ipAddress = null;
+
+ if (!File.Exists(_regionFile))
+ {
+ return false;
+ }
+
+ using (var file = File.Open(_regionFile, FileMode.Open, FileAccess.Read))
+ using (var reader = new BinaryReader(file))
+ {
+ var region = RegionInfo.Deserialize(reader);
+ if (region.Name == RegionName && region.Servers.Count >= 1)
+ {
+ ipAddress = region.Servers[0].Ip;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void OnError(string message)
+ {
+ Error?.Invoke(this, new ErrorEventArgs(message));
+ }
+
+ private void OnSaved(string ipAddress)
+ {
+ Saved?.Invoke(this, new SavedEventArgs(ipAddress));
+ }
+
+ public event EventHandler<ErrorEventArgs> Error;
+ public event EventHandler<SavedEventArgs> Saved;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace Impostor.Client.Core.Events
+{
+ public class ErrorEventArgs : EventArgs
+ {
+ public ErrorEventArgs(string message)
+ {
+ Message = message;
+ }
+
+ public string Message { get; }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace Impostor.Client.Core.Events
+{
+ public class SavedEventArgs : EventArgs
+ {
+ public SavedEventArgs(string ipAddress)
+ {
+ IpAddress = ipAddress;
+ }
+
+ public string IpAddress { get; }
+ }
+}
\ No newline at end of file
this.label2 = new System.Windows.Forms.Label();
this.buttonLaunch = new System.Windows.Forms.Button();
this.textIp = new System.Windows.Forms.TextBox();
+ this.lblUrl = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
- this.label1.Location = new System.Drawing.Point(12, 90);
+ this.label1.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(28, 139);
this.label1.Name = "label1";
- this.label1.Size = new System.Drawing.Size(62, 15);
+ this.label1.Size = new System.Drawing.Size(60, 13);
this.label1.TabIndex = 0;
this.label1.Text = "IP Address";
//
// label2
//
this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(12, 9);
+ this.label2.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label2.Location = new System.Drawing.Point(28, 23);
this.label2.Name = "label2";
- this.label2.Size = new System.Drawing.Size(230, 60);
+ this.label2.Size = new System.Drawing.Size(225, 91);
this.label2.TabIndex = 1;
this.label2.Text = "Welcome to Impostor\r\n\r\nPlease enter in the IP Address of the \r\nserver you would l" +
- "ike to use for Among Us";
+ "ike to use for Among Us\r\n\r\nIf you want to stop playing on the server, \r\nsimply s" +
+ "elect another region";
//
// buttonLaunch
//
- this.buttonLaunch.Location = new System.Drawing.Point(168, 123);
+ this.buttonLaunch.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.buttonLaunch.Location = new System.Drawing.Point(179, 155);
this.buttonLaunch.Name = "buttonLaunch";
- this.buttonLaunch.Size = new System.Drawing.Size(79, 23);
+ this.buttonLaunch.Size = new System.Drawing.Size(74, 22);
this.buttonLaunch.TabIndex = 2;
this.buttonLaunch.Text = "Save";
this.buttonLaunch.UseVisualStyleBackColor = true;
//
// textIp
//
- this.textIp.Location = new System.Drawing.Point(12, 123);
+ this.textIp.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.textIp.Location = new System.Drawing.Point(31, 155);
this.textIp.Name = "textIp";
- this.textIp.Size = new System.Drawing.Size(150, 23);
+ this.textIp.Size = new System.Drawing.Size(141, 22);
this.textIp.TabIndex = 3;
+ this.textIp.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textIp_KeyDown);
+ //
+ // lblUrl
+ //
+ this.lblUrl.AutoSize = true;
+ this.lblUrl.Cursor = System.Windows.Forms.Cursors.Hand;
+ this.lblUrl.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Underline, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblUrl.ForeColor = System.Drawing.SystemColors.Highlight;
+ this.lblUrl.Location = new System.Drawing.Point(39, 215);
+ this.lblUrl.Name = "lblUrl";
+ this.lblUrl.Size = new System.Drawing.Size(212, 13);
+ this.lblUrl.TabIndex = 4;
+ this.lblUrl.Text = "https://github.com/AeonLucid/Impostor";
+ this.lblUrl.Click += new System.EventHandler(this.lblUrl_Click);
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label3.Location = new System.Drawing.Point(54, 199);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(182, 13);
+ this.label3.TabIndex = 5;
+ this.label3.Text = "Source code and latest versions at\r\n";
//
// FrmMain
//
- this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(259, 161);
+ this.ClientSize = new System.Drawing.Size(283, 253);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.lblUrl);
this.Controls.Add(this.textIp);
this.Controls.Add(this.buttonLaunch);
this.Controls.Add(this.label2);
this.ForeColor = System.Drawing.SystemColors.ControlText;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
- this.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.MaximizeBox = false;
this.Name = "FrmMain";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Impostor";
this.Load += new System.EventHandler(this.FrmMain_Load);
+ this.Shown += new System.EventHandler(this.FrmMain_Shown);
this.ResumeLayout(false);
this.PerformLayout();
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
- private System.Windows.Forms.Button buttonL;
- private System.Windows.Forms.TextBox txtIp;
private System.Windows.Forms.Button buttonLaunch;
private System.Windows.Forms.TextBox textIp;
+ private System.Windows.Forms.Label lblUrl;
+ private System.Windows.Forms.Label label3;
}
}
\ No newline at end of file
using System;
-using System.IO;
-using System.Net;
-using System.Net.Sockets;
+using System.Diagnostics;
+using System.Threading.Tasks;
using System.Windows.Forms;
-using Impostor.Shared.Innersloth;
+using Impostor.Client.Core;
+using Impostor.Client.Core.Events;
namespace Impostor.Client.Forms
{
public partial class FrmMain : Form
{
+ private readonly AmongUsModifier _modifier;
+
public FrmMain()
{
InitializeComponent();
+
+ AcceptButton = buttonLaunch;
+
+ _modifier = new AmongUsModifier();
+ _modifier.Error += ModifierOnError;
+ _modifier.Saved += ModifierOnSaved;
}
- private void FrmMain_Load(object sender, EventArgs e)
+ private void ModifierOnError(object sender, ErrorEventArgs e)
{
- // TODO: Load old IP.
+ MessageBox.Show(e.Message, "Error",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+
+ textIp.Text = string.Empty;
+ textIp.Focus();
+
+ textIp.Enabled = true;
+ buttonLaunch.Enabled = true;
}
- private void buttonLaunch_Click(object sender, EventArgs e)
+ private void ModifierOnSaved(object sender, SavedEventArgs e)
{
- var ipText = textIp.Text;
-
- if (!IPAddress.TryParse(ipText, out var ipAddress))
+ MessageBox.Show("The IP Address was saved, please (re)start Among Us.", "Success",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Information);
+
+ textIp.Text = e.IpAddress;
+ textIp.Enabled = true;
+ buttonLaunch.Enabled = true;
+ }
+
+ private void FrmMain_Load(object sender, EventArgs e)
+ {
+ if (_modifier.TryLoadIp(out var ipAddress))
{
- MessageBox.Show("Invalid IP Address entered", "Error",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
-
- textIp.Text = string.Empty;
- textIp.Focus();
- return;
+ textIp.Text = ipAddress;
}
+ }
+
+ private void FrmMain_Shown(object sender, EventArgs e)
+ {
+ textIp.Focus();
+ }
- if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
+ private void textIp_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
{
- MessageBox.Show("Invalid IP Address entered, only IPv4 is allowed.", "Error",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
+ e.Handled = true;
- textIp.Text = string.Empty;
- textIp.Focus();
- return;
+ buttonLaunch_Click(this, EventArgs.Empty);
}
-
- // TODO: Clean up, move to somewhere else & error handling.
-
- var appData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "..\\LocalLow");
- var regionFile = Path.Combine(appData, "Innersloth", "Among Us", "regionInfo.dat");
- var region = new RegionInfo("Private", ipText, new []
- {
- new ServerInfo("Private-Master-1", ipText, 22023)
- });
-
- using (var file = File.Open(regionFile, FileMode.Create, FileAccess.Write))
- using (var writer = new BinaryWriter(file))
- {
- region.Serialize(writer);
- }
-
- MessageBox.Show("The IP Address was saved, please (re)start Among Us.", "Success",
- MessageBoxButtons.OK,
- MessageBoxIcon.Information);
+ }
+
+ private async void buttonLaunch_Click(object sender, EventArgs e)
+ {
+ textIp.Enabled = false;
+ buttonLaunch.Enabled = false;
+
+ await _modifier.SaveIp(textIp.Text);
+ }
+
+ private void lblUrl_Click(object sender, EventArgs e)
+ {
+ Process.Start("https://github.com/AeonLucid/Impostor");
}
}
}
\ No newline at end of file
-<root>
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
- <assembly alias="System.Drawing.Common" name="System.Drawing.Common, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
- <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing.Common" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAYAAAAAAAEAIAAUgQAAZgAAAICAAAABACAAKAgBAHqBAABAQAAAAQAgAChCAACiiQEAMDAAAAEA
IACoJQAAyssBACAgAAABACAAqBAAAHLxAQAQEAAAAQAgAGgEAAAaAgIAiVBORw0KGgoAAAANSUhEUgAA