Merge pull request #360 from tgstation/353-Seperation

Unified namespaces. Adds the server console
This commit is contained in:
Jordan Brown
2017-11-13 14:02:28 -05:00
committed by GitHub
172 changed files with 3644 additions and 3357 deletions
+3 -21
View File
@@ -28,29 +28,11 @@ Visual Studio comes with the nuget package manager. To install the dependencies,
##### (Optional) Installing WiX Toolset and Visual Studio Extension
The [WiX Toolset](http://wixtoolset.org/) is used for creating the installer .msi (Not the .exe, which is a standard C# program wrapper to the .msi). Building and modifying this is not required for debugging and development of the service but necessary if you want to debug tweaks to the installer configuration. You can download the Wix Toolset and Visual studio extension [here](http://wixtoolset.org/releases/). This will allow you to build `TGServiceInstaller.wixproj` just like all the other projects.
The [WiX Toolset](http://wixtoolset.org/) is used for creating the installer .msi (Not the .exe, which is a standard C# program wrapper to the .msi). Building and modifying this is not required for debugging and development of the service but necessary if you want to debug tweaks to the installer configuration. You can download the Wix Toolset and Visual studio extension [here](http://wixtoolset.org/releases/). This will allow you to build `TGS.Installer.wixproj` just like all the other projects.
#### Debugging
##### Debugging
So you've built the project and everything's good, right? Now you have to debug it. Debugging the command line and control panel are easy enough, just launch them like any other process. Debugging the TGServerService itself though requires a bit of finagling due to how Windows services work.
1. Uninstall any release versions of TG Station Server 3 you may have on your machine
1. Open an administrative Windows cmd prompt
1. Run `sc delete "TG Station Server"` for sanity
1. Build the service in debug mode
1. Navigate to `C:\Windows\Microsoft.NET\Framework\v4.0.30319`
1. Run `InstallUtil.exe` with the path to your debug `TGServerService.exe` as an argument. This will register your debug build as a Windows service.
If the command runs successfully you're all set up. Now, here is the debugging process.
1. BEFORE BUILDING. Stop `TG Station Server` from the Windows Services control panel
1. Build your new Debug version
1. Set your breakpoints
1. Start the service
1. Use your environment to attach to `TGServerService.exe` for debugging
1. If you need to debug startup, you'll have to add `System.Diagnostics.Debugger.Start()` where you want the service to wait for you. Do not write a constructor for the Service classas Windows will not let you debug it properly
Now be careful while debugging. The service runs with root level privileges and you wouldn't want any [accidents](http://i.imgur.com/zvGEpJD.png) to happen, would you?
Be careful while debugging. The service runs with root level privileges and you wouldn't want any [accidents](http://i.imgur.com/zvGEpJD.png) to happen, would you?
## Meet the Team
+1 -1
View File
@@ -7,4 +7,4 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyFileVersion("3.2.0.6")]
[assembly: AssemblyInformationalVersion("3.2.0.6")]
[assembly: InternalsVisibleTo("TGServiceTests")]
[assembly: InternalsVisibleTo("TGS.Tests")]
+2 -2
View File
@@ -2,7 +2,7 @@
[![Build status](https://ci.appveyor.com/api/projects/status/7t1h7bvuha0p9j5f?svg=true)](https://ci.appveyor.com/project/Cyberboss/tgstation-server-tools) [![Build Status](https://travis-ci.org/tgstation/tgstation-server.svg?branch=master)](https://travis-ci.org/tgstation/tgstation-server) [![codecov](https://codecov.io/gh/tgstation/tgstation-server/branch/master/graph/badge.svg)](https://codecov.io/gh/tgstation/tgstation-server)
[![GitHub license](https://img.shields.io/github/license/tgstation/tgstation-server.svg)](https://github.com/tgstation/tgstation-server/blob/master/LICENSE) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/tgstation/tgstation-server.svg)](http://isitmaintained.com/project/tgstation/tgstation-server "Average time to resolve an issue") [![NuGet version](https://badge.fury.io/nu/TGServiceInterface.svg)](https://badge.fury.io/nu/TGServiceInterface)
[![GitHub license](https://img.shields.io/github/license/tgstation/tgstation-server.svg)](https://github.com/tgstation/tgstation-server/blob/master/LICENSE) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/tgstation/tgstation-server.svg)](http://isitmaintained.com/project/tgstation/tgstation-server "Average time to resolve an issue") [![NuGet version](https://badge.fury.io/nu/TTGServiceInterface.svg)](https://badge.fury.io/nu/TGServiceInterface)
[![forthebadge](http://forthebadge.com/images/badges/made-with-c-sharp.svg)](http://forthebadge.com) [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a)
@@ -191,7 +191,7 @@ You can clear all active test merges using `Reset to Origin Branch` in the `Repo
### Viewing Server Logs
* Logs are stored in the Windows event viewer under `Windows Logs` -> `Application`. You'll need to filter this list for `TG Station Server`
* Every event type is keyed with an ID. A complete listing of these IDs and their purpose can be found [here](https://github.com/tgstation/tgstation-server/blob/master/TGServerService/EventID.cs).
* Every event type is keyed with an ID. A complete listing of these IDs and their purpose can be found [here](https://github.com/tgstation/tgstation-server/blob/master/TGS.Server/EventID.cs).
* You can also import the custom view `View TGS3 Logs.xml` in this folder to have them automatically filtered
### Enabling upstream changelog generation
-12
View File
@@ -1,12 +0,0 @@
using TGServiceInterface;
namespace TGCommandLine
{
abstract class ConsoleCommand : Command
{
/// <summary>
/// The <see cref="IInterface"/> currently in use by the <see cref="Program"/>
/// </summary>
public static IInterface Interface;
}
}
@@ -1,8 +1,8 @@
using System.Collections.Generic;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
class AdminCommand : InstanceRootCommand
{
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
class BYONDCommand : InstanceRootCommand
{
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
class IRCCommand : InstanceRootCommand
{
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
class ConfigCommand : InstanceRootCommand
{
+12
View File
@@ -0,0 +1,12 @@
using TGS.Interface;
namespace TGS.CommandLine
{
abstract class ConsoleCommand : Command
{
/// <summary>
/// The <see cref="IServerInterface"/> currently in use by the <see cref="Program"/>
/// </summary>
public static IServerInterface Interface;
}
}
@@ -1,315 +1,315 @@
using System;
using System.Collections.Generic;
using TGServiceInterface;
using TGServiceInterface.Components;
namespace TGCommandLine
{
class DDCommand : InstanceRootCommand
{
public DDCommand()
{
Keyword = "dd";
Children = new Command[] { new DDStartCommand(), new DDStopCommand(), new DDRestartCommand(), new DDStatusCommand(), new DDAutostartCommand(), new DDPortCommand(), new DDSecurityCommand(), new DDWorldAnnounceCommand(), new DDWebclientCommand() };
}
public override string GetHelpText()
{
return "Manage DreamDaemon";
}
}
class DDWorldAnnounceCommand : ConsoleCommand
{
public DDWorldAnnounceCommand()
{
Keyword = "announce";
RequiredParameters = 1;
}
public override string GetHelpText()
{
return "Sends a message all players on the server";
}
public override string GetArgumentString()
{
return "<message>";
}
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGDreamDaemon>().WorldAnnounce(String.Join(" ", parameters));
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class DDStartCommand : ConsoleCommand
{
public DDStartCommand()
{
Keyword = "start";
}
public override string GetHelpText()
{
return "Starts the server and watchdog";
}
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGDreamDaemon>().Start();
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class DDStopCommand : ConsoleCommand
{
public DDStopCommand()
{
Keyword = "stop";
}
public override string GetArgumentString()
{
return "[--graceful]";
}
public override string GetHelpText()
{
return "Stops the server and watchdog optionally waiting for the current round to end";
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
if (parameters.Count > 0 && parameters[0].ToLower() == "--graceful")
{
if (DD.DaemonStatus() != DreamDaemonStatus.Online)
{
OutputProc("Error: The game is not currently running!");
return ExitCode.ServerError;
}
DD.RequestStop();
return ExitCode.Normal;
}
var res = DD.Stop();
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class DDRestartCommand : ConsoleCommand
{
public DDRestartCommand()
{
Keyword = "restart";
}
public override string GetArgumentString()
{
return "[--graceful]";
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
if (parameters.Count > 0 && parameters[0].ToLower() == "--graceful")
{
if (DD.DaemonStatus() != DreamDaemonStatus.Online)
{
OutputProc("Error: The game is not currently running!");
return ExitCode.ServerError;
}
DD.RequestRestart();
return ExitCode.Normal;
}
var res = DD.Restart();
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
public override string GetHelpText()
{
return "Restarts the server and watchdog optionally waiting for the current round to end";
}
}
class DDStatusCommand : ConsoleCommand
{
public DDStatusCommand()
{
Keyword = "status";
}
public override string GetHelpText()
{
return "Gets the current status of the watchdog and server";
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
OutputProc(DD.StatusString(true));
if (DD.ShutdownInProgress())
OutputProc("The server will shutdown once the current round completes.");
var pc = DD.PlayerCount();
if (pc != -1)
OutputProc(pc + " connected clients");
return ExitCode.Normal;
}
}
class DDAutostartCommand : ConsoleCommand
{
public DDAutostartCommand()
{
Keyword = "autostart";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
switch (parameters[0].ToLower())
{
case "on":
DD.SetAutostart(true);
break;
case "off":
DD.SetAutostart(false);
break;
case "check":
OutputProc("Autostart is: " + (DD.Autostart() ? "On" : "Off"));
break;
default:
OutputProc("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<on|off|check>";
}
public override string GetHelpText()
{
return "Change or check autostarting of the game server with the service";
}
}
class DDWebclientCommand : ConsoleCommand
{
public DDWebclientCommand()
{
Keyword = "webclient";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
switch (parameters[0].ToLower())
{
case "on":
DD.SetWebclient(true);
break;
case "off":
DD.SetWebclient(false);
break;
case "check":
OutputProc("Webclient is: " + (DD.Webclient() ? "Enabled" : "Disabled"));
break;
default:
OutputProc("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<on|off|check>";
}
public override string GetHelpText()
{
return "Change or check if the BYOND webclient is enabled for the game server";
}
}
class DDPortCommand : ConsoleCommand
{
public DDPortCommand()
{
Keyword = "set-port";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
ushort port;
try
{
port = Convert.ToUInt16(parameters[0]);
}
catch
{
OutputProc("Invalid port number!");
return ExitCode.BadCommand;
}
Interface.GetComponent<ITGDreamDaemon>().SetPort(port);
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<number>";
}
public override string GetHelpText()
{
return "Sets the port DreamDaemon will open the server on. Requires a server restart to apply and queues a graceful one up";
}
}
class DDSecurityCommand : ConsoleCommand
{
public DDSecurityCommand()
{
Keyword = "set-security";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
DreamDaemonSecurity sec;
switch (parameters[0].ToLower())
{
case "safe":
sec = DreamDaemonSecurity.Safe;
break;
case "ultra":
case "ultrasafe":
sec = DreamDaemonSecurity.Ultrasafe;
break;
case "trust":
case "trusted":
sec = DreamDaemonSecurity.Trusted;
break;
default:
OutputProc("Invalid security word!");
return ExitCode.BadCommand;
}
Interface.GetComponent<ITGDreamDaemon>().SetSecurityLevel(sec);
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<safe|ultrasafe|trusted>";
}
public override string GetHelpText()
{
return "Sets the visibility option for the DreamDaemon world";
}
}
}
using System;
using System.Collections.Generic;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class DDCommand : InstanceRootCommand
{
public DDCommand()
{
Keyword = "dd";
Children = new Command[] { new DDStartCommand(), new DDStopCommand(), new DDRestartCommand(), new DDStatusCommand(), new DDAutostartCommand(), new DDPortCommand(), new DDSecurityCommand(), new DDWorldAnnounceCommand(), new DDWebclientCommand() };
}
public override string GetHelpText()
{
return "Manage DreamDaemon";
}
}
class DDWorldAnnounceCommand : ConsoleCommand
{
public DDWorldAnnounceCommand()
{
Keyword = "announce";
RequiredParameters = 1;
}
public override string GetHelpText()
{
return "Sends a message all players on the server";
}
public override string GetArgumentString()
{
return "<message>";
}
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGDreamDaemon>().WorldAnnounce(String.Join(" ", parameters));
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class DDStartCommand : ConsoleCommand
{
public DDStartCommand()
{
Keyword = "start";
}
public override string GetHelpText()
{
return "Starts the server and watchdog";
}
protected override ExitCode Run(IList<string> parameters)
{
var res = Interface.GetComponent<ITGDreamDaemon>().Start();
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class DDStopCommand : ConsoleCommand
{
public DDStopCommand()
{
Keyword = "stop";
}
public override string GetArgumentString()
{
return "[--graceful]";
}
public override string GetHelpText()
{
return "Stops the server and watchdog optionally waiting for the current round to end";
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
if (parameters.Count > 0 && parameters[0].ToLower() == "--graceful")
{
if (DD.DaemonStatus() != DreamDaemonStatus.Online)
{
OutputProc("Error: The game is not currently running!");
return ExitCode.ServerError;
}
DD.RequestStop();
return ExitCode.Normal;
}
var res = DD.Stop();
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
}
class DDRestartCommand : ConsoleCommand
{
public DDRestartCommand()
{
Keyword = "restart";
}
public override string GetArgumentString()
{
return "[--graceful]";
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
if (parameters.Count > 0 && parameters[0].ToLower() == "--graceful")
{
if (DD.DaemonStatus() != DreamDaemonStatus.Online)
{
OutputProc("Error: The game is not currently running!");
return ExitCode.ServerError;
}
DD.RequestRestart();
return ExitCode.Normal;
}
var res = DD.Restart();
OutputProc(res ?? "Success!");
return res == null ? ExitCode.Normal : ExitCode.ServerError;
}
public override string GetHelpText()
{
return "Restarts the server and watchdog optionally waiting for the current round to end";
}
}
class DDStatusCommand : ConsoleCommand
{
public DDStatusCommand()
{
Keyword = "status";
}
public override string GetHelpText()
{
return "Gets the current status of the watchdog and server";
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
OutputProc(DD.StatusString(true));
if (DD.ShutdownInProgress())
OutputProc("The server will shutdown once the current round completes.");
var pc = DD.PlayerCount();
if (pc != -1)
OutputProc(pc + " connected clients");
return ExitCode.Normal;
}
}
class DDAutostartCommand : ConsoleCommand
{
public DDAutostartCommand()
{
Keyword = "autostart";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
switch (parameters[0].ToLower())
{
case "on":
DD.SetAutostart(true);
break;
case "off":
DD.SetAutostart(false);
break;
case "check":
OutputProc("Autostart is: " + (DD.Autostart() ? "On" : "Off"));
break;
default:
OutputProc("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<on|off|check>";
}
public override string GetHelpText()
{
return "Change or check autostarting of the game server with the service";
}
}
class DDWebclientCommand : ConsoleCommand
{
public DDWebclientCommand()
{
Keyword = "webclient";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
var DD = Interface.GetComponent<ITGDreamDaemon>();
switch (parameters[0].ToLower())
{
case "on":
DD.SetWebclient(true);
break;
case "off":
DD.SetWebclient(false);
break;
case "check":
OutputProc("Webclient is: " + (DD.Webclient() ? "Enabled" : "Disabled"));
break;
default:
OutputProc("Invalid parameter: " + parameters[0]);
return ExitCode.BadCommand;
}
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<on|off|check>";
}
public override string GetHelpText()
{
return "Change or check if the BYOND webclient is enabled for the game server";
}
}
class DDPortCommand : ConsoleCommand
{
public DDPortCommand()
{
Keyword = "set-port";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
ushort port;
try
{
port = Convert.ToUInt16(parameters[0]);
}
catch
{
OutputProc("Invalid port number!");
return ExitCode.BadCommand;
}
Interface.GetComponent<ITGDreamDaemon>().SetPort(port);
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<number>";
}
public override string GetHelpText()
{
return "Sets the port DreamDaemon will open the server on. Requires a server restart to apply and queues a graceful one up";
}
}
class DDSecurityCommand : ConsoleCommand
{
public DDSecurityCommand()
{
Keyword = "set-security";
RequiredParameters = 1;
}
protected override ExitCode Run(IList<string> parameters)
{
DreamDaemonSecurity sec;
switch (parameters[0].ToLower())
{
case "safe":
sec = DreamDaemonSecurity.Safe;
break;
case "ultra":
case "ultrasafe":
sec = DreamDaemonSecurity.Ultrasafe;
break;
case "trust":
case "trusted":
sec = DreamDaemonSecurity.Trusted;
break;
default:
OutputProc("Invalid security word!");
return ExitCode.BadCommand;
}
Interface.GetComponent<ITGDreamDaemon>().SetSecurityLevel(sec);
return ExitCode.Normal;
}
public override string GetArgumentString()
{
return "<safe|ultrasafe|trusted>";
}
public override string GetHelpText()
{
return "Sets the visibility option for the DreamDaemon world";
}
}
}
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
class DMCommand : InstanceRootCommand
{
@@ -1,11 +1,11 @@
using System.Collections.Generic;
using TGServiceInterface;
using TGS.Interface;
namespace TGCommandLine
namespace TGS.CommandLine
{
abstract class InstanceRootCommand : RootCommand
{
public static IInterface currentInterface;
public static IServerInterface currentInterface;
public override ExitCode DoRun(IList<string> parameters)
{
if (currentInterface.InstanceName == null)
@@ -1,286 +1,285 @@
using System;
using System.Collections.Generic;
using System.Linq;
using TGServiceInterface;
using TGServiceInterface.Components;
namespace TGCommandLine
{
class Program
{
static bool interactive = false, saidSrvVersion = false;
static IInterface currentInterface;
static Command.ExitCode RunCommandLine(IList<string> argsAsList)
{
//first lookup the connection string
bool badConnectionString = false;
for (var I = 0; I < argsAsList.Count - 1; ++I) {
var lowerarg = argsAsList[I].ToLower();
if (lowerarg == "-c" || lowerarg == "--connect")
{
var connectionString = argsAsList[I + 1];
var splits = connectionString.Split('@');
var userpass = splits[0].Split(':');
if (splits.Length != 2 || userpass.Length != 2)
{
badConnectionString = true;
break;
}
var addrport = splits[1].Split(':');
if (addrport.Length != 2)
{
badConnectionString = true;
break;
}
var username = userpass[0];
var password = userpass[1];
var address = addrport[0];
ushort port;
try
{
port = Convert.ToUInt16(addrport[1]);
}
catch
{
badConnectionString = true;
break;
}
if(String.IsNullOrWhiteSpace(username) || String.IsNullOrWhiteSpace(password) || String.IsNullOrWhiteSpace(address))
{
badConnectionString = true;
break;
}
argsAsList.RemoveAt(I);
argsAsList.RemoveAt(I);
ReplaceInterface(new Interface(address, port, username, password));
break;
}
}
if (badConnectionString)
{
Console.WriteLine("Remote connection usage: <-c/--connect> username:password@address:port");
return Command.ExitCode.BadCommand;
}
var res = currentInterface.ConnectionStatus(out string error);
if (!res.HasFlag(ConnectivityLevel.Connected))
{
Console.WriteLine("Unable to connect to service: " + error);
Console.WriteLine("Remote connection usage: <-c/--connect> username:password@address:port");
return Command.ExitCode.ConnectionError;
}
if (!res.HasFlag(ConnectivityLevel.Authenticated))
{
Console.WriteLine("Authentication error: Username/password/windows identity is not authorized!");
return Command.ExitCode.ConnectionError;
}
if (!SentVMMWarning && currentInterface.VersionMismatch(out error))
{
SentVMMWarning = true;
Console.WriteLine(error);
}
else if (interactive && !saidSrvVersion)
{
Console.WriteLine("Connectd to service version: " + currentInterface.GetServiceComponent<ITGLanding>().Version());
saidSrvVersion = true;
}
try
{
return new CLICommand(currentInterface).DoRun(argsAsList);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
return Command.ExitCode.ConnectionError;
};
}
static void ReplaceInterface(IInterface I)
{
currentInterface = I;
ConsoleCommand.Interface = I;
InstanceRootCommand.currentInterface = I;
saidSrvVersion = false;
}
public static string ReadLineSecure()
{
string result = "";
while (true)
{
ConsoleKeyInfo i = Console.ReadKey(true);
if (i.Key == ConsoleKey.Enter)
{
break;
}
else if (i.Key == ConsoleKey.Backspace)
{
if (result.Length > 0)
{
result = result.Substring(0, result.Length - 1);
Console.Write("\b \b");
}
}
else
{
result += i.KeyChar;
Console.Write("*");
}
}
Console.WriteLine();
return result;
}
static bool SentVMMWarning = false;
static string AcceptedBadCert;
static bool BadCertificateInteractive(string message)
{
if (AcceptedBadCert == message)
return true;
Console.WriteLine(message);
Console.Write("Do you wish to continue? NOT RECCOMENDED! (y/N): ");
var result = Console.ReadLine().Trim().ToLower();
if (result == "y" || result == "yes")
{
AcceptedBadCert = message;
return true;
}
return false;
}
/// <summary>
/// Tries to set <see cref="currentInterface"/>'s <see cref="ITGInstance"/> to <paramref name="instanceName"/>, outputting appropriate messages
/// </summary>
/// <param name="instanceName">The name of the <see cref="ITGInstance"/> to test</param>
/// <param name="silentSuccess">If <see langword="true"/>, does not output on success</param>
/// <returns><see langword="true"/> if a <see cref="ConnectivityLevel.Authenticated"/> was achieved with <see cref="IInterface.ConnectToInstance(string, bool)"/>, <see langword="false"/> otherwise</returns>
static bool CheckInstanceConnectivity(string instanceName, bool silentSuccess)
{
var res = currentInterface.ConnectToInstance(instanceName);
if (!res.HasFlag(ConnectivityLevel.Connected))
Console.WriteLine("Unable to connect to instance! Does it exist?");
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
Console.WriteLine("The current user is not authorized to use this instance!");
else
{
if(!silentSuccess)
Console.WriteLine("Successfully conected to instance!");
return true;
}
return false;
}
static int Main(string[] args)
{
ReplaceInterface(new Interface());
Command.OutputProcVar.Value = Console.WriteLine;
if (args.Length != 0)
{
var argsAsList = new List<string>(args);
for (var I = 0; I < argsAsList.Count - 1; ++I)
{
if (argsAsList[I].ToLower() == "--instance")
{
if (!CheckInstanceConnectivity(args[I + 1], true))
return (int)Command.ExitCode.ConnectionError;
argsAsList.RemoveRange(I, 2);
break;
}
else if (argsAsList[I].ToLower() == "--disable-ssl-verification") //im just not even going to document this because i hate it so much
{
argsAsList.RemoveAt(I);
--I;
Interface.SetBadCertificateHandler(_ => false);
}
}
return (int)RunCommandLine(argsAsList);
}
//interactive mode
Interface.SetBadCertificateHandler(BadCertificateInteractive);
Console.WriteLine("Type 'instance' to connect to a server instance");
Console.WriteLine("Type 'remote' to connect to a remote service");
while (true)
{
Console.Write("Enter command: ");
var NextCommand = Console.ReadLine();
switch (NextCommand.ToLower())
{
case "instance":
Console.Write("Enter instance name: ");
CheckInstanceConnectivity(Console.ReadLine(), false);
break;
case "remote":
SentVMMWarning = false;
Console.Write("Enter server address: ");
var address = Console.ReadLine();
Console.Write("Enter server port: ");
ushort port;
try{
port = Convert.ToUInt16(Console.ReadLine());
}
catch
{
Console.WriteLine("Error: Bad port!");
break;
}
Console.Write("Enter username: ");
var username = Console.ReadLine();
Console.Write("Enter password: ");
var password = ReadLineSecure();
ReplaceInterface(new Interface(address, port, username, password));
var res = currentInterface.ConnectionStatus(out string error);
if (!res.HasFlag(ConnectivityLevel.Connected))
{
Console.WriteLine("Unable to connect: " + error);
ReplaceInterface(new Interface());
}
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
{
Console.WriteLine("Authentication error: Username/password/windows identity is not authorized! Returning to local mode...");
ReplaceInterface(new Interface());
}
else
{
Console.WriteLine("Connected remotely");
if (currentInterface.VersionMismatch(out error))
{
SentVMMWarning = true;
Console.WriteLine(error);
}
Console.WriteLine("Type 'disconnect' to return to local mode");
}
break;
case "disconnect":
SentVMMWarning = false;
ReplaceInterface(new Interface());
Console.WriteLine("Switch to local mode");
break;
case "quit":
case "exit":
return (int)Command.ExitCode.Normal;
#if DEBUG
case "debug-upgrade":
currentInterface.GetComponent<ITGSService>().PrepareForUpdate();
return (int)Command.ExitCode.Normal;
#endif
default:
//linq voodoo to get quoted strings
var formattedCommand = NextCommand.Split('"')
.Select((element, index) => index % 2 == 0 // If even index
? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) // Split the item
: new string[] { element }) // Keep the entire item
.SelectMany(element => element).ToList();
formattedCommand = formattedCommand.Select(x => x.Trim()).ToList();
formattedCommand.Remove("");
RunCommandLine(formattedCommand);
break;
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGS.CommandLine
{
class Program
{
static bool interactive = false, saidSrvVersion = false;
static IServerInterface currentInterface;
static Command.ExitCode RunCommandLine(IList<string> argsAsList)
{
//first lookup the connection string
bool badConnectionString = false;
for (var I = 0; I < argsAsList.Count - 1; ++I) {
var lowerarg = argsAsList[I].ToLower();
if (lowerarg == "-c" || lowerarg == "--connect")
{
var connectionString = argsAsList[I + 1];
var splits = connectionString.Split('@');
var userpass = splits[0].Split(':');
if (splits.Length != 2 || userpass.Length != 2)
{
badConnectionString = true;
break;
}
var addrport = splits[1].Split(':');
if (addrport.Length != 2)
{
badConnectionString = true;
break;
}
var username = userpass[0];
var password = userpass[1];
var address = addrport[0];
ushort port;
try
{
port = Convert.ToUInt16(addrport[1]);
}
catch
{
badConnectionString = true;
break;
}
if(String.IsNullOrWhiteSpace(username) || String.IsNullOrWhiteSpace(password) || String.IsNullOrWhiteSpace(address))
{
badConnectionString = true;
break;
}
argsAsList.RemoveAt(I);
argsAsList.RemoveAt(I);
ReplaceInterface(new ServerInterface(address, port, username, password));
break;
}
}
if (badConnectionString)
{
Console.WriteLine("Remote connection usage: <-c/--connect> username:password@address:port");
return Command.ExitCode.BadCommand;
}
var res = currentInterface.ConnectionStatus(out string error);
if (!res.HasFlag(ConnectivityLevel.Connected))
{
Console.WriteLine("Unable to connect to service: " + error);
Console.WriteLine("Remote connection usage: <-c/--connect> username:password@address:port");
return Command.ExitCode.ConnectionError;
}
if (!res.HasFlag(ConnectivityLevel.Authenticated))
{
Console.WriteLine("Authentication error: Username/password/windows identity is not authorized!");
return Command.ExitCode.ConnectionError;
}
if (!SentVMMWarning && currentInterface.VersionMismatch(out error))
{
SentVMMWarning = true;
Console.WriteLine(error);
}
else if (interactive && !saidSrvVersion)
{
Console.WriteLine("Connectd to service version: " + currentInterface.GetServiceComponent<ITGLanding>().Version());
saidSrvVersion = true;
}
try
{
return new CLICommand(currentInterface).DoRun(argsAsList);
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.ToString());
return Command.ExitCode.ConnectionError;
};
}
static void ReplaceInterface(IServerInterface I)
{
currentInterface = I;
ConsoleCommand.Interface = I;
InstanceRootCommand.currentInterface = I;
saidSrvVersion = false;
}
public static string ReadLineSecure()
{
string result = "";
while (true)
{
ConsoleKeyInfo i = Console.ReadKey(true);
if (i.Key == ConsoleKey.Enter)
{
break;
}
else if (i.Key == ConsoleKey.Backspace)
{
if (result.Length > 0)
{
result = result.Substring(0, result.Length - 1);
Console.Write("\b \b");
}
}
else
{
result += i.KeyChar;
Console.Write("*");
}
}
Console.WriteLine();
return result;
}
static bool SentVMMWarning = false;
static string AcceptedBadCert;
static bool BadCertificateInteractive(string message)
{
if (AcceptedBadCert == message)
return true;
Console.WriteLine(message);
Console.Write("Do you wish to continue? NOT RECCOMENDED! (y/N): ");
var result = Console.ReadLine().Trim().ToLower();
if (result == "y" || result == "yes")
{
AcceptedBadCert = message;
return true;
}
return false;
}
/// <summary>
/// Tries to set <see cref="currentInterface"/>'s <see cref="ITGInstance"/> to <paramref name="instanceName"/>, outputting appropriate messages
/// </summary>
/// <param name="instanceName">The name of the <see cref="ITGInstance"/> to test</param>
/// <param name="silentSuccess">If <see langword="true"/>, does not output on success</param>
/// <returns><see langword="true"/> if a <see cref="ConnectivityLevel.Authenticated"/> was achieved with <see cref="IServerInterface.ConnectToInstance(string, bool)"/>, <see langword="false"/> otherwise</returns>
static bool CheckInstanceConnectivity(string instanceName, bool silentSuccess)
{
var res = currentInterface.ConnectToInstance(instanceName);
if (!res.HasFlag(ConnectivityLevel.Connected))
Console.WriteLine("Unable to connect to instance! Does it exist?");
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
Console.WriteLine("The current user is not authorized to use this instance!");
else
{
if(!silentSuccess)
Console.WriteLine("Successfully conected to instance!");
return true;
}
return false;
}
static int Main(string[] args)
{
ReplaceInterface(new ServerInterface());
Command.OutputProcVar.Value = Console.WriteLine;
if (args.Length != 0)
{
var argsAsList = new List<string>(args);
for (var I = 0; I < argsAsList.Count - 1; ++I)
{
if (argsAsList[I].ToLower() == "--instance")
{
if (!CheckInstanceConnectivity(args[I + 1], true))
return (int)Command.ExitCode.ConnectionError;
argsAsList.RemoveRange(I, 2);
break;
}
else if (argsAsList[I].ToLower() == "--disable-ssl-verification") //im just not even going to document this because i hate it so much
{
argsAsList.RemoveAt(I);
--I;
ServerInterface.SetBadCertificateHandler(_ => false);
}
}
return (int)RunCommandLine(argsAsList);
}
//interactive mode
ServerInterface.SetBadCertificateHandler(BadCertificateInteractive);
Console.WriteLine("Type 'instance' to connect to a server instance");
Console.WriteLine("Type 'remote' to connect to a remote service");
while (true)
{
Console.Write("Enter command: ");
var NextCommand = Console.ReadLine();
switch (NextCommand.ToLower())
{
case "instance":
Console.Write("Enter instance name: ");
CheckInstanceConnectivity(Console.ReadLine(), false);
break;
case "remote":
SentVMMWarning = false;
Console.Write("Enter server address: ");
var address = Console.ReadLine();
Console.Write("Enter server port: ");
ushort port;
try{
port = Convert.ToUInt16(Console.ReadLine());
}
catch
{
Console.WriteLine("Error: Bad port!");
break;
}
Console.Write("Enter username: ");
var username = Console.ReadLine();
Console.Write("Enter password: ");
var password = ReadLineSecure();
ReplaceInterface(new ServerInterface(address, port, username, password));
var res = currentInterface.ConnectionStatus(out string error);
if (!res.HasFlag(ConnectivityLevel.Connected))
{
Console.WriteLine("Unable to connect: " + error);
ReplaceInterface(new ServerInterface());
}
else if (!res.HasFlag(ConnectivityLevel.Authenticated))
{
Console.WriteLine("Authentication error: Username/password/windows identity is not authorized! Returning to local mode...");
ReplaceInterface(new ServerInterface());
}
else
{
Console.WriteLine("Connected remotely");
if (currentInterface.VersionMismatch(out error))
{
SentVMMWarning = true;
Console.WriteLine(error);
}
Console.WriteLine("Type 'disconnect' to return to local mode");
}
break;
case "disconnect":
SentVMMWarning = false;
ReplaceInterface(new ServerInterface());
Console.WriteLine("Switch to local mode");
break;
case "quit":
case "exit":
return (int)Command.ExitCode.Normal;
#if DEBUG
case "debug-upgrade":
currentInterface.GetComponent<ITGSService>().PrepareForUpdate();
return (int)Command.ExitCode.Normal;
#endif
default:
//linq voodoo to get quoted strings
var formattedCommand = NextCommand.Split('"')
.Select((element, index) => index % 2 == 0 // If even index
? element.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) // Split the item
: new string[] { element }) // Keep the entire item
.SelectMany(element => element).ToList();
formattedCommand = formattedCommand.Select(x => x.Trim()).ToList();
formattedCommand.Remove("");
RunCommandLine(formattedCommand);
break;
}
}
}
}
}
@@ -1,17 +1,17 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Commandline")]
[assembly: AssemblyDescription("CLI for the TG Station Server Service")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9ad1f086-a83e-4d14-a844-58a9471106b6")]
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Commandline")]
[assembly: AssemblyDescription("CLI for the TG Station Server Service")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9ad1f086-a83e-4d14-a844-58a9471106b6")]
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
class RepoCommand : RootCommand
{
@@ -1,13 +1,13 @@
using System;
using System.Collections.Generic;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
class CLICommand : RootCommand
{
public CLICommand(IInterface I)
public CLICommand(IServerInterface I)
{
var tmp = new List<Command> { new UpdateCommand(), new TestmergeCommand(), new RepoCommand(), new BYONDCommand(), new DMCommand(), new DDCommand(), new ConfigCommand(), new IRCCommand(), new DiscordCommand(), new AutoUpdateCommand(), new SetAutoUpdateCommand() };
if (I.ConnectToInstance().HasFlag(ConnectivityLevel.Administrator))
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGCommandLine
namespace TGS.CommandLine
{
/// <summary>
/// Used for managing the <see cref="ITGSService"/> components
@@ -316,7 +316,7 @@ namespace TGCommandLine
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.RemoteAccessPort"/>
/// Command for calling <see cref="TGS.Interface.Components.ITGSService.RemoteAccessPort"/>
/// </summary>
class ServiceRemoteAccessPortCommand : ConsoleCommand
{
@@ -343,7 +343,7 @@ namespace TGCommandLine
}
/// <summary>
/// Command for calling <see cref="TGServiceInterface.Components.ITGSService.SetRemoteAccessPort(ushort)"/>
/// Command for calling <see cref="TGS.Interface.Components.ITGSService.SetRemoteAccessPort(ushort)"/>
/// </summary>
class ServiceSetRemoteAccessPortCommand : ConsoleCommand
{
@@ -6,7 +6,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{89191F69-B18E-4B59-B72E-E12F9B6811A0}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>TGCommandLine</RootNamespace>
<RootNamespace>TGS.CommandLine</RootNamespace>
<AssemblyName>TGCommandLine</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
@@ -31,7 +31,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>bin\x86\Release\TGCommandLine.xml</DocumentationFile>
<DocumentationFile>bin\x86\Release\TGS.CommandLine.xml</DocumentationFile>
<Optimize>true</Optimize>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>pdbonly</DebugType>
@@ -63,9 +63,9 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGServiceInterface\TGServiceInterface.csproj">
<ProjectReference Include="..\TGS.Interface\TGS.Interface.csproj">
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Name>TGServiceInterface</Name>
<Name>TGS.Interface</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

@@ -3,8 +3,8 @@
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="TGControlPanel.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="TGControlPanel.Properties.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="TGS.ControlPanel.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="TGS.ControlPanel.Properties.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="TGStationServer3.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
@@ -13,7 +13,7 @@
</startup>
<userSettings>
<TGControlPanel.Properties.Settings>
<TGS.ControlPanel.Properties.Settings>
<setting name="LastPageIndex" serializeAs="String">
<value>0</value>
</setting>
@@ -50,12 +50,12 @@
<setting name="GitHubAPIKeyEntropy" serializeAs="String">
<value />
</setting>
</TGControlPanel.Properties.Settings>
<TGControlPanel.Properties.Settings1>
</TGS.ControlPanel.Properties.Settings>
<TGS.ControlPanel.Properties.Settings1>
<setting name="LastPageIndex" serializeAs="String">
<value>0</value>
</setting>
</TGControlPanel.Properties.Settings1>
</TGS.ControlPanel.Properties.Settings1>
<TGStationServer3.Properties.Settings>
<setting name="RepoURL" serializeAs="String">
<value>https://github.com/tgstation/tgstation.git</value>
@@ -1,9 +1,9 @@
using System;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class ControlPanel
{
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class ControlPanel
{
@@ -1,4 +1,4 @@
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class ControlPanel
{
@@ -2,10 +2,10 @@
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
/// <summary>
/// The main <see cref="ControlPanel"/> form
@@ -18,15 +18,15 @@ namespace TGControlPanel
public static IDictionary<string, ControlPanel> InstancesInUse { get; private set; } = new Dictionary<string, ControlPanel>();
/// <summary>
/// The <see cref="IInterface"/> instance for this <see cref="ControlPanel"/>
/// The <see cref="IServerInterface"/> instance for this <see cref="ControlPanel"/>
/// </summary>
readonly IInterface Interface;
readonly IServerInterface Interface;
/// <summary>
/// Constructs a <see cref="ControlPanel"/>
/// </summary>
/// <param name="I">The <see cref="IInterface"/> for the <see cref="ControlPanel"/></param>
public ControlPanel(IInterface I)
/// <param name="I">The <see cref="IServerInterface"/> for the <see cref="ControlPanel"/></param>
public ControlPanel(IServerInterface I)
{
InitializeComponent();
FormClosed += ControlPanel_FormClosed;
@@ -2,10 +2,10 @@
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class ControlPanel
{
@@ -5,10 +5,10 @@ using System.ComponentModel;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class ControlPanel
{
@@ -2,10 +2,10 @@
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class ControlPanel
{
@@ -1,6 +1,6 @@
using System.Windows.Forms;
namespace TGControlPanel
namespace TGS.ControlPanel
{
/// <summary>
/// Calls <see cref="Application.Exit()"/> when all <see cref="CountedForm"/>s are <see cref="Form.Close"/>d
@@ -1,4 +1,4 @@
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class GitHubLoginPrompt
{
@@ -2,9 +2,9 @@
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGServiceInterface;
using TGS.Interface;
namespace TGControlPanel
namespace TGS.ControlPanel
{
/// <summary>
/// Used for recieving a GitHub API key for use in <see cref="Credentials"/>
@@ -76,7 +76,7 @@ namespace TGControlPanel
try
{
client.Credentials = new Credentials(UsernameTextBox.Text, PasswordTextBox.Text);
var token = await client.Authorization.Create(new NewAuthorization { Note = "TGControlPanel token to bypass rate limiting" });
var token = await client.Authorization.Create(new NewAuthorization { Note = "TGS.ControlPanel token to bypass rate limiting" });
APIKey = token.Token;
}
catch (AuthorizationException)
@@ -1,4 +1,4 @@
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class InstanceSelector
{
@@ -2,10 +2,10 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
/// <summary>
/// Form used for managing <see cref="ITGSService"/> <see cref="ITGInstance"/> manipulation functions
@@ -13,9 +13,9 @@ namespace TGControlPanel
sealed partial class InstanceSelector : CountedForm
{
/// <summary>
/// The <see cref="IInterface"/> we build instance connections from
/// The <see cref="IServerInterface"/> we build instance connections from
/// </summary>
readonly IInterface masterInterface;
readonly IServerInterface masterInterface;
/// <summary>
/// List of <see cref="InstanceMetadata"/> from <see cref="masterInterface"/>
/// </summary>
@@ -28,8 +28,8 @@ namespace TGControlPanel
/// <summary>
/// Construct an <see cref="InstanceSelector"/>
/// </summary>
/// <param name="I">An <see cref="IInterface"/> connected a the <see cref="ITGSService"/></param>
public InstanceSelector(IInterface I)
/// <param name="I">An <see cref="IServerInterface"/> connected a the <see cref="ITGSService"/></param>
public InstanceSelector(IServerInterface I)
{
InitializeComponent();
InstanceListBox.MouseDoubleClick += InstanceListBox_MouseDoubleClick;
@@ -100,7 +100,7 @@ namespace TGControlPanel
activeCP.BringToFront();
return;
}
var InstanceAccessor = new Interface(masterInterface as Interface);
var InstanceAccessor = new ServerInterface(masterInterface as ServerInterface);
try
{
ConnectivityLevel res = ConnectivityLevel.None;
@@ -1,4 +1,4 @@
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class Login
{
@@ -1,8 +1,8 @@
using System;
using System.Windows.Forms;
using TGServiceInterface;
using TGS.Interface;
namespace TGControlPanel
namespace TGS.ControlPanel
{
sealed partial class Login : CountedForm
{
@@ -31,7 +31,7 @@ namespace TGControlPanel
{
IPTextBox.Text = IPTextBox.Text.Trim();
UsernameTextBox.Text = UsernameTextBox.Text.Trim();
using (var I = new Interface(IPTextBox.Text, (ushort)PortSelector.Value, UsernameTextBox.Text, PasswordTextBox.Text))
using (var I = new ServerInterface(IPTextBox.Text, (ushort)PortSelector.Value, UsernameTextBox.Text, PasswordTextBox.Text))
{
var Config = Properties.Settings.Default;
Config.RemoteIP = IPTextBox.Text;
@@ -55,10 +55,10 @@ namespace TGControlPanel
private void LocalLoginButton_Click(object sender, EventArgs e)
{
Properties.Settings.Default.RemoteDefault = false;
VerifyAndConnect(new Interface());
VerifyAndConnect(new ServerInterface());
}
void VerifyAndConnect(IInterface I)
void VerifyAndConnect(IServerInterface I)
{
try
{
@@ -1,9 +1,9 @@
using System;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
static class Program
{
@@ -20,7 +20,7 @@ namespace TGControlPanel
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Interface.SetBadCertificateHandler(BadCertificateHandler);
ServerInterface.SetBadCertificateHandler(BadCertificateHandler);
var login = new Login();
login.Show();
Application.Run();
@@ -1,16 +1,16 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Control Panel")]
[assembly: AssemblyDescription("Control panel for the TG Station Server Service")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("394e7643-6b8c-416f-ab18-95ac12648cdc")]
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Control Panel")]
[assembly: AssemblyDescription("Control panel for the TG Station Server Service")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("394e7643-6b8c-416f-ab18-95ac12648cdc")]
@@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace TGControlPanel.Properties {
namespace TGS.ControlPanel.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TGControlPanel.Properties" GeneratedClassName="Settings">
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="TGS.ControlPanel.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="LastPageIndex" Type="System.Int32" Scope="User">
@@ -2,10 +2,10 @@
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TGControlPanel
namespace TGS.ControlPanel
{
/// <summary>
/// Used to provide an ATP function for calls into an <see cref="TGServiceInterface.IInterface"/>
/// Used to provide an ATP function for calls into an <see cref="TGS.Interface.IServerInterface"/>
/// </summary>
#if !DEBUG
abstract class ServerOpForm : Form
@@ -14,9 +14,9 @@ namespace TGControlPanel
#endif
{
/// <summary>
/// Used to wrap <see cref="TGServiceInterface.IInterface"/> calls in a non-blocking fashion while disabling the <see cref="Form"/> and enabling the wait cursor
/// Used to wrap <see cref="TGS.Interface.IServerInterface"/> calls in a non-blocking fashion while disabling the <see cref="Form"/> and enabling the wait cursor
/// </summary>
/// <param name="action">The <see cref="TGServiceInterface.IInterface"/> operation to wrap</param>
/// <param name="action">The <see cref="TGS.Interface.IServerInterface"/> operation to wrap</param>
/// <returns>A <see cref="Task"/> wrapping <paramref name="action"/></returns>
protected Task WrapServerOp(Action action)
{
@@ -6,7 +6,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{394E7643-6B8C-416F-AB18-95AC12648CDC}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>TGControlPanel</RootNamespace>
<RootNamespace>TGS.ControlPanel</RootNamespace>
<AssemblyName>TGControlPanel</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
@@ -30,7 +30,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>bin\x86\Release\TGControlPanel.xml</DocumentationFile>
<DocumentationFile>bin\x86\Release\TGS.ControlPanel.xml</DocumentationFile>
<Optimize>true</Optimize>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>pdbonly</DebugType>
@@ -139,9 +139,9 @@
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGServiceInterface\TGServiceInterface.csproj">
<ProjectReference Include="..\TGS.Interface\TGS.Interface.csproj">
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Name>TGServiceInterface</Name>
<Name>TGS.Interface</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
@@ -1,4 +1,4 @@
namespace TGControlPanel
namespace TGS.ControlPanel
{
partial class TestMergeManager
{
@@ -4,10 +4,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGControlPanel
namespace TGS.ControlPanel
{
sealed partial class TestMergeManager : ServerOpForm
{
@@ -17,9 +17,9 @@ namespace TGControlPanel
const string MergedPullsError = "Error retrieving currently merged pull requests: {0}";
/// <summary>
/// The <see cref="IInterface"/> connected to an <see cref="ITGInstance"/> to handle the pull requests for
/// The <see cref="IServerInterface"/> connected to an <see cref="ITGInstance"/> to handle the pull requests for
/// </summary>
readonly IInterface currentInterface;
readonly IServerInterface currentInterface;
/// <summary>
/// The <see cref="GitHubClient"/> to use to read PR lists
@@ -38,9 +38,9 @@ namespace TGControlPanel
/// <summary>
/// Construct a <see cref="TestMergeManager"/>
/// </summary>
/// <param name="interfaceToUse">The <see cref="IInterface"/> to use for managing the <see cref="ITGInstance"/></param>
/// <param name="interfaceToUse">The <see cref="IServerInterface"/> to use for managing the <see cref="ITGInstance"/></param>
/// <param name="clientToUse">The <see cref="GitHubClient"/> to use for getting pull request information</param>
public TestMergeManager(IInterface interfaceToUse, GitHubClient clientToUse)
public TestMergeManager(IServerInterface interfaceToUse, GitHubClient clientToUse)
{
InitializeComponent();
DialogResult = DialogResult.Cancel;

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

@@ -2,7 +2,7 @@
using System.Diagnostics;
using System.Reflection;
namespace TGInstallerWrapper
namespace TGS.Installer.UI
{
partial class Main
{
@@ -6,10 +6,11 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
using TGS.Server;
namespace TGInstallerWrapper
namespace TGS.Installer.UI
{
partial class Main : Form
{
@@ -19,8 +20,17 @@ namespace TGInstallerWrapper
bool installing = false;
bool cancelled = false;
bool pathIsDefault = true;
/// <summary>
/// If we should attempt to make a <see cref="ServerConfig"/> for the new install
/// </summary>
bool attemptNetSettingsMigration = false;
/// <summary>
/// If the service we are upgrading is confirmed to be less than version 3.2
/// </summary>
bool isUnderV2 = false;
IInterface Interface;
IServerInterface Interface;
/// <summary>
/// Construct an installer form
@@ -69,17 +79,21 @@ namespace TGInstallerWrapper
}
void CheckForExistingVersion() {
Interface = new Interface();
Interface = new ServerInterface();
var verifiedConnection = Interface.ConnectionStatus().HasFlag(ConnectivityLevel.Administrator);
try
{
VersionLabel.Text = Interface.GetServiceComponent<ITGSService>().Version();
var isV0 = VersionLabel.Text.Contains("v3.0");
var splits = VersionLabel.Text.Split(' ');
var realVersion = new Version(splits[splits.Length - 1].Substring(1));
var isV0 = realVersion < new Version(3, 1, 0, 0);
if (isV0) //OH GOD!!!!
MessageBox.Show("Upgrading from version 3.0 may trigger a bug that can delete /config and /data. IT IS STRONGLY RECCOMMENDED THAT YOU BACKUP THESE FOLDERS BEFORE UPDATING!", "Warning");
if (isV0 || VersionLabel.Text.Contains("v3.1"))
isUnderV2 = isV0 || realVersion < new Version(3, 2, 0, 0);
if (isUnderV2)
//Friendly reminger
MessageBox.Show("Upgrading to service version 3.2 will break the 3.1 DMAPI. It is recommended you update your game to the 3.2 API before updating the servive to avoid having to trigger hard restarts.", "Note");
attemptNetSettingsMigration = realVersion < new Version(3, 2, 1, 0);
}
catch
{
@@ -142,6 +156,39 @@ namespace TGInstallerWrapper
return PKillType.NoneFound;
}
/// <summary>
/// Migrate to the new <see cref="ServerConfig"/> since the <see cref="Server.Server"/> won't know about it until it's upgraded
/// </summary>
void AttemptMigrationOfNetSettings()
{
if (!attemptNetSettingsMigration)
return;
var sc = new ServerConfig();
try
{
sc.PythonPath = Interface.GetServiceComponent<ITGSService>().PythonPath();
}
catch { }
try
{
sc.RemoteAccessPort = Interface.GetServiceComponent<ITGSService>().RemoteAccessPort();
}
catch { }
try
{
foreach (var I in Interface.GetServiceComponent<ITGLanding>().ListInstances())
sc.InstancePaths.Add(I.Path);
}
catch { }
if (sc.InstancePaths.Count == 0 && isUnderV2)
//add the default ip as a last resort
sc.InstancePaths.Add("C:\\TGSTATION-SERVER-3"); //normalized
sc.Save(Server.Server.MigrationConfigDirectory);
}
async void DoInstall()
{
string logfile = null;
@@ -149,12 +196,12 @@ namespace TGInstallerWrapper
{
while (true)
{
var res = PromptKillProcesses("TGCommandLine");
var res = PromptKillProcesses("TGS.CommandLine");
if (res == PKillType.Aborted)
return;
else if (res == PKillType.Killed)
continue;
res = PromptKillProcesses("TGControlPanel");
res = PromptKillProcesses("TGS.ControlPanel");
if (res == PKillType.Aborted)
return;
else if (res == PKillType.Killed)
@@ -183,8 +230,10 @@ namespace TGInstallerWrapper
ShowLogCheckbox.Enabled = false;
InstallButton.Text = "Installing...";
var msipath = Path.Combine(tempDir, "TGServiceInstaller.msi");
File.WriteAllBytes(msipath, Properties.Resources.TGServiceInstaller);
AttemptMigrationOfNetSettings();
var msipath = Path.Combine(tempDir, "TGS.Installer.msi");
File.WriteAllBytes(msipath, Properties.Resources.TGSInstaller);
File.WriteAllBytes(Path.Combine(tempDir, "cab1.cab"), Properties.Resources.cab1);
ProgressBar.Style = ProgressBarStyle.Marquee;
@@ -193,13 +242,13 @@ namespace TGInstallerWrapper
if (ShowLogCheckbox.Checked)
{
logfile = Path.Combine(tempDir, "tgsinstall.log");
Installer.EnableLog(InstallLogModes.Verbose | InstallLogModes.PropertyDump, logfile);
Microsoft.Deployment.WindowsInstaller.Installer.EnableLog(InstallLogModes.Verbose | InstallLogModes.PropertyDump, logfile);
}
var cl = String.Join(" ", args);
Installer.SetInternalUI(InstallUIOptions.Silent);
Installer.SetExternalUI(OnUIUpdate, InstallLogModes.Progress);
Microsoft.Deployment.WindowsInstaller.Installer.SetInternalUI(InstallUIOptions.Silent);
Microsoft.Deployment.WindowsInstaller.Installer.SetExternalUI(OnUIUpdate, InstallLogModes.Progress);
await Task.Factory.StartNew(() => Installer.InstallProduct(msipath, cl));
await Task.Factory.StartNew(() => Microsoft.Deployment.WindowsInstaller.Installer.InstallProduct(msipath, cl));
if (cancelled)
{
@@ -1,7 +1,7 @@
using System;
using System.Windows.Forms;
namespace TGInstallerWrapper
namespace TGS.Installer.UI
{
static class Program
{
@@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace TGInstallerWrapper.Properties {
namespace TGS.Installer.UI.Properties {
using System;
@@ -39,7 +39,7 @@ namespace TGInstallerWrapper.Properties {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TGInstallerWrapper.Properties.Resources", typeof(Resources).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TGS.Installer.UI.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
@@ -73,9 +73,9 @@ namespace TGInstallerWrapper.Properties {
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] TGServiceInstaller {
internal static byte[] TGSInstaller {
get {
object obj = ResourceManager.GetObject("TGServiceInstaller", resourceCulture);
object obj = ResourceManager.GetObject("TGSInstaller", resourceCulture);
return ((byte[])(obj));
}
}
@@ -119,9 +119,9 @@
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="cab1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\TGServiceInstaller\bin\Release\cab1.cab;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<value>..\..\TGS.Installer\bin\Release\cab1.cab;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="TGServiceInstaller" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\TGServiceInstaller\bin\Release\TGServiceInstaller.msi;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
<data name="TGSInstaller" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\TGS.Installer\bin\Release\TGServiceInstaller.msi;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
@@ -6,7 +6,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8956D4C3-BFB9-448E-BF5F-EE7E6F9996F9}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>TGInstallerWrapper</RootNamespace>
<RootNamespace>TGS.Installer.UI</RootNamespace>
<AssemblyName>TG Station Server Installer</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
@@ -89,9 +89,13 @@
<Content Include="tgs.ico" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGServiceInterface\TGServiceInterface.csproj">
<ProjectReference Include="..\TGS.Interface\TGS.Interface.csproj">
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Name>TGServiceInterface</Name>
<Name>TGS.Interface</Name>
</ProjectReference>
<ProjectReference Include="..\TGS.Server\TGS.Server.csproj">
<Project>{f32eda25-0855-411c-af5e-f0d042917e2d}</Project>
<Name>TGS.Server</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

@@ -1,152 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="TG Station Server" Language="1033" Version="!(bind.FileVersion.ServiceExecutable)" Manufacturer="/tg/station 13" UpgradeCode="663badae-ddca-4aa9-8f3f-3b7b20332eac">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="TGServiceInstaller" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="StartMenuShortcuts" />
<ComponentGroupRef Id="DesktopShortcuts" />
<ComponentGroupRef Id="Gitx86Components" />
<ComponentGroupRef Id="Gitx64Components" />
</Feature>
<Icon Id="tgs.ico" SourceFile="..\tgs.ico"/>
<Property Id="ARPPRODUCTICON" Value="tgs.ico" />
<Property Id="INSTALLSHORTCUTDESK" Value="0" />
<Property Id="INSTALLSHORTCUTSTART" Value="0" />
<InstallExecuteSequence>
<RemoveShortcuts>Installed AND NOT UPGRADINGPRODUCTCODE</RemoveShortcuts>
</InstallExecuteSequence>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="TG Station Server">
<Directory Id ="LibFolder" Name="lib">
<Directory Id ="Win32Folder" Name="win32">
<Directory Id ="x86Folder" Name="x86" />
<Directory Id ="x64Folder" Name="x64" />
</Directory>
</Directory>
</Directory>
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
<Directory Id="ProgramMenuFolder" Name="StartMenuDir">
<Directory Id="ApplicationProgramsFolder" Name="TG Station Server"/>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="StartMenuShortcuts" Directory="ApplicationProgramsFolder">
<Component Id="StartMenuShortcut" Guid="*">
<Condition>INSTALLSHORTCUTSTART = 1</Condition>
<Shortcut Id="StartMenuShortcutCL"
Name="TG Command Line"
Target="[!TGCommandLine.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<Shortcut Id="StartMenuShortcutCP"
Name="TG Control Panel"
Target="[!TGControlPanel.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<Shortcut Id="UninstallProduct"
Name="Uninstall TG Station Server"
Target="[SystemFolder]msiexec.exe"
Arguments="/x [ProductCode]"
Description="Uninstalls TG Station Server" />
<RemoveFolder Id="CleanUpSMShortCuts" Directory="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\TGStation\Server" Name="StartMenuShortcuts" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="DesktopShortcuts" Directory="DesktopFolder">
<Component Id="DesktopShortcut" Guid="*">
<Condition>INSTALLSHORTCUTDESK = 1</Condition>
<Shortcut Id="DesktopShortcutCL"
Name="TG Command Line"
Target="[!TGCommandLine.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<Shortcut Id="DesktopShortcutCP"
Name="TG Control Panel"
Target="[!TGControlPanel.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<RemoveFolder Id="CleanUpDKShortCuts" Directory="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\TGStation\Server" Name="DesktopShortcuts" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="TGCommandLine" Guid="*">
<File Source="$(var.TGCommandLine.TargetPath)" />
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="no" Part="last" Action="set" System="yes" />
</Component>
<Component Id="TGServerService" Guid="*">
<File Source="$(var.TGServerService.TargetPath)" Id="ServiceExecutable" />
<ServiceInstall Id="ServiceInstaller" Name="TG Station Server" Type="ownProcess" EraseDescription="no" ErrorControl="normal" Start="auto" Vital="yes" />
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="TG Station Server" Wait="yes" />
</Component>
<Component Id="DiscordNetCore" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/Discord.Net.Core.dll" />
</Component>
<Component Id="DiscordNetRest" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/Discord.Net.Rest.dll" />
</Component>
<Component Id="DiscordNetWebSocket" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/Discord.Net.WebSocket.dll" />
</Component>
<Component Id="LibGit2Sharp" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/LibGit2Sharp.dll" />
</Component>
<Component Id="Octokit" Guid="*">
<File Source="$(var.TGControlPanel.TargetDir)/Octokit.dll" />
</Component>
<Component Id="MeebeySmartIrc4net" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/Meebey.SmartIrc4net.dll" />
</Component>
<Component Id="NewtonsoftJson" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/Newtonsoft.Json.dll" />
</Component>
<Component Id="SystemCollectionsImmutable" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/System.Collections.Immutable.dll" />
</Component>
<Component Id="SystemInteractiveAsync" Guid="*">
<File Source="$(var.TGServerService.TargetDir)/System.Interactive.Async.dll" />
</Component>
<Component Id="TGControlPanel" Guid="*">
<File Source="$(var.TGControlPanel.TargetPath)" KeyPath="yes" />
</Component>
<Component Id="TGServiceInterface" Guid="*">
<File Source="$(var.TGServiceInterface.TargetPath)" />
</Component>
<Component Id="TGDreamDaemonBridge" Guid="*">
<File Source="$(var.TGDreamDaemonBridge.TargetPath)" />
</Component>
</ComponentGroup>
<ComponentGroup Id="Gitx86Components" Directory="x86Folder">
<Component Id="LibGit2Sharpx86" Guid="*">
<File Source="$(var.TGServerService.TargetDir)lib\win32\x86\git2-ssh-baa87df.dll" Id="LibGit2Sharpx86dll"/>
</Component>
<Component Id="LibGit2Sharpx86SSH" Guid="*">
<File Source="$(var.TGServerService.TargetDir)lib\win32\x86\libssh2.dll" Id="LibGit2Sharpx86SSHdll"/>
</Component>
<Component Id="LibGit2Sharpx86Z" Guid="*">
<File Source="$(var.TGServerService.TargetDir)lib\win32\x86\zlib.dll" Id="LibGit2Sharpx86Zdll"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="Gitx64Components" Directory="x64Folder">
<Component Id="LibGit2Sharpx64" Guid="*">
<File Source="$(var.TGServerService.TargetDir)lib\win32\x64\git2-ssh-baa87df.dll" Id="LibGit2Sharpx64dll" />
</Component>
<Component Id="LibGit2Sharpx64SSH" Guid="*">
<File Source="$(var.TGServerService.TargetDir)lib\win32\x64\libssh2.dll" Id="LibGit2Sharpx64SSHdll"/>
</Component>
<Component Id="LibGit2Sharpx64Z" Guid="*">
<File Source="$(var.TGServerService.TargetDir)lib\win32\x64\zlib.dll" Id="LibGit2Sharpx64Zdll"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="TG Station Server" Language="1033" Version="!(bind.FileVersion.ServiceExecutable)" Manufacturer="/tg/station 13" UpgradeCode="663badae-ddca-4aa9-8f3f-3b7b20332eac">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="TGS.Installer" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="StartMenuShortcuts" />
<ComponentGroupRef Id="DesktopShortcuts" />
<ComponentGroupRef Id="Gitx86Components" />
<ComponentGroupRef Id="Gitx64Components" />
</Feature>
<Icon Id="tgs.ico" SourceFile="..\tgs.ico"/>
<Property Id="ARPPRODUCTICON" Value="tgs.ico" />
<Property Id="INSTALLSHORTCUTDESK" Value="0" />
<Property Id="INSTALLSHORTCUTSTART" Value="0" />
<InstallExecuteSequence>
<RemoveShortcuts>Installed AND NOT UPGRADINGPRODUCTCODE</RemoveShortcuts>
</InstallExecuteSequence>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="TG Station Server">
<Directory Id ="LibFolder" Name="lib">
<Directory Id ="Win32Folder" Name="win32">
<Directory Id ="x86Folder" Name="x86" />
<Directory Id ="x64Folder" Name="x64" />
</Directory>
</Directory>
</Directory>
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
<Directory Id="ProgramMenuFolder" Name="StartMenuDir">
<Directory Id="ApplicationProgramsFolder" Name="TG Station Server"/>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="StartMenuShortcuts" Directory="ApplicationProgramsFolder">
<Component Id="StartMenuShortcut" Guid="*">
<Condition>INSTALLSHORTCUTSTART = 1</Condition>
<Shortcut Id="StartMenuShortcutCL"
Name="TG Command Line"
Target="[!TGCommandLine.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<Shortcut Id="StartMenuShortcutCP"
Name="TG Control Panel"
Target="[!TGControlPanel.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<Shortcut Id="UninstallProduct"
Name="Uninstall TG Station Server"
Target="[SystemFolder]msiexec.exe"
Arguments="/x [ProductCode]"
Description="Uninstalls TG Station Server" />
<RemoveFolder Id="CleanUpSMShortCuts" Directory="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\TGStation\Server" Name="StartMenuShortcuts" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="DesktopShortcuts" Directory="DesktopFolder">
<Component Id="DesktopShortcut" Guid="*">
<Condition>INSTALLSHORTCUTDESK = 1</Condition>
<Shortcut Id="DesktopShortcutCL"
Name="TG Command Line"
Target="[!TGCommandLine.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<Shortcut Id="DesktopShortcutCP"
Name="TG Control Panel"
Target="[!TGControlPanel.exe]"
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
<RemoveFolder Id="CleanUpDKShortCuts" Directory="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\TGStation\Server" Name="DesktopShortcuts" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="TGS.CommandLine" Guid="*">
<File Source="$(var.TGS.CommandLine.TargetPath)" />
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="no" Part="last" Action="set" System="yes" />
</Component>
<Component Id="TGS.Server" Guid="*">
<File Source="$(var.TGS.Server.TargetPath)" />
</Component>
<Component Id="TGS.Server.Service" Guid="*">
<File Source="$(var.TGS.Server.Service.TargetPath)" Id="ServiceExecutable" />
<ServiceInstall Id="ServiceInstaller" Name="TG Station Server" Type="ownProcess" EraseDescription="no" ErrorControl="normal" Start="auto" Vital="yes" />
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="TG Station Server" Wait="yes" />
</Component>
<Component Id="DiscordNetCore" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/Discord.Net.Core.dll" />
</Component>
<Component Id="DiscordNetRest" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/Discord.Net.Rest.dll" />
</Component>
<Component Id="DiscordNetWebSocket" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/Discord.Net.WebSocket.dll" />
</Component>
<Component Id="LibGit2Sharp" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/LibGit2Sharp.dll" />
</Component>
<Component Id="Octokit" Guid="*">
<File Source="$(var.TGS.ControlPanel.TargetDir)/Octokit.dll" />
</Component>
<Component Id="MeebeySmartIrc4net" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/Meebey.SmartIrc4net.dll" />
</Component>
<Component Id="NewtonsoftJson" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/Newtonsoft.Json.dll" />
</Component>
<Component Id="SystemCollectionsImmutable" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/System.Collections.Immutable.dll" />
</Component>
<Component Id="SystemInteractiveAsync" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)/System.Interactive.Async.dll" />
</Component>
<Component Id="TGS.ControlPanel" Guid="*">
<File Source="$(var.TGS.ControlPanel.TargetPath)" KeyPath="yes" />
</Component>
<Component Id="TGS.Interface" Guid="*">
<File Source="$(var.TGS.Interface.TargetPath)" />
</Component>
<Component Id="TGS.Interface.Bridge" Guid="*">
<File Source="$(var.TGS.Interface.Bridge.TargetPath)" />
</Component>
</ComponentGroup>
<ComponentGroup Id="Gitx86Components" Directory="x86Folder">
<Component Id="LibGit2Sharpx86" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x86\git2-ssh-baa87df.dll" Id="LibGit2Sharpx86dll"/>
</Component>
<Component Id="LibGit2Sharpx86SSH" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x86\libssh2.dll" Id="LibGit2Sharpx86SSHdll"/>
</Component>
<Component Id="LibGit2Sharpx86Z" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x86\zlib.dll" Id="LibGit2Sharpx86Zdll"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="Gitx64Components" Directory="x64Folder">
<Component Id="LibGit2Sharpx64" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x64\git2-ssh-baa87df.dll" Id="LibGit2Sharpx64dll" />
</Component>
<Component Id="LibGit2Sharpx64SSH" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x64\libssh2.dll" Id="LibGit2Sharpx64SSHdll"/>
</Component>
<Component Id="LibGit2Sharpx64Z" Guid="*">
<File Source="$(var.TGS.Server.TargetDir)lib\win32\x64\zlib.dll" Id="LibGit2Sharpx64Zdll"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>
@@ -1,90 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>154435f6-0890-42d4-9aec-b743d4fbc1cb</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>TGServiceInstaller</OutputName>
<OutputType>Package</OutputType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<SuppressPdbOutput>True</SuppressPdbOutput>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGControlPanel\TGControlPanel.csproj">
<Name>TGControlPanel</Name>
<Project>{394e7643-6b8c-416f-ab18-95ac12648cdc}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGCommandLine\TGCommandLine.csproj">
<Name>TGCommandLine</Name>
<Project>{89191f69-b18e-4b59-b72e-e12f9b6811a0}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGDreamDaemonBridge\TGDreamDaemonBridge.csproj">
<Name>TGDreamDaemonBridge</Name>
<Project>{9a01ef03-8eae-45cb-8b87-4a17bd904557}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGServerService\TGServerService.csproj">
<Name>TGServerService</Name>
<Project>{f32eda25-0855-411c-af5e-f0d042917e2d}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGServiceInterface\TGServiceInterface.csproj">
<Name>TGServiceInterface</Name>
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
</ItemGroup>
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="The WiX Toolset v3 build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
</Target>
<Target Name="AfterResolveReferences">
<Exec Command="$(PreBuildEventCommand)" />
</Target>
<PropertyGroup>
<PreBuildEventCommand>powershell -Command "&amp; \"$(SolutionDir)Tools/SignBasics.ps1\""</PreBuildEventCommand>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>powershell -Command "&amp; \"$(SolutionDir)Tools/SignMSI.ps1\""</PostBuildEvent>
</PropertyGroup>
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>154435f6-0890-42d4-9aec-b743d4fbc1cb</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>TGServiceInstaller</OutputName>
<OutputType>Package</OutputType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<SuppressPdbOutput>True</SuppressPdbOutput>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGS.ControlPanel\TGS.ControlPanel.csproj">
<Name>TGS.ControlPanel</Name>
<Project>{394e7643-6b8c-416f-ab18-95ac12648cdc}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGS.CommandLine\TGS.CommandLine.csproj">
<Name>TGS.CommandLine</Name>
<Project>{89191f69-b18e-4b59-b72e-e12f9b6811a0}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGS.Interface.Bridge\TGS.Interface.Bridge.csproj">
<Name>TGS.Interface.Bridge</Name>
<Project>{9a01ef03-8eae-45cb-8b87-4a17bd904557}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGS.Server.Service\TGS.Server.Service.csproj">
<Name>TGS.Server.Service</Name>
<Project>{3f81e398-b223-4006-b40c-c2800714ce29}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGS.Server\TGS.Server.csproj">
<Name>TGS.Server</Name>
<Project>{f32eda25-0855-411c-af5e-f0d042917e2d}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\TGS.Interface\TGS.Interface.csproj">
<Name>TGS.Interface</Name>
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
</ItemGroup>
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="The WiX Toolset v3 build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
</Target>
<Target Name="AfterResolveReferences">
<Exec Command="$(PreBuildEventCommand)" />
</Target>
<PropertyGroup>
<PreBuildEventCommand>powershell -Command "&amp; \"$(SolutionDir)Tools/SignBasics.ps1\""</PreBuildEventCommand>
</PropertyGroup>
<PropertyGroup>
<PostBuildEvent>powershell -Command "&amp; \"$(SolutionDir)Tools/SignMSI.ps1\""</PostBuildEvent>
</PropertyGroup>
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -2,10 +2,10 @@ using RGiesecke.DllExport;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using TGServiceInterface;
using TGServiceInterface.Components;
using TGS.Interface;
using TGS.Interface.Components;
namespace TGDreamDaemonBridge
namespace TGS.Interface.Bridge
{
/// <summary>
/// Holds the proc that DD calls to access <see cref="ITGInterop"/>
@@ -27,7 +27,7 @@ namespace TGDreamDaemonBridge
parsedArgs.AddRange(args);
var instance = parsedArgs[0];
parsedArgs.RemoveAt(0);
using (var I = new Interface())
using (var I = new ServerInterface())
if(I.ConnectToInstance(instance, true).HasFlag(ConnectivityLevel.Connected))
I.GetComponent<ITGInterop>().InteropMessage(String.Join(" ", parsedArgs));
}
@@ -7,7 +7,7 @@
<ProjectGuid>{9A01EF03-8EAE-45CB-8B87-4A17BD904557}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TGDreamDaemonBridge</RootNamespace>
<RootNamespace>TGS.Interface.Bridge</RootNamespace>
<AssemblyName>TGDreamDaemonBridge</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
@@ -59,9 +59,9 @@
<None Include="FodyWeavers.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGServiceInterface\TGServiceInterface.csproj">
<ProjectReference Include="..\TGS.Interface\TGS.Interface.csproj">
<Project>{ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab}</Project>
<Name>TGServiceInterface</Name>
<Name>TGS.Interface</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
@@ -1,344 +1,344 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Web.Script.Serialization;
namespace TGServiceInterface
{
/// <summary>
/// For setting up authentication no matter the chat provider
/// </summary>
[DataContract]
[KnownType(typeof(IRCSetupInfo))]
[KnownType(typeof(DiscordSetupInfo))]
public class ChatSetupInfo
{
const int AdminListIndex = 0;
const int AdminModeIndex = 1;
const int AdminChannelIndex = 2;
const int DevChannelIndex = 3;
const int WDChannelIndex = 4;
const int GameChannelIndex = 5;
const int ProviderIndex = 6;
const int EnabledIndex = 7;
/// <summary>
/// Starting index of <see cref="DataFields"/> which child classes should use to write their custom data to
/// </summary>
protected const int BaseIndex = 8;
/// <summary>
/// Set to <see langword="true"/> if a child constructor should use the baseInfo parameter of <see cref="ChatSetupInfo.ChatSetupInfo(ChatProvider, ChatSetupInfo, int)"/> to initialize it's property fields, <see langword="false"/> otherwise
/// </summary>
protected readonly bool InitializeFields;
/// <summary>
/// Raw access to the underlying data
/// </summary>
[DataMember]
public IList<string> DataFields { get; protected set; }
/// <summary>
/// Constructs a <see cref="ChatSetupInfo"/> from optional <paramref name="baseInfo"/>
/// </summary>
/// <param name="provider">The <see cref="ChatProvider"/> that this <see cref="ChatSetupInfo"/> is for</param>
/// <param name="baseInfo">Optional past data</param>
/// <param name="numFields">The number of fields in this chat provider</param>
protected internal ChatSetupInfo(ChatProvider provider, ChatSetupInfo baseInfo, int numFields)
{
numFields += BaseIndex;
InitializeFields = baseInfo == null || baseInfo.DataFields.Count != numFields;
if (InitializeFields)
{
DataFields = new List<string>(numFields);
for (var I = 0; I < numFields; ++I)
DataFields.Add(null);
AdminList = new List<string>();
AdminChannels = new List<string>();
DevChannels = new List<string>();
GameChannels = new List<string>();
WatchdogChannels = new List<string>();
AdminsAreSpecial = false;
Enabled = false;
}
else
DataFields = baseInfo.DataFields;
Provider = provider;
Specialize(true); //to check we have a valid provider
}
/// <summary>
/// Recreates <see langword="this"/> as the correct child <see cref="ChatSetupInfo"/>
/// </summary>
/// <param name="checkOnly">If <see langword="true"/>, <see langword="null"/> is returned provided <see cref="Provider"/> is a valid <see cref="ChatProvider"/></param>
/// <returns>A new <see cref="ChatSetupInfo"/> based on the <see cref="Provider"/> type</returns>
ChatSetupInfo Specialize(bool checkOnly)
{
switch (Provider)
{
case ChatProvider.IRC:
if (!checkOnly)
return new IRCSetupInfo(this);
break;
case ChatProvider.Discord:
if (!checkOnly)
return new DiscordSetupInfo(this);
break;
default:
throw new Exception("Invalid provider!");
}
return null;
}
/// <summary>
/// Properly formats a <paramref name="channel"/> name for the <see cref="ChatProvider"/>
/// </summary>
/// <param name="channel">The <see cref="string"/> to format</param>
/// <returns>The formatted <see cref="string"/></returns>
protected virtual string SanitizeChannelName(string channel)
{
return Specialize(false).SanitizeChannelName(channel);
}
/// <summary>
/// Sanitizes a list of <paramref name="channelnames"/>
/// </summary>
/// <param name="channelnames">A <see cref="List{T}"/> of strings</param>
void SanitizeChannelNames(IList<string> channelnames)
{
for (var I = 0; I < channelnames.Count; ++I)
if (String.IsNullOrWhiteSpace(channelnames[I]))
{
channelnames.RemoveAt(I);
--I;
}
else
channelnames[I] = SanitizeChannelName(channelnames[I].Trim());
}
/// <summary>
/// Constructs a <see cref="ChatSetupInfo"/> from a data list
/// </summary>
/// <param name="DeserializedData">The data</param>
public ChatSetupInfo(IList<string> DeserializedData)
{
DataFields = DeserializedData;
Specialize(false); //ensure provider type is valid
}
/// <summary>
/// The list of admin entries
/// </summary>
public List<string> AdminList
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[AdminListIndex]); }
set { DataFields[AdminListIndex] = new JavaScriptSerializer().Serialize(value); }
}
/// <summary>
/// If AdminList corresponds to a Provider specific recognization method
/// </summary>
public bool AdminsAreSpecial
{
get { return Convert.ToBoolean(DataFields[AdminModeIndex]); }
set { DataFields[AdminModeIndex] = Convert.ToString(value); }
}
/// <summary>
/// The channels from which admin commands/messages can be sent/received
/// </summary>
public List<string> AdminChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[AdminChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[AdminChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which repo and compile messages are sent
/// </summary>
public List<string> DevChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[DevChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[DevChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which watchdog messages are sent
/// </summary>
public List<string> WatchdogChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[WDChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[WDChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which game messages are sent
/// </summary>
public List<string> GameChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[GameChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[GameChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// If this chat provider is enabled
/// </summary>
public bool Enabled
{
get { return Convert.ToBoolean(DataFields[EnabledIndex]); }
set { DataFields[EnabledIndex] = Convert.ToString(value); }
}
/// <summary>
/// The type of provider
/// </summary>
public ChatProvider Provider
{
get { return (ChatProvider)Convert.ToInt32(DataFields[ProviderIndex]); }
set { DataFields[ProviderIndex] = Convert.ToString((int)value); }
}
}
/// <summary>
/// Chat provider for IRC. Admin entries should be user nicknames in normal mode or required channel flags in special mode
/// </summary>
[DataContract]
public sealed class IRCSetupInfo : ChatSetupInfo
{
const int URLIndex = 0;
const int PortIndex = 1;
const int NickIndex = 2;
const int AuthTargetIndex = 3;
const int AuthMessageIndex = 4;
const int AuthLevelIndex = 5;
const int FieldsLen = 6;
/// <summary>
/// Construct IRC setup info from optional generic info. Defaults to TGS3 on rizons IRC server
/// </summary>
/// <param name="baseInfo">Optional generic info</param>
public IRCSetupInfo(ChatSetupInfo baseInfo = null) : base(ChatProvider.IRC, baseInfo, FieldsLen)
{
if (!InitializeFields)
return;
Nickname = "TGS3";
URL = "irc.rizon.net";
Port = 6667;
AuthTarget = "";
AuthMessage = "";
AdminsAreSpecial = true;
AuthLevel = IRCMode.Op;
}
/// <inheritdoc />
protected override string SanitizeChannelName(string working)
{
if (working[0] != '#')
return "#" + working;
return working;
}
/// <summary>
/// The port of the IRC server
/// </summary>
public ushort Port
{
get { return Convert.ToUInt16(DataFields[BaseIndex + PortIndex]); }
set { DataFields[BaseIndex + PortIndex] = value.ToString(); }
}
/// <summary>
/// The URL of the IRC server
/// </summary>
public string URL
{
get { return DataFields[BaseIndex + URLIndex]; }
set { DataFields[BaseIndex + URLIndex] = value; }
}
/// <summary>
/// The nickname of the IRC bot
/// </summary>
public string Nickname
{
get { return DataFields[BaseIndex + NickIndex]; }
set { DataFields[BaseIndex + NickIndex] = value; }
}
/// <summary>
/// The target for sending authentication messages
/// </summary>
public string AuthTarget
{
get { return DataFields[BaseIndex + AuthTargetIndex]; }
set { DataFields[BaseIndex + AuthTargetIndex] = value; }
}
/// <summary>
/// The authentication message
/// </summary>
public string AuthMessage
{
get { return DataFields[BaseIndex + AuthMessageIndex]; }
set { DataFields[BaseIndex + AuthMessageIndex] = value; }
}
/// <summary>
/// The minimum mode required to use admin bot commands when in special auth mode
/// </summary>
public IRCMode AuthLevel
{
get { return (IRCMode)Convert.ToInt32(DataFields[BaseIndex + AuthLevelIndex]); }
set { DataFields[BaseIndex + AuthLevelIndex] = Convert.ToString((int)value); }
}
}
/// <summary>
/// Chat provider for Discord. Admin entires should be user ids in normal mode or group ids in special mode
/// </summary>
[DataContract]
public sealed class DiscordSetupInfo : ChatSetupInfo
{
const int BotTokenIndex = 0;
const int FieldsLen = 1;
/// <summary>
/// Construct Discord setup info from optional generic info. Default is not a valid discord bot tokent
/// </summary>
/// <param name="baseInfo">Optional generic info</param>
public DiscordSetupInfo(ChatSetupInfo baseInfo = null) : base(ChatProvider.Discord, baseInfo, FieldsLen)
{
if (!InitializeFields)
return;
BotToken = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; //needless to say, this is fake
}
/// <inheritdoc />
protected override string SanitizeChannelName(string working)
{
working = working.Replace("<", "").Replace(">", "").Replace("&", ""); //filter out some stuff that can come in the copypasta
try
{
Convert.ToUInt64(working);
}
catch
{
throw new Exception("Invalid Discord channel ID!");
}
return working;
}
/// <summary>
/// The Discord bot token to use. See https://discordapp.com/developers/applications/me for registering bot accounts
/// </summary>
public string BotToken
{
get { return DataFields[BaseIndex + BotTokenIndex]; }
set { DataFields[BaseIndex + BotTokenIndex] = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Web.Script.Serialization;
namespace TGS.Interface
{
/// <summary>
/// For setting up authentication no matter the chat provider
/// </summary>
[DataContract]
[KnownType(typeof(IRCSetupInfo))]
[KnownType(typeof(DiscordSetupInfo))]
public class ChatSetupInfo
{
const int AdminListIndex = 0;
const int AdminModeIndex = 1;
const int AdminChannelIndex = 2;
const int DevChannelIndex = 3;
const int WDChannelIndex = 4;
const int GameChannelIndex = 5;
const int ProviderIndex = 6;
const int EnabledIndex = 7;
/// <summary>
/// Starting index of <see cref="DataFields"/> which child classes should use to write their custom data to
/// </summary>
protected const int BaseIndex = 8;
/// <summary>
/// Set to <see langword="true"/> if a child constructor should use the baseInfo parameter of <see cref="ChatSetupInfo.ChatSetupInfo(ChatProvider, ChatSetupInfo, int)"/> to initialize it's property fields, <see langword="false"/> otherwise
/// </summary>
protected readonly bool InitializeFields;
/// <summary>
/// Raw access to the underlying data
/// </summary>
[DataMember]
public IList<string> DataFields { get; protected set; }
/// <summary>
/// Constructs a <see cref="ChatSetupInfo"/> from optional <paramref name="baseInfo"/>
/// </summary>
/// <param name="provider">The <see cref="ChatProvider"/> that this <see cref="ChatSetupInfo"/> is for</param>
/// <param name="baseInfo">Optional past data</param>
/// <param name="numFields">The number of fields in this chat provider</param>
protected internal ChatSetupInfo(ChatProvider provider, ChatSetupInfo baseInfo, int numFields)
{
numFields += BaseIndex;
InitializeFields = baseInfo == null || baseInfo.DataFields.Count != numFields;
if (InitializeFields)
{
DataFields = new List<string>(numFields);
for (var I = 0; I < numFields; ++I)
DataFields.Add(null);
AdminList = new List<string>();
AdminChannels = new List<string>();
DevChannels = new List<string>();
GameChannels = new List<string>();
WatchdogChannels = new List<string>();
AdminsAreSpecial = false;
Enabled = false;
}
else
DataFields = baseInfo.DataFields;
Provider = provider;
Specialize(true); //to check we have a valid provider
}
/// <summary>
/// Recreates <see langword="this"/> as the correct child <see cref="ChatSetupInfo"/>
/// </summary>
/// <param name="checkOnly">If <see langword="true"/>, <see langword="null"/> is returned provided <see cref="Provider"/> is a valid <see cref="ChatProvider"/></param>
/// <returns>A new <see cref="ChatSetupInfo"/> based on the <see cref="Provider"/> type</returns>
ChatSetupInfo Specialize(bool checkOnly)
{
switch (Provider)
{
case ChatProvider.IRC:
if (!checkOnly)
return new IRCSetupInfo(this);
break;
case ChatProvider.Discord:
if (!checkOnly)
return new DiscordSetupInfo(this);
break;
default:
throw new Exception("Invalid provider!");
}
return null;
}
/// <summary>
/// Properly formats a <paramref name="channel"/> name for the <see cref="ChatProvider"/>
/// </summary>
/// <param name="channel">The <see cref="string"/> to format</param>
/// <returns>The formatted <see cref="string"/></returns>
protected virtual string SanitizeChannelName(string channel)
{
return Specialize(false).SanitizeChannelName(channel);
}
/// <summary>
/// Sanitizes a list of <paramref name="channelnames"/>
/// </summary>
/// <param name="channelnames">A <see cref="List{T}"/> of strings</param>
void SanitizeChannelNames(IList<string> channelnames)
{
for (var I = 0; I < channelnames.Count; ++I)
if (String.IsNullOrWhiteSpace(channelnames[I]))
{
channelnames.RemoveAt(I);
--I;
}
else
channelnames[I] = SanitizeChannelName(channelnames[I].Trim());
}
/// <summary>
/// Constructs a <see cref="ChatSetupInfo"/> from a data list
/// </summary>
/// <param name="DeserializedData">The data</param>
public ChatSetupInfo(IList<string> DeserializedData)
{
DataFields = DeserializedData;
Specialize(false); //ensure provider type is valid
}
/// <summary>
/// The list of admin entries
/// </summary>
public List<string> AdminList
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[AdminListIndex]); }
set { DataFields[AdminListIndex] = new JavaScriptSerializer().Serialize(value); }
}
/// <summary>
/// If AdminList corresponds to a Provider specific recognization method
/// </summary>
public bool AdminsAreSpecial
{
get { return Convert.ToBoolean(DataFields[AdminModeIndex]); }
set { DataFields[AdminModeIndex] = Convert.ToString(value); }
}
/// <summary>
/// The channels from which admin commands/messages can be sent/received
/// </summary>
public List<string> AdminChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[AdminChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[AdminChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which repo and compile messages are sent
/// </summary>
public List<string> DevChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[DevChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[DevChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which watchdog messages are sent
/// </summary>
public List<string> WatchdogChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[WDChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[WDChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// The channels to which game messages are sent
/// </summary>
public List<string> GameChannels
{
get { return new JavaScriptSerializer().Deserialize<List<string>>(DataFields[GameChannelIndex]); }
set
{
SanitizeChannelNames(value);
DataFields[GameChannelIndex] = new JavaScriptSerializer().Serialize(value);
}
}
/// <summary>
/// If this chat provider is enabled
/// </summary>
public bool Enabled
{
get { return Convert.ToBoolean(DataFields[EnabledIndex]); }
set { DataFields[EnabledIndex] = Convert.ToString(value); }
}
/// <summary>
/// The type of provider
/// </summary>
public ChatProvider Provider
{
get { return (ChatProvider)Convert.ToInt32(DataFields[ProviderIndex]); }
set { DataFields[ProviderIndex] = Convert.ToString((int)value); }
}
}
/// <summary>
/// Chat provider for IRC. Admin entries should be user nicknames in normal mode or required channel flags in special mode
/// </summary>
[DataContract]
public sealed class IRCSetupInfo : ChatSetupInfo
{
const int URLIndex = 0;
const int PortIndex = 1;
const int NickIndex = 2;
const int AuthTargetIndex = 3;
const int AuthMessageIndex = 4;
const int AuthLevelIndex = 5;
const int FieldsLen = 6;
/// <summary>
/// Construct IRC setup info from optional generic info. Defaults to TGS3 on rizons IRC server
/// </summary>
/// <param name="baseInfo">Optional generic info</param>
public IRCSetupInfo(ChatSetupInfo baseInfo = null) : base(ChatProvider.IRC, baseInfo, FieldsLen)
{
if (!InitializeFields)
return;
Nickname = "TGS3";
URL = "irc.rizon.net";
Port = 6667;
AuthTarget = "";
AuthMessage = "";
AdminsAreSpecial = true;
AuthLevel = IRCMode.Op;
}
/// <inheritdoc />
protected override string SanitizeChannelName(string working)
{
if (working[0] != '#')
return "#" + working;
return working;
}
/// <summary>
/// The port of the IRC server
/// </summary>
public ushort Port
{
get { return Convert.ToUInt16(DataFields[BaseIndex + PortIndex]); }
set { DataFields[BaseIndex + PortIndex] = value.ToString(); }
}
/// <summary>
/// The URL of the IRC server
/// </summary>
public string URL
{
get { return DataFields[BaseIndex + URLIndex]; }
set { DataFields[BaseIndex + URLIndex] = value; }
}
/// <summary>
/// The nickname of the IRC bot
/// </summary>
public string Nickname
{
get { return DataFields[BaseIndex + NickIndex]; }
set { DataFields[BaseIndex + NickIndex] = value; }
}
/// <summary>
/// The target for sending authentication messages
/// </summary>
public string AuthTarget
{
get { return DataFields[BaseIndex + AuthTargetIndex]; }
set { DataFields[BaseIndex + AuthTargetIndex] = value; }
}
/// <summary>
/// The authentication message
/// </summary>
public string AuthMessage
{
get { return DataFields[BaseIndex + AuthMessageIndex]; }
set { DataFields[BaseIndex + AuthMessageIndex] = value; }
}
/// <summary>
/// The minimum mode required to use admin bot commands when in special auth mode
/// </summary>
public IRCMode AuthLevel
{
get { return (IRCMode)Convert.ToInt32(DataFields[BaseIndex + AuthLevelIndex]); }
set { DataFields[BaseIndex + AuthLevelIndex] = Convert.ToString((int)value); }
}
}
/// <summary>
/// Chat provider for Discord. Admin entires should be user ids in normal mode or group ids in special mode
/// </summary>
[DataContract]
public sealed class DiscordSetupInfo : ChatSetupInfo
{
const int BotTokenIndex = 0;
const int FieldsLen = 1;
/// <summary>
/// Construct Discord setup info from optional generic info. Default is not a valid discord bot tokent
/// </summary>
/// <param name="baseInfo">Optional generic info</param>
public DiscordSetupInfo(ChatSetupInfo baseInfo = null) : base(ChatProvider.Discord, baseInfo, FieldsLen)
{
if (!InitializeFields)
return;
BotToken = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; //needless to say, this is fake
}
/// <inheritdoc />
protected override string SanitizeChannelName(string working)
{
working = working.Replace("<", "").Replace(">", "").Replace("&", ""); //filter out some stuff that can come in the copypasta
try
{
Convert.ToUInt64(working);
}
catch
{
throw new Exception("Invalid Discord channel ID!");
}
return working;
}
/// <summary>
/// The Discord bot token to use. See https://discordapp.com/developers/applications/me for registering bot accounts
/// </summary>
public string BotToken
{
get { return DataFields[BaseIndex + BotTokenIndex]; }
set { DataFields[BaseIndex + BotTokenIndex] = value; }
}
}
}
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Threading;
namespace TGServiceInterface
namespace TGS.Interface
{
/// <summary>
/// Helper for creating a text <see cref="Command"/> tree
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Manage the group that is used to access the service, can only be used by an administrator
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Interface for handling chat bot
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// For managing the Game A/B/Live folders, compiling, and hotswapping them
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// For modifying the in game config
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Used for testing connections to the service without authentication
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Metadata for a server instance
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Used for managing <see cref="ITGInstance"/>s
@@ -1,6 +1,6 @@
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Used by DreamDaemon to access the interop API with call()(). Restrictions are in place so that only a DreamDaemon instance launched by the service can use this API
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Used for general authentication and listing <see cref="ITGInstance"/>s
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Interface for managing the code repository
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.ServiceModel;
namespace TGServiceInterface.Components
namespace TGS.Interface.Components
{
/// <summary>
/// Interface for managing the service
@@ -1,6 +1,6 @@
using System;
namespace TGServiceInterface
namespace TGS.Interface
{
/// <summary>
/// Description of the connectivity level to an <see cref="Components.ITGInstance"/> or the <see cref="Components.ITGSService"/>
@@ -2,7 +2,7 @@
using System.Security.Cryptography;
using System.Text;
namespace TGServiceInterface
namespace TGS.Interface
{
/// <summary>
/// Helper functions used across the server suite
@@ -1,11 +1,12 @@
using System.Runtime.Serialization;
namespace TGServiceInterface
namespace TGS.Interface
{
/// <summary>
/// Metadata about an <see cref="Components.ITGInstance"/>
/// </summary>
[DataContract]
//Namespace required for compatibility reasons
[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/TGServiceInterface")]
public sealed class InstanceMetadata
{
/// <summary>
@@ -1,16 +1,16 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Service Interface")]
[assembly: AssemblyDescription("Used by user programs to access the TGStation Server Service")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab")]
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Service Interface")]
[assembly: AssemblyDescription("Used by user programs to access the TGStation Server Service")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ac4e7e8b-f83a-481c-a8b0-8fa4e8ae59ab")]
@@ -1,6 +1,6 @@
using System.Runtime.Serialization;
namespace TGServiceInterface
namespace TGS.Interface
{
/// <summary>
/// Information about a pull request
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace TGServiceInterface
namespace TGS.Interface
{
/// <summary>
/// Helper for creating commands that contain sub commands
File diff suppressed because it is too large Load Diff
@@ -7,7 +7,7 @@
<ProjectGuid>{AC4E7E8B-F83A-481C-A8B0-8FA4E8AE59AB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TGServiceInterface</RootNamespace>
<RootNamespace>TGS.Interface</RootNamespace>
<AssemblyName>TGServiceInterface</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
@@ -27,7 +27,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>bin\x86\Release\TGServiceInterface.xml</DocumentationFile>
<DocumentationFile>bin\x86\Release\TGS.Interface.xml</DocumentationFile>
<Optimize>true</Optimize>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>pdbonly</DebugType>
@@ -66,7 +66,7 @@
<Compile Include="Components\Repository.cs" />
<Compile Include="PullRequestInfo.cs" />
<Compile Include="RootCommand.cs" />
<Compile Include="Interface.cs" />
<Compile Include="ServerInterface.cs" />
<Compile Include="..\AssemblyInfo.global.cs" />
<Compile Include="Components\Service.cs" />
<Compile Include="Components\Interop.cs" />
@@ -75,7 +75,7 @@
<Content Include="tgs.ico" />
</ItemGroup>
<ItemGroup>
<None Include="TGServiceInterface.nuspec" />
<None Include="TGS.Interface.nuspec" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<id>TGServiceInterface</id>
<version>$version$</version>
<authors>Cyberboss</authors>
<licenseUrl>https://github.com/tgstation/tgstation-server/blob/master/LICENSE</licenseUrl>

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
</configuration>
+73
View File
@@ -0,0 +1,73 @@
using System;
namespace TGS.Server.Console
{
/// <summary>
/// Console runner for a <see cref="Server"/>
/// </summary>
sealed class Console : ILogger
{
/// <summary>
/// Entry point to the <see cref="Console"/>
/// </summary>
/// <param name="args"></param>
static void Main(string[] args) => new Console(args);
/// <summary>
/// Construct and run a <see cref="Console"/>
/// </summary>
/// <param name="args">Command line arguments</param>
Console(string[] args)
{
try
{
System.Console.WriteLine("Starting server...");
var server = new Server(args, this); //no using to avoid including more references
try
{
System.Console.WriteLine("Server started!");
ExitPrompt();
}
finally
{
server.Dispose();
}
}
catch (Exception e)
{
System.Console.WriteLine(String.Format("Unhandled exception: {0}", e.ToString()));
ExitPrompt();
}
}
void ExitPrompt()
{
System.Console.WriteLine("Press any key to exit...");
System.Console.ReadKey();
}
/// <inheritdoc />
public void WriteAccess(string username, bool authSuccess, byte loggingID)
{
System.Console.WriteLine(String.Format("[{0}]: {1}-{4}: Authentication {3} from {2}", DateTime.UtcNow.ToString(), EventID.Authentication, username, authSuccess ? "success" : "fail", loggingID));
}
/// <inheritdoc />
public void WriteError(string message, EventID id, byte loggingID)
{
System.Console.WriteLine(String.Format("[{0}]: {1}-{3}: ERROR: {2}", DateTime.Now.ToString(), id, message, loggingID));
}
/// <inheritdoc />
public void WriteInfo(string message, EventID id, byte loggingID)
{
System.Console.WriteLine(String.Format("[{0}]: {1}-{3}: {2}", DateTime.Now.ToString(), id, message, loggingID));
}
/// <inheritdoc />
public void WriteWarning(string message, EventID id, byte loggingID)
{
System.Console.WriteLine(String.Format("[{0}]: {1}-{3}: Warning: {2}", DateTime.Now.ToString(), id, message, loggingID));
}
}
}
@@ -0,0 +1,16 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TGStation Server Console")]
[assembly: AssemblyDescription("Console adapter for TGStation Server")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("509433f6-aefb-44ca-bfe3-c782166d2cc3")]
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{509433F6-AEFB-44CA-BFE3-C782166D2CC3}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>TGS.Server.Console</RootNamespace>
<AssemblyName>TGS.Server.Console</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>tgs.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Console.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="app.manifest" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TGS.Server\TGS.Server.csproj">
<Project>{f32eda25-0855-411c-af5e-f0d042917e2d}</Project>
<Name>TGS.Server</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="tgs.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+76
View File
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Specifying requestedExecutionLevel element will disable file and registry virtualization.
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
-->
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>

Some files were not shown because too many files have changed in this diff Show More