Client, launcher, and too much stuff to document.

This commit is contained in:
John Michael Gross
2016-09-24 13:08:36 -07:00
parent e153870182
commit 7488384fb8
59 changed files with 1908 additions and 219 deletions

View File

@@ -1,7 +1,7 @@
<Application x:Class="PistonClient.App" <Application x:Class="Piston.Launcher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PistonClient" xmlns:local="clr-namespace:Piston.Launcher"
StartupUri="MainWindow.xaml"> StartupUri="MainWindow.xaml">
<Application.Resources> <Application.Resources>

View File

@@ -6,7 +6,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
namespace PistonClient namespace Piston.Launcher
{ {
/// <summary> /// <summary>
/// Interaction logic for App.xaml /// Interaction logic for App.xaml

57
Piston.Launcher/Config.cs Normal file
View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace Piston.Launcher
{
public class Config
{
public int Version { get; set; }
public string RemoteFilePath { get; set; }
public string SpaceDirectory { get; set; }
private Config()
{
Version = 0;
RemoteFilePath = "ftp://athena.jimmacle.com/";
SpaceDirectory = @"C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64";
}
public static string GetConfigPath()
{
var appdata = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var pistonFolder = Path.Combine(appdata, "Piston");
if (!Directory.Exists(pistonFolder))
Directory.CreateDirectory(pistonFolder);
return Path.Combine(appdata, "Piston\\config.xml");
}
public static Config Load()
{
if (!File.Exists(GetConfigPath()))
return new Config();
XmlSerializer ser = new XmlSerializer(typeof(Config));
using (var f = File.OpenRead(GetConfigPath()))
{
using (var sr = new StreamReader(f))
{
return (Config)ser.Deserialize(sr);
}
}
}
public void Save()
{
XmlSerializer ser = new XmlSerializer(typeof(Config));
using (var sw = new StreamWriter(GetConfigPath()))
{
ser.Serialize(sw, this);
}
}
}
}

View File

@@ -0,0 +1,15 @@
<Window x:Class="Piston.Launcher.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Piston.Launcher"
mc:Ignorable="d"
Title="Piston Launcher" ResizeMode="NoResize" Height="220" Width="400">
<StackPanel Orientation="Vertical">
<Label FontSize="50" Content="Piston Launcher" HorizontalAlignment="Center"/>
<Button x:Name="LaunchBtn" FontSize="20" Height="30" Content="Launch" Margin="5,5,5,5" Click="LaunchBtn_Click"/>
<Button x:Name="UpdateBtn" FontSize="20" Height="30" Content="Install/Update" Margin="5,5,5,5" Click="UpdateBtn_Click"/>
<Label x:Name="InfoLabel" Margin="5,5,5,5" HorizontalAlignment="Center"/>
</StackPanel>
</Window>

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.IO;
using Microsoft.Win32;
namespace Piston.Launcher
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Config _config;
private PistonFileManager _fileManager;
public MainWindow()
{
InitializeComponent();
_config = Config.Load();
Title += $" v{_config.Version}";
_fileManager = new PistonFileManager(_config.RemoteFilePath);
CheckSpaceDirectory();
UpdatePistonFiles();
}
protected override void OnClosing(CancelEventArgs e)
{
_config.Save();
base.OnClosing(e);
}
private bool CheckSpaceDirectory()
{
if (Directory.Exists(_config.SpaceDirectory) && Directory.GetFiles(_config.SpaceDirectory).Any(i => i.Contains("SpaceEngineers.exe")))
return true;
var dialog = new SpaceDirPrompt();
dialog.ShowDialog();
if (dialog.Success)
{
_config.SpaceDirectory = dialog.SelectedDir;
return true;
}
return false;
}
private void UpdatePistonFiles()
{
var i = 0;
var files = _fileManager.GetDirectoryList();
foreach (var file in files)
{
if (_fileManager.UpdateIfNew(file, _config.SpaceDirectory))
{
i++;
}
}
InfoLabel.Content = $"Updated {i} files";
}
private void LaunchBtn_Click(object sender, RoutedEventArgs e)
{
if (!CheckSpaceDirectory())
return;
Directory.SetCurrentDirectory(_config.SpaceDirectory);
Process.Start(Path.Combine(_config.SpaceDirectory, "PistonClient.exe"));
Environment.Exit(0);
}
private void UpdateBtn_Click(object sender, RoutedEventArgs e)
{
var btn = (Button)sender;
btn.Content = "Up to date!";
btn.IsEnabled = false;
}
}
}

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" 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>{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Piston.Launcher</RootNamespace>
<AssemblyName>PistonLauncher</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<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 Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="SpaceDirPrompt.xaml.cs">
<DependentUpon>SpaceDirPrompt.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Config.cs" />
<Compile Include="PistonFileManager.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="SpaceDirPrompt.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace Piston.Launcher
{
public class PistonFileManager
{
private readonly string _baseUri;
public PistonFileManager(string baseUri)
{
_baseUri = baseUri;
}
public List<string> GetDirectoryList()
{
var fileList = new List<string>();
var response = RequestFtp("", WebRequestMethods.Ftp.ListDirectory);
using (var tr = (TextReader)new StreamReader(response.GetResponseStream()))
{
string line;
while ((line = tr.ReadLine()) != null)
fileList.Add(line);
}
response.Close();
return fileList;
}
public bool UpdateIfNew(string fileName, string targetDir)
{
var info = GetFileInfo(fileName);
var localPath = Path.Combine(targetDir, fileName);
if (File.Exists(localPath))
{
var localTime = File.GetLastWriteTime(localPath);
if (info.LastModified < localTime)
return false;
}
File.WriteAllBytes(localPath, DownloadFile(fileName));
return true;
}
public byte[] DownloadFile(string fileName)
{
byte[] file;
var response = RequestFtp(fileName, WebRequestMethods.Ftp.DownloadFile);
using (var s = response.GetResponseStream())
{
file = new byte[response.ContentLength];
s.Read(file, 0, (int)response.ContentLength);
}
response.Close();
return file;
}
public FileInfo GetFileInfo(string fileName)
{
var response = RequestFtp(fileName, WebRequestMethods.Ftp.GetDateTimestamp);
return new FileInfo
{
Name = fileName,
LastModified = response.LastModified,
SizeInBytes = response.ContentLength
};
}
private FtpWebResponse RequestFtp(string resource, string method)
{
var request = (FtpWebRequest)WebRequest.Create(_baseUri + resource);
request.Credentials = new NetworkCredential("pistonftp", "piston");
request.Method = method;
try { return (FtpWebResponse)request.GetResponse(); }
catch (WebException e)
{
MessageBox.Show($"{e.Message}\r\n{e.StackTrace}");
throw;
}
}
public struct FileInfo
{
public string Name;
public DateTime LastModified;
public long SizeInBytes;
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 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("Piston.Launcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Piston.Launcher")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 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)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Piston.Launcher.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Piston.Launcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Piston.Launcher.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,14 @@
<Window x:Class="Piston.Launcher.SpaceDirPrompt"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Piston.Launcher"
mc:Ignorable="d"
Title="Select SE Directory" Height="120" Width="500">
<StackPanel>
<Label Content="SE not found in the default location. Please input the path of your game's Bin64 directory." HorizontalAlignment="Center"/>
<TextBox x:Name="PathBox" Margin="5,5,5,5"/>
<Button x:Name="OkButton" Content="OK" Margin="5,5,5,5" Click="OkButton_Click"></Button>
</StackPanel>
</Window>

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Piston.Launcher
{
/// <summary>
/// Interaction logic for SpaceDirPrompt.xaml
/// </summary>
public partial class SpaceDirPrompt : Window
{
public string SelectedDir { get; private set; }
public bool Success { get; private set; }
public SpaceDirPrompt()
{
InitializeComponent();
}
private void OkButton_Click(object sender, RoutedEventArgs e)
{
if (!Directory.Exists(PathBox.Text))
{
MessageBox.Show(this, "That's not a valid directory.");
return;
}
if (!Directory.GetFiles(PathBox.Text).Any(i => i.Contains("SpaceEngineers.exe")))
{
MessageBox.Show(this, "SE was not found in the given directory.");
return;
}
Success = true;
SelectedDir = PathBox.Text;
Close();
}
}
}

View File

@@ -11,6 +11,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Piston.Client", "PistonClie
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Piston.Server", "PistonServer\Piston.Server.csproj", "{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Piston.Server", "PistonServer\Piston.Server.csproj", "{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{BF0D9941-B488-4880-B378-A9BF942D140D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Piston.Launcher", "Piston.Launcher\Piston.Launcher.csproj", "{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -51,6 +55,22 @@ Global
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|Any CPU.Build.0 = Release|Any CPU {CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|Any CPU.Build.0 = Release|Any CPU
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.ActiveCfg = Release|x64 {CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.ActiveCfg = Release|x64
{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.Build.0 = Release|x64 {CA50886B-7B22-4CD8-93A0-C06F38D4F77D}.Release|x64.Build.0 = Release|x64
{BF0D9941-B488-4880-B378-A9BF942D140D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF0D9941-B488-4880-B378-A9BF942D140D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF0D9941-B488-4880-B378-A9BF942D140D}.Debug|x64.ActiveCfg = Debug|x64
{BF0D9941-B488-4880-B378-A9BF942D140D}.Debug|x64.Build.0 = Debug|x64
{BF0D9941-B488-4880-B378-A9BF942D140D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF0D9941-B488-4880-B378-A9BF942D140D}.Release|Any CPU.Build.0 = Release|Any CPU
{BF0D9941-B488-4880-B378-A9BF942D140D}.Release|x64.ActiveCfg = Release|x64
{BF0D9941-B488-4880-B378-A9BF942D140D}.Release|x64.Build.0 = Release|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Debug|x64.ActiveCfg = Debug|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Debug|x64.Build.0 = Debug|x64
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Release|Any CPU.Build.0 = Release|Any CPU
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Release|x64.ActiveCfg = Release|Any CPU
{19292801-5B9C-4EE0-961F-0FA37B3A6C3D}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -1,6 +1,6 @@
using System; using System;
namespace Piston.Server namespace Piston
{ {
/// <summary> /// <summary>
/// Identifies a player's current connection state. /// Identifies a player's current connection state.

View File

@@ -49,24 +49,37 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Sandbox.Common"> <Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Common.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Common.dll</HintPath>
</Reference> </Reference>
<Reference Include="Sandbox.Game"> <Reference Include="Sandbox.Game, Version=0.1.6108.20542, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll</HintPath>
</Reference> </Reference>
<Reference Include="Sandbox.Graphics"> <Reference Include="Sandbox.Graphics, Version=0.1.6108.20417, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Graphics.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Graphics.dll</HintPath>
</Reference> </Reference>
<Reference Include="SpaceEngineers.Game"> <Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.Game.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.Game.dll</HintPath>
</Reference> </Reference>
<Reference Include="SpaceEngineers.ObjectBuilders"> <Reference Include="SpaceEngineers.ObjectBuilders, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.ObjectBuilders.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.ObjectBuilders.dll</HintPath>
</Reference> </Reference>
<Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers"> <Reference Include="SpaceEngineers.ObjectBuilders.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.ObjectBuilders.XmlSerializers.dll</HintPath>
</Reference> </Reference>
<Reference Include="SpaceEngineersDedicated">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\SpaceEngineersDedicated.exe</HintPath>
</Reference>
<Reference Include="SteamSDK, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SteamSDK.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
@@ -75,51 +88,70 @@
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="VRage"> <Reference Include="VRage, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Audio"> <Reference Include="VRage.Audio, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Audio.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Audio.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Game"> <Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Game.XmlSerializers"> <Reference Include="VRage.Game.XmlSerializers, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.XmlSerializers.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.XmlSerializers.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Input"> <Reference Include="VRage.Input, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Input.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Input.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Library"> <Reference Include="VRage.Library, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Library.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Library.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Math"> <Reference Include="VRage.Math">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Math.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Math.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Native"> <Reference Include="VRage.Native, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Native.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Native.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.OpenVRWrapper"> <Reference Include="VRage.OpenVRWrapper, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.OpenVRWrapper.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.OpenVRWrapper.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Render"> <Reference Include="VRage.Render, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Render11"> <Reference Include="VRage.Render11, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render11.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render11.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Scripting"> <Reference Include="VRage.Scripting, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Scripting.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Scripting.dll</HintPath>
</Reference> </Reference>
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ConnectionState.cs" />
<Compile Include="Logger.cs" /> <Compile Include="Logger.cs" />
<Compile Include="PlayerInfo.cs" />
<Compile Include="PlayerInfoCache.cs" />
<Compile Include="SteamService.cs" />
<Compile Include="ViewModels\ModViewModel.cs" />
<Compile Include="MTObservableCollection.cs" /> <Compile Include="MTObservableCollection.cs" />
<Compile Include="MyPlayerCollectionExtensions.cs" /> <Compile Include="MyPlayerCollectionExtensions.cs" />
<Compile Include="ObservableType.cs" /> <Compile Include="SteamHelper.cs" />
<Compile Include="StringExtensions.cs" />
<Compile Include="ViewModels\ViewModel.cs" />
<Compile Include="PluginManager.cs" /> <Compile Include="PluginManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\PluginViewModel.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\PistonAPI\Piston.API.csproj"> <ProjectReference Include="..\PistonAPI\Piston.API.csproj">

View File

@@ -1,6 +1,6 @@
using Sandbox.Engine.Multiplayer; using Sandbox.Engine.Multiplayer;
namespace Piston.Server namespace Piston
{ {
/// <summary> /// <summary>
/// Stores player information in an observable format. /// Stores player information in an observable format.

37
Piston/PlayerInfoCache.cs Normal file
View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Piston
{
public static class PlayerInfoCache
{
private static readonly Dictionary<ulong, PlayerInfo> _cache = new Dictionary<ulong, PlayerInfo>();
public static PlayerInfo GetOrCreate(ulong steamId)
{
PlayerInfo info;
if (_cache.TryGetValue(steamId, out info))
return info;
info = new PlayerInfo(steamId) {State = ConnectionState.Unknown};
_cache.Add(steamId, info);
return info;
}
public static void Add(PlayerInfo info)
{
if (_cache.ContainsKey(info.SteamId))
return;
_cache.Add(info.SteamId, info);
}
public static void Reset()
{
_cache.Clear();
}
}
}

View File

@@ -3,9 +3,11 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Piston.API; using Piston.API;
using PistonAPI;
using Sandbox; using Sandbox;
using VRage.Plugins; using VRage.Plugins;
using VRage.Collections; using VRage.Collections;
@@ -30,17 +32,42 @@ namespace Piston
GetPluginList(); GetPluginList();
} }
/// <summary>
/// Get a reference to the internal VRage plugin list.
/// </summary>
private void GetPluginList() private void GetPluginList()
{ {
_plugins = typeof(MyPlugins).GetField("m_plugins", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as List<IPlugin>; _plugins = typeof(MyPlugins).GetField("m_plugins", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as List<IPlugin>;
} }
/// <summary>
/// Get a plugin's name from its <see cref="PluginAttribute"/> or its type name.
/// </summary>
public string GetPluginName(Type pluginType)
{
var attr = pluginType.GetCustomAttribute<PluginAttribute>();
return attr?.Name ?? pluginType.Name;
}
/// <summary>
/// Load all plugins in the <see cref="PluginDir"/> folder.
/// </summary>
public void LoadAllPlugins()
{
var pluginFolders = GetPluginFolders();
foreach (var folder in pluginFolders)
{
LoadPluginFolder(folder);
}
}
/// <summary> /// <summary>
/// Load a plugin into the game. /// Load a plugin into the game.
/// </summary> /// </summary>
/// <param name="plugin"></param> /// <param name="plugin"></param>
public void LoadPlugin(IPlugin plugin) public void LoadPlugin(IPlugin plugin)
{ {
Logger.Write($"Loading plugin: {GetPluginName(plugin.GetType())}");
plugin.Init(MySandboxGame.Static); plugin.Init(MySandboxGame.Static);
_plugins.Add(plugin); _plugins.Add(plugin);
} }
@@ -68,21 +95,25 @@ namespace Piston
{ {
var relativeDir = Path.Combine(PluginDir, folderName); var relativeDir = Path.Combine(PluginDir, folderName);
if (!Directory.Exists(relativeDir)) if (!Directory.Exists(relativeDir))
throw new FileNotFoundException($"Plugin {folderName} does not exist in the Plugins folder."); {
Logger.Write($"Plugin {folderName} does not exist in the Plugins folder.");
return;
}
var fileNames = Directory.GetFiles(relativeDir, "*.dll"); var fileNames = Directory.GetFiles(relativeDir, "*.dll");
foreach (var fileName in fileNames) foreach (var fileName in fileNames)
{ {
var fullPath = Path.Combine(Directory.GetCurrentDirectory(), fileName); var fullPath = Path.Combine(Directory.GetCurrentDirectory(), fileName);
UnblockDll(fullPath);
var asm = Assembly.LoadFrom(fullPath); var asm = Assembly.LoadFrom(fullPath);
foreach (var type in asm.GetTypes()) foreach (var type in asm.GetTypes())
{ {
if (type.GetInterfaces().Contains(typeof(IPlugin))) if (type.GetInterfaces().Contains(typeof(IPlugin)))
{ {
var inst = Activator.CreateInstance(type); var inst = (IPlugin)Activator.CreateInstance(type);
LoadPlugin((IPlugin)inst); MySandboxGame.Static.Invoke(() => LoadPlugin(inst));
} }
} }
} }
@@ -91,7 +122,6 @@ namespace Piston
/// <summary> /// <summary>
/// Unload a plugin from the game. /// Unload a plugin from the game.
/// </summary> /// </summary>
/// <param name="plugin"></param>
public void UnloadPlugin(IPlugin plugin) public void UnloadPlugin(IPlugin plugin)
{ {
_plugins.Remove(plugin); _plugins.Remove(plugin);
@@ -125,5 +155,14 @@ namespace Piston
p?.Reload(); p?.Reload();
} }
} }
[DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeleteFile(string name);
public bool UnblockDll(string fileName)
{
return DeleteFile(fileName + ":Zone.Identifier");
}
} }
} }

101
Piston/SteamHelper.cs Normal file
View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Sandbox;
using Sandbox.Engine.Networking;
using Sandbox.Engine.Platform;
using SteamSDK;
using VRage.Game;
namespace Piston
{
public static class SteamHelper
{
private static Thread _callbackThread;
public static void Init()
{
_callbackThread = new Thread(() =>
{
while (true)
{
SteamAPI.Instance.RunCallbacks();
Thread.Sleep(100);
}
}) {Name = "SteamAPICallbacks"};
_callbackThread.Start();
}
public static MySteamWorkshop.SubscribedItem GetItemInfo(ulong itemId)
{
MySteamWorkshop.SubscribedItem item = null;
using (var mre = new ManualResetEvent(false))
{
SteamAPI.Instance.RemoteStorage.GetPublishedFileDetails(itemId, 0, (ioFail, result) =>
{
if (!ioFail && result.Result == Result.OK)
{
item = new MySteamWorkshop.SubscribedItem
{
Title = result.Title,
Description = result.Description,
PublishedFileId = result.PublishedFileId,
SteamIDOwner = result.SteamIDOwner,
Tags = result.Tags.Split(' '),
TimeUpdated = result.TimeUpdated,
UGCHandle = result.FileHandle
};
}
else
{
Logger.Write($"Failed to get item info for {itemId}");
}
mre.Set();
});
mre.WaitOne();
mre.Reset();
return item;
}
}
public static SteamUGCDetails GetItemDetails(ulong itemId)
{
SteamUGCDetails details = default(SteamUGCDetails);
using (var mre = new ManualResetEvent(false))
{
SteamAPI.Instance.UGC.RequestUGCDetails(itemId, 0, (b, result) =>
{
if (!b && result.Details.Result == Result.OK)
details = result.Details;
else
Logger.Write($"Failed to get item details for {itemId}");
mre.Set();
});
mre.WaitOne();
mre.Reset();
}
return details;
}
public static MyObjectBuilder_Checkpoint.ModItem GetModItem(ulong modId)
{
var details = GetItemDetails(modId);
return new MyObjectBuilder_Checkpoint.ModItem(null, modId, details.Title);
}
public static MyObjectBuilder_Checkpoint.ModItem GetModItem(SteamUGCDetails details)
{
return new MyObjectBuilder_Checkpoint.ModItem(null, details.PublishedFileId, details.Title);
}
}
}

49
Piston/SteamService.cs Normal file
View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sandbox;
namespace Piston
{
/// <summary>
/// SNAGGED FROM PHOENIX84'S SE WORKSHOP TOOL
/// Keen's steam service calls RestartIfNecessary, which triggers steam to think the game was launched
/// outside of Steam, which causes this process to exit, and the game to launch instead with an arguments warning.
/// We have to override the default behavior, then forcibly set the correct options.
/// </summary>
public class SteamService : MySteamService
{
public SteamService(bool isDedicated, uint appId)
: base(true, appId)
{
// TODO: Add protection for this mess... somewhere
SteamSDK.SteamServerAPI.Instance.Dispose();
var steam = typeof(Sandbox.MySteamService);
steam.GetField("SteamServerAPI").SetValue(this, null);
steam.GetProperty("AppId").GetSetMethod(true).Invoke(this, new object[] { appId });
if (isDedicated)
{
steam.GetField("SteamServerAPI").SetValue(this, SteamSDK.SteamServerAPI.Instance);
}
else
{
var SteamAPI = SteamSDK.SteamAPI.Instance;
steam.GetField("SteamAPI").SetValue(this, SteamSDK.SteamAPI.Instance);
steam.GetProperty("IsActive").GetSetMethod(true).Invoke(this, new object[] { SteamSDK.SteamAPI.Instance != null });
if (SteamAPI != null)
{
steam.GetProperty("UserId").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamUserId() });
steam.GetProperty("UserName").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamName() });
steam.GetProperty("OwnsGame").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.HasGame() });
steam.GetProperty("UserUniverse").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetSteamUserUniverse() });
steam.GetProperty("BranchName").GetSetMethod(true).Invoke(this, new object[] { SteamAPI.GetBranchName() });
SteamAPI.LoadStats();
}
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Piston
{
public static class StringExtensions
{
public static string Truncate(this string s, int maxLength)
{
return s.Length <= maxLength ? s : s.Substring(0, maxLength);
}
public static IEnumerable<string> ReadLines(this string s, int max, bool skipEmpty = false, char delim = '\n')
{
var lines = s.Split(delim);
for (var i = 0; i < lines.Length && i < max; i++)
{
var l = lines[i];
if (skipEmpty && string.IsNullOrWhiteSpace(l))
continue;
yield return l;
}
}
public static string Wrap(this string s, int lineLength)
{
if (s.Length <= lineLength)
return s;
var result = new StringBuilder();
for (var i = 0; i < s.Length;)
{
var next = i + lineLength;
if (s.Length - 1 < next)
{
result.AppendLine(s.Substring(i));
break;
}
result.AppendLine(s.Substring(i, next));
i = next;
}
return result.ToString();
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VRage.Game;
namespace Piston
{
public class ModViewModel
{
public MyObjectBuilder_Checkpoint.ModItem ModItem { get; }
public string Name => ModItem.Name;
public string FriendlyName => ModItem.FriendlyName;
public ulong PublishedFileId => ModItem.PublishedFileId;
public string Description { get; }
public ModViewModel(MyObjectBuilder_Checkpoint.ModItem item, string description = "")
{
ModItem = item;
Description = description;
}
public static implicit operator MyObjectBuilder_Checkpoint.ModItem(ModViewModel item)
{
return item.ModItem;
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Piston.ViewModels
{
public class PluginViewModel : ViewModel
{
}
}

View File

@@ -8,6 +8,9 @@ using System.Threading.Tasks;
namespace Piston namespace Piston
{ {
/// <summary>
/// Provides a method to notify an observer of changes to an object's properties.
/// </summary>
public class ViewModel : INotifyPropertyChanged public class ViewModel : INotifyPropertyChanged
{ {
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;

View File

@@ -10,7 +10,6 @@ namespace Piston.API
{ {
public interface IPistonPlugin : IPlugin public interface IPistonPlugin : IPlugin
{ {
string Name { get; }
void Reload(); void Reload();
} }
} }

View File

@@ -68,6 +68,7 @@
<Compile Include="IPistonPlugin.cs" /> <Compile Include="IPistonPlugin.cs" />
<Compile Include="IServerControls.cs" /> <Compile Include="IServerControls.cs" />
<Compile Include="PistonAPI.cs" /> <Compile Include="PistonAPI.cs" />
<Compile Include="PluginAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PistonAPI
{
public class PluginAttribute : Attribute
{
public string Name { get; }
public bool Reloadable { get; }
public PluginAttribute(string name, bool reloadable = false)
{
Name = name;
Reloadable = reloadable;
}
}
}

View File

@@ -1,12 +0,0 @@
<Window x:Class="PistonClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:PistonClient"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PistonClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

View File

@@ -7,7 +7,7 @@
<ProjectGuid>{E36DF745-260B-4956-A2E8-09F08B2E7161}</ProjectGuid> <ProjectGuid>{E36DF745-260B-4956-A2E8-09F08B2E7161}</ProjectGuid>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PistonClient</RootNamespace> <RootNamespace>Piston.Client</RootNamespace>
<AssemblyName>PistonClient</AssemblyName> <AssemblyName>PistonClient</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
@@ -56,6 +56,16 @@
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Sandbox.Game">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll</HintPath>
</Reference>
<Reference Include="Sandbox.Graphics, Version=0.1.6108.20417, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Graphics.dll</HintPath>
</Reference>
<Reference Include="SpaceEngineers.Game">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.Game.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
@@ -67,29 +77,31 @@
<Reference Include="System.Xaml"> <Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework> <RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="VRage">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath>
</Reference>
<Reference Include="VRage.Game">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Game.dll</HintPath>
</Reference>
<Reference Include="VRage.Library">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Library.dll</HintPath>
</Reference>
<Reference Include="VRage.Math, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Math.dll</HintPath>
</Reference>
<Reference Include="VRage.Render">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render.dll</HintPath>
</Reference>
<Reference Include="VRage.Render11">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.Render11.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
<Reference Include="PresentationCore" /> <Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ApplicationDefinition Include="App.xaml"> <Compile Include="Program.cs" />
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
@@ -114,7 +126,10 @@
<AppDesigner Include="Properties\" /> <AppDesigner Include="Properties\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <ProjectReference Include="..\Piston\Piston.csproj">
<Project>{7E01635C-3B67-472E-BCD6-C5539564F214}</Project>
<Name>Piston</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

137
PistonClient/Program.cs Normal file
View File

@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows;
using Sandbox;
using Sandbox.Engine.Platform;
using Sandbox.Game;
using SpaceEngineers.Game;
using VRage.FileSystem;
using VRageRender;
using Piston;
using Sandbox.Game.Gui;
using Sandbox.Graphics.GUI;
using Sandbox.Gui;
using VRageMath;
namespace Piston.Client
{
/// <summary>
/// This is nearly all Keen's code.
/// </summary>
public static class MyProgram
{
private static MyCommonProgramStartup _startup;
private static IMyRender _renderer;
private static readonly uint AppId = 244850u;
private static PluginManager _pluginManager;
private static void Main(string[] args)
{
if (!File.Exists("steam_appid.txt"))
{
Directory.SetCurrentDirectory(Path.GetDirectoryName(typeof(VRage.FastResourceLock).Assembly.Location) + "\\..");
}
//Add myself to the credits because I'm awesome.
var credits = new MyCreditsDepartment("Piston Developed By") {Persons = new List<MyCreditsPerson> {new MyCreditsPerson("JIMMACLE")}};
MyPerGameSettings.Credits.Departments.Add(credits);
SpaceEngineersGame.SetupBasicGameInfo();
_startup = new MyCommonProgramStartup(args);
if (_startup.PerformReporting())
return;
_startup.PerformAutoconnect();
if (!_startup.CheckSingleInstance())
return;
var appDataPath = _startup.GetAppDataPath();
MyInitializer.InvokeBeforeRun(AppId, MyPerGameSettings.BasicGameInfo.ApplicationName, appDataPath, false);
MyInitializer.InitCheckSum();
if (!_startup.Check64Bit())
return;
_startup.DetectSharpDxLeaksBeforeRun();
using (var mySteamService = new SteamService(Game.IsDedicated, AppId))
{
_renderer = null;
SpaceEngineersGame.SetupPerGameSettings();
SpaceEngineersGame.SetupRender();
try
{
InitializeRender();
}
catch (MyRenderException ex)
{
MessageBox.Show(ex.Message);
return;
}
var services = new VRageGameServices(mySteamService);
if (!Game.IsDedicated)
MyFileSystem.InitUserSpecific(mySteamService.UserId.ToString());
using (var spaceEngineersGame = new SpaceEngineersGame(services, args))
{
Logger.Write("Starting SE...");
spaceEngineersGame.OnGameLoaded += SpaceEngineersGame_OnGameLoaded;
MyGuiSandbox.GuiControlCreated += GuiControlCreated;
spaceEngineersGame.Run();
}
}
_startup.DetectSharpDxLeaksAfterRun();
MyInitializer.InvokeAfterRun();
}
private static void GuiControlCreated(object o)
{
var menu = o as MyGuiScreenMainMenu;
if (menu != null)
{
Logger.Write("Adding button to main menu");
menu.Controls.Add(new MyGuiControlImageButton("PistonButton", text: new StringBuilder("Piston"), size: new Vector2(20), position: new Vector2(0)));
}
}
private static void SpaceEngineersGame_OnGameLoaded(object sender, System.EventArgs e)
{
_pluginManager = new PluginManager();
_pluginManager.LoadAllPlugins();
//Fix Marek's name.
MyPerGameSettings.Credits.Departments[1].Persons[0].Name.Clear().Append("MEARK ROAS");
}
private static void InitializeRender()
{
if (Game.IsDedicated)
{
_renderer = new MyNullRender();
}
else
{
var graphicsRenderer = MySandboxGame.Config.GraphicsRenderer;
if (graphicsRenderer == MySandboxGame.DirectX11RendererKey)
{
_renderer = new MyDX11Render();
if (!_renderer.IsSupported)
{
MySandboxGame.Log.WriteLine("DirectX 11 renderer not supported. No renderer to revert back to.");
_renderer = null;
}
}
if (_renderer == null)
throw new MyRenderException("The current version of the game requires a Dx11 card. \\n For more information please see : http://blog.marekrosa.org/2016/02/space-engineers-news-full-source-code_26.html", MyRenderExceptionEnum.GpuNotSupported);
MySandboxGame.Config.GraphicsRenderer = graphicsRenderer;
}
MyRenderProxy.Initialize(_renderer);
MyRenderProxy.IS_OFFICIAL = true;
MyRenderProxy.GetRenderProfiler().SetAutocommit(false);
MyRenderProxy.GetRenderProfiler().InitMemoryHack("MainEntryPoint");
}
}
}

View File

@@ -8,7 +8,7 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace PistonClient.Properties { namespace Piston.Client.Properties {
using System; using System;
@@ -39,7 +39,7 @@ namespace PistonClient.Properties {
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PistonClient.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Piston.Client.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;

View File

@@ -8,7 +8,7 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace PistonClient.Properties { namespace Piston.Client.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]

View File

@@ -12,6 +12,7 @@ using System.Windows;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Threading; using System.Windows.Threading;
using Piston; using Piston;
using Piston.Server.ViewModels;
using Sandbox.Engine.Multiplayer; using Sandbox.Engine.Multiplayer;
using Sandbox.Game.Multiplayer; using Sandbox.Game.Multiplayer;
using Sandbox.Game.World; using Sandbox.Game.World;
@@ -101,87 +102,4 @@ namespace Piston.Server
PlayerLeft?.Invoke(player); PlayerLeft?.Invoke(player);
} }
} }
/// <summary>
/// Stores player information in an observable format.
/// </summary>
public class PlayerInfo : ObservableType
{
private ulong _steamId;
private string _name;
private ConnectionState _state;
public ulong SteamId
{
get { return _steamId; }
set { _steamId = value; OnPropertyChanged(); }
}
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(); }
}
public ConnectionState State
{
get { return _state; }
set { _state = value; OnPropertyChanged(); }
}
public PlayerInfo(ulong steamId)
{
_steamId = steamId;
_name = MyMultiplayer.Static.GetMemberName(steamId);
_state = ConnectionState.Unknown;
}
}
public class ChatItemInfo : ObservableType
{
private PlayerInfo _sender;
private string _message;
private DateTime _timestamp;
public PlayerInfo Sender
{
get { return _sender; }
set { _sender = value; OnPropertyChanged(); }
}
public string Message
{
get { return _message; }
set { _message = value; OnPropertyChanged(); }
}
public DateTime Timestamp
{
get { return _timestamp; }
set { _timestamp = value; OnPropertyChanged(); }
}
public string Time => Timestamp.ToShortTimeString();
public ChatItemInfo(PlayerInfo sender, string message)
{
_sender = sender;
_message = message;
_timestamp = DateTime.Now;
}
}
/// <summary>
/// Identifies a player's current connection state.
/// </summary>
[Flags]
public enum ConnectionState
{
Unknown,
Connected = 1,
Left = 2,
Disconnected = 4,
Kicked = 8,
Banned = 16,
}
} }

View File

@@ -7,7 +7,7 @@
<ProjectGuid>{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}</ProjectGuid> <ProjectGuid>{CA50886B-7B22-4CD8-93A0-C06F38D4F77D}</ProjectGuid>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PistonServer</RootNamespace> <RootNamespace>Piston.Server</RootNamespace>
<AssemblyName>PistonServer</AssemblyName> <AssemblyName>PistonServer</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
@@ -56,17 +56,28 @@
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<StartupObject /> <StartupObject>Piston.Server.Program</StartupObject>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>SpaceEngineers.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="HavokWrapper, Version=1.0.6051.28726, Culture=neutral, processorArchitecture=AMD64"> <Reference Include="HavokWrapper, Version=1.0.6051.28726, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\HavokWrapper.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\HavokWrapper.dll</HintPath>
</Reference> </Reference>
<Reference Include="Sandbox.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\Sandbox.Common.dll</HintPath>
</Reference>
<Reference Include="Sandbox.Game, Version=0.1.6101.33378, Culture=neutral, processorArchitecture=AMD64"> <Reference Include="Sandbox.Game, Version=0.1.6101.33378, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\Sandbox.Game.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\Sandbox.Game.dll</HintPath>
</Reference> </Reference>
<Reference Include="SpaceEngineers.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\SpaceEngineers.Game.dll</HintPath>
</Reference>
<Reference Include="SpaceEngineersDedicated"> <Reference Include="SpaceEngineersDedicated">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\SpaceEngineersDedicated.exe</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\SpaceEngineersDedicated.exe</HintPath>
</Reference> </Reference>
@@ -76,6 +87,8 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
@@ -89,6 +102,10 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath>
</Reference> </Reference>
<Reference Include="VRage.Dedicated, Version=1.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\VRage.Dedicated.dll</HintPath>
</Reference>
<Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="VRage.Game, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\VRage.Game.dll</HintPath> <HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\DedicatedServer64\VRage.Game.dll</HintPath>
@@ -106,19 +123,30 @@
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ChatControl.xaml.cs"> <Compile Include="ViewModels\ConfigDedicatedViewModel.cs" />
<Compile Include="Views\AddWorkshopItemsDialog.xaml.cs">
<DependentUpon>AddWorkshopItemsDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ChatControl.xaml.cs">
<DependentUpon>ChatControl.xaml</DependentUpon> <DependentUpon>ChatControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="MainWindow.xaml.cs"> <Compile Include="ViewModels\ChatItemInfo.cs" />
<DependentUpon>MainWindow.xaml</DependentUpon> <Compile Include="Views\ModsControl.xaml.cs">
<DependentUpon>ModsControl.xaml</DependentUpon>
</Compile>
<Compile Include="Views\PistonUI.xaml.cs">
<DependentUpon>PistonUI.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="MultiplayerManager.cs" /> <Compile Include="MultiplayerManager.cs" />
<Compile Include="PistonServer.cs" /> <Compile Include="PistonServer.cs" />
<Compile Include="PlayerListControl.xaml.cs"> <Compile Include="Views\PlayerListControl.xaml.cs">
<DependentUpon>PlayerListControl.xaml</DependentUpon> <DependentUpon>PlayerListControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="ServerManager.cs" /> <Compile Include="ServerManager.cs" />
<Compile Include="Views\PropertyGrid.xaml.cs">
<DependentUpon>PropertyGrid.xaml</DependentUpon>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
@@ -138,6 +166,7 @@
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
@@ -151,18 +180,33 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="ChatControl.xaml"> <Page Include="Views\AddWorkshopItemsDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ChatControl.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="MainWindow.xaml"> <Page Include="Views\ModsControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\PistonUI.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="PlayerListControl.xaml"> <Page Include="Views\PlayerListControl.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="Views\PropertyGrid.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Resource Include="SpaceEngineers.ico" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -1,9 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Piston; using Piston;
using Piston.Server.Properties;
using Sandbox;
using Sandbox.Game;
using SpaceEngineers.Game;
using VRage.Dedicated;
using VRage.Game;
using VRage.Game.SessionComponents;
namespace Piston.Server namespace Piston.Server
{ {
@@ -21,15 +29,20 @@ namespace Piston.Server
public static void Init() public static void Init()
{ {
if (!_init) if (_init)
{ return;
Logger.Write("Initializing Piston");
_init = true; Logger.Write("Initializing Piston");
Server = new ServerManager(); _init = true;
Multiplayer = new MultiplayerManager(Server); Server = new ServerManager();
Plugins = new PluginManager(); Multiplayer = new MultiplayerManager(Server);
UI = new PistonUI(); Plugins = new PluginManager();
} UI = new PistonUI();
Server.SessionLoaded += Plugins.LoadAllPlugins;
Server.InitSandbox();
SteamHelper.Init();
UI.PropGrid.SetObject(MySandboxGame.ConfigDedicated);
} }
public static void Reset() public static void Reset()

View File

@@ -39,7 +39,7 @@ namespace Piston.Server.Properties {
internal static global::System.Resources.ResourceManager ResourceManager { internal static global::System.Resources.ResourceManager ResourceManager {
get { get {
if (object.ReferenceEquals(resourceMan, null)) { if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PistonServer.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Piston.Server.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;

View File

@@ -10,7 +10,12 @@ using System.Windows;
using Piston; using Piston;
using Sandbox; using Sandbox;
using Sandbox.Engine.Multiplayer; using Sandbox.Engine.Multiplayer;
using Sandbox.Game;
using Sandbox.Game.World; using Sandbox.Game.World;
using SpaceEngineers.Game;
using VRage.Dedicated;
using VRage.Game;
using VRage.Game.SessionComponents;
using VRage.Profiler; using VRage.Profiler;
namespace Piston.Server namespace Piston.Server
@@ -24,22 +29,39 @@ namespace Piston.Server
public event Action SessionLoading; public event Action SessionLoading;
public event Action SessionLoaded; public event Action SessionLoaded;
private readonly Assembly _dsAssembly;
private readonly ManualResetEvent _stopHandle = new ManualResetEvent(false); private readonly ManualResetEvent _stopHandle = new ManualResetEvent(false);
internal ServerManager() internal ServerManager()
{ {
using (var f = File.OpenRead("SpaceEngineersDedicated.exe"))
{
var bin = new byte[f.Length];
f.Read(bin, 0, (int)f.Length);
_dsAssembly = Assembly.Load(bin);
}
ServerThread = new Thread(StartServer);
MySession.OnLoading += OnSessionLoading; MySession.OnLoading += OnSessionLoading;
} }
public void InitSandbox()
{
SpaceEngineersGame.SetupBasicGameInfo();
SpaceEngineersGame.SetupPerGameSettings();
MyPerGameSettings.SendLogToKeen = false;
MyPerServerSettings.GameName = MyPerGameSettings.GameName;
MyPerServerSettings.GameNameSafe = MyPerGameSettings.GameNameSafe;
MyPerServerSettings.GameDSName = MyPerServerSettings.GameNameSafe + "Dedicated";
MyPerServerSettings.GameDSDescription = "Your place for space engineering, destruction and exploring.";
MySessionComponentExtDebug.ForceDisable = true;
MyPerServerSettings.AppId = 244850u;
ConfigForm<MyObjectBuilder_SessionSettings>.GameAttributes = Game.SpaceEngineers;
ConfigForm<MyObjectBuilder_SessionSettings>.OnReset = delegate
{
SpaceEngineersGame.SetupBasicGameInfo();
SpaceEngineersGame.SetupPerGameSettings();
};
int? gameVersion = MyPerGameSettings.BasicGameInfo.GameVersion;
MyFinalBuildConstants.APP_VERSION = gameVersion ?? 0;
}
public void Invoke(Action action)
{
MySandboxGame.Static.Invoke(action);
}
private void OnSessionLoading() private void OnSessionLoading()
{ {
SessionLoading?.Invoke(); SessionLoading?.Invoke();
@@ -56,9 +78,10 @@ namespace Piston.Server
/// </summary> /// </summary>
public void StartServerThread() public void StartServerThread()
{ {
if (ServerThread.IsAlive) if (ServerThread?.IsAlive ?? false)
{ {
throw new InvalidOperationException("The server thread is already running."); Logger.Write("Cannot start the server because it's already running.");
return;
} }
ServerThread = new Thread(StartServer); ServerThread = new Thread(StartServer);
@@ -76,16 +99,7 @@ namespace Piston.Server
if (MySandboxGame.Log.LogEnabled) if (MySandboxGame.Log.LogEnabled)
MySandboxGame.Log.Close(); MySandboxGame.Log.Close();
foreach (var type in _dsAssembly.GetTypes()) DedicatedServer.Run<MyObjectBuilder_SessionSettings>(RunArgs);
{
if (type.FullName.Contains("MyProgram"))
{
var method = type.GetMethod("Main", BindingFlags.Static | BindingFlags.NonPublic);
method.Invoke(null, new object[] {RunArgs});
break;
}
}
} }
/// <summary> /// <summary>
@@ -93,7 +107,7 @@ namespace Piston.Server
/// </summary> /// </summary>
public void StopServer() public void StopServer()
{ {
if (Thread.CurrentThread.ManagedThreadId != ServerThread.ManagedThreadId) if (Thread.CurrentThread.ManagedThreadId != ServerThread?.ManagedThreadId)
{ {
Logger.Write("Requesting server stop."); Logger.Write("Requesting server stop.");
MySandboxGame.Static.Invoke(StopServer); MySandboxGame.Static.Invoke(StopServer);

View File

@@ -1,6 +1,6 @@
using System; using System;
namespace Piston.Server namespace Piston.Server.ViewModels
{ {
public class ChatItemInfo : ViewModel public class ChatItemInfo : ViewModel
{ {

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sandbox.Engine.Utils;
using VRage.Game;
using VRage.Game.ModAPI;
namespace Piston.Server.ViewModels
{
public class ConfigDedicatedViewModel : ViewModel
{
public IMyConfigDedicated Config { get; }
public MTObservableCollection<string> Administrators { get; } = new MTObservableCollection<string>();
public MTObservableCollection<ulong> BannedPlayers { get; } = new MTObservableCollection<ulong>();
public int AsteroidAmount
{
get { return Config.AsteroidAmount; }
set { Config.AsteroidAmount = value; OnPropertyChanged(); }
}
public ConfigDedicatedViewModel(IMyConfigDedicated config)
{
Config = config;
Config.Administrators.ForEach(x => Administrators.Add(x));
Config.Banned.ForEach(x => BannedPlayers.Add(x));
}
public void FlushConfig()
{
Config.Administrators = Administrators.ToList();
}
}
}

View File

@@ -0,0 +1,14 @@
<Window x:Class="Piston.Server.AddModsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Piston.Server"
mc:Ignorable="d"
Title="Add Workshop Item" Height="200" Width="400">
<DockPanel Background="LightGray">
<Label DockPanel.Dock="Top" Content="Add each workshop URL or ID on its own line." HorizontalAlignment="Center"/>
<Button DockPanel.Dock="Bottom" Content="Done" Margin="5,0,5,5" Click="Done_Clicked"/>
<TextBox x:Name="urlBlock" Margin="5,0,5,5" Background="White" AcceptsReturn="True"/>
</DockPanel>
</Window>

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Piston.Server
{
/// <summary>
/// Interaction logic for AddModsDialog.xaml
/// </summary>
public partial class AddModsDialog : Window
{
public ulong[] Result = new ulong[0];
public AddModsDialog()
{
InitializeComponent();
}
private void Done_Clicked(object sender, RoutedEventArgs e)
{
var text = urlBlock.Text;
var lines = text.Split('\n');
Result = new ulong[lines.Length];
for (var i = 0; i < lines.Length; i++)
{
Result[i] = ExtractId(lines[i]);
}
Close();
}
private ulong ExtractId(string input)
{
ulong result;
var match = Regex.Match(input, @"(?<=id=)\d+").Value;
if (string.IsNullOrEmpty(match))
ulong.TryParse(input, out result);
else
ulong.TryParse(match, out result);
return result;
}
}
}

View File

@@ -0,0 +1,20 @@
<UserControl x:Class="Piston.Server.ModsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Piston.Server"
mc:Ignorable="d">
<StackPanel Margin="0,0,0,0" Orientation="Vertical">
<Label Content="Mods" Margin="5,5,5,5"/>
<ListView x:Name="ModList" HorizontalAlignment="Left" Height="265" VerticalAlignment="Top" Width="300" Margin="5,5,5,5" MouseDoubleClick="modList_OnMouesDoubleClick">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}" ToolTip="{Binding Description}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button x:Name="AddBtn" Content="Add Mods" Click="addBtn_Click" Margin="5,5,5,5"/>
<Button x:Name="RemBtn" Content="Remove Mods" Margin="5,5,5,5" Click="remBtn_Click"/>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Sandbox.Engine.Networking;
using SteamSDK;
using VRage.Game;
namespace Piston.Server
{
/// <summary>
/// Interaction logic for ModsControl.xaml
/// </summary>
public partial class ModsControl : UserControl
{
public ModsControl()
{
InitializeComponent();
}
private void addBtn_Click(object sender, RoutedEventArgs e)
{
var dialog = new AddModsDialog();
dialog.ShowDialog();
foreach (var id in dialog.Result)
{
var details = SteamHelper.GetItemDetails(id);
if (details.FileType != WorkshopFileType.Community)
continue;
var item = SteamHelper.GetModItem(details);
var desc = string.Join("\n", details.Description.ReadLines(5, true), "Double click to open the workshop page.");
ModList.Items.Add(new ModViewModel(item, desc));
}
}
private void modList_OnMouesDoubleClick(object sender, MouseButtonEventArgs e)
{
var box = (ListView)sender;
if (box.SelectedItem == null)
return;
var id = ((ModViewModel)box.SelectedItem).PublishedFileId;
Process.Start($"http://steamcommunity.com/sharedfiles/filedetails/?id={id}");
}
private void remBtn_Click(object sender, RoutedEventArgs e)
{
var box = (ListView)sender;
if (box.SelectedItems == null || box.SelectedItems.Count == 0)
return;
foreach (var item in box.SelectedItems)
{
box.Items.Remove(item);
}
}
}
}

View File

@@ -1,9 +1,10 @@
<Window x:Class="Piston.Server.MainWindow" <Window x:Class="Piston.Server.PistonUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Piston.Server" xmlns:local="clr-namespace:Piston.Server"
xmlns:views="clr-namespace:Piston.Server.Views"
mc:Ignorable="d" mc:Ignorable="d"
Title="Piston" Height="600" Width="900"> Title="Piston" Height="600" Width="900">
<DockPanel> <DockPanel>
@@ -16,8 +17,12 @@
</StackPanel> </StackPanel>
<TabControl x:Name="TabControl" DockPanel.Dock="Bottom" Margin="5,0,5,5"> <TabControl x:Name="TabControl" DockPanel.Dock="Bottom" Margin="5,0,5,5">
<TabItem Header="Configuration"> <TabItem Header="Configuration">
<DockPanel>
<local:ModsControl/>
<views:PropertyGrid x:Name="PropGrid"/>
</DockPanel>
</TabItem> </TabItem>
<TabItem Header="Chat/PlayerList"> <TabItem Header="Chat/Players">
<DockPanel> <DockPanel>
<local:PlayerListControl x:Name="PlayerList" DockPanel.Dock="Right" Width="250" IsEnabled="False"/> <local:PlayerListControl x:Name="PlayerList" DockPanel.Dock="Right" Width="250" IsEnabled="False"/>
<local:ChatControl x:Name="Chat" IsEnabled="False"/> <local:ChatControl x:Name="Chat" IsEnabled="False"/>

View File

@@ -77,7 +77,7 @@ namespace Piston.Server
protected override void OnClosing(CancelEventArgs e) protected override void OnClosing(CancelEventArgs e)
{ {
PistonServer.Server.StopServer(); PistonServer.Reset();
} }
private void BtnRestart_Click(object sender, RoutedEventArgs e) private void BtnRestart_Click(object sender, RoutedEventArgs e)

View File

@@ -0,0 +1,15 @@
<UserControl x:Class="Piston.Server.Views.PropertyGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Piston.Server.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<DataGrid x:Name="Grid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn x:Name="NameCol" Width="1*" Header="Name" Binding="{Binding Name}" IsReadOnly="True"/>
<DataGridTemplateColumn x:Name="ValCol" Width="1*" Header="Value"/>
</DataGrid.Columns>
</DataGrid>
</UserControl>

View File

@@ -0,0 +1,68 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Piston.Server.Views
{
/// <summary>
/// Interaction logic for PropertyGrid.xaml
/// </summary>
public partial class PropertyGrid : UserControl
{
public PropertyGrid()
{
InitializeComponent();
}
public void SetObject(object obj)
{
var props = obj.GetType().GetProperties();
foreach (var prop in props)
{
var p = prop.GetValue(obj);
Grid.Items.Add(new PropertyView(p, prop.Name));
}
}
}
public class PropertyView : ViewModel
{
private object _obj;
public string Name { get; }
public string Value { get { return _obj.ToString(); } }
public DataTemplate ValueEditTemplate;
public PropertyView(object obj, string name)
{
Name = name;
_obj = obj;
ValueEditTemplate = new DataTemplate();
}
}
/*
public class PropertyGridDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is IEnumerable)
{
}
}
}*/
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Extended.Wpf.Toolkit" version="2.9" targetFramework="net461" />
</packages>

View File

@@ -0,0 +1,36 @@
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("TestPlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestPlugin")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 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("bf0d9941-b488-4880-b378-a9bf942d140d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

35
TestPlugin/TestPlugin.cs Normal file
View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Piston.API;
using PistonAPI;
using Sandbox;
namespace TestPlugin
{
[Plugin("Test Plugin")]
public class TestPlugin : IPistonPlugin
{
public void Dispose()
{
MySandboxGame.Log.WriteLineAndConsole("TestDispose");
}
public void Init(object gameInstance)
{
MySandboxGame.Log.WriteLineAndConsole("TestInit");
}
public void Update()
{
MySandboxGame.Log.WriteLineAndConsole("TestUpdate");
}
public void Reload()
{
MySandboxGame.Log.WriteLineAndConsole("TestReload");
}
}
}

View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" 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>{BF0D9941-B488-4880-B378-A9BF942D140D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestPlugin</RootNamespace>
<AssemblyName>TestPlugin</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<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' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Sandbox.Game, Version=0.1.6103.31727, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\Sandbox.Game.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="VRage">
<HintPath>C:\Program Files (x86)\Steam\steamapps\common\SpaceEngineers\Bin64\VRage.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="TestPlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PistonAPI\Piston.API.csproj">
<Project>{fba5d932-6254-4a1e-baf4-e229fa94e3c2}</Project>
<Name>Piston.API</Name>
</ProjectReference>
<ProjectReference Include="..\PistonClient\Piston.Client.csproj">
<Project>{e36df745-260b-4956-a2e8-09f08b2e7161}</Project>
<Name>Piston.Client</Name>
</ProjectReference>
<ProjectReference Include="..\PistonServer\Piston.Server.csproj">
<Project>{ca50886b-7b22-4cd8-93a0-c06f38d4f77d}</Project>
<Name>Piston.Server</Name>
</ProjectReference>
<ProjectReference Include="..\Piston\Piston.csproj">
<Project>{7e01635c-3b67-472e-bcd6-c5539564f214}</Project>
<Name>Piston</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>