├── .gitattributes ├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Jenkins ├── jenkins-grab-se.ps1 └── release.ps1 ├── Jenkinsfile ├── LICENSE ├── NLog-user.config ├── NLog.config ├── NOTICE ├── README.md ├── Setup (run before opening solution).bat ├── Torch.API ├── ConnectionState.cs ├── Event │ ├── EventHandlerAttribute.cs │ ├── IEvent.cs │ ├── IEventHandler.cs │ └── IEventManager.cs ├── IPlayer.cs ├── IServerControls.cs ├── ITorchBase.cs ├── ITorchConfig.cs ├── InformationalVersion.cs ├── Managers │ ├── DependencyManagerExtensions.cs │ ├── DependencyProviderExtensions.cs │ ├── IChatManagerClient.cs │ ├── IChatManagerServer.cs │ ├── IDependencyManager.cs │ ├── IDependencyProvider.cs │ ├── IManager.cs │ ├── IMultiplayerManagerBase.cs │ ├── IMultiplayerManagerClient.cs │ ├── IMultiplayerManagerServer.cs │ ├── INetworkManager.cs │ └── IPluginManager.cs ├── ModAPI │ ├── Ingame │ │ └── GridExtensions.cs │ └── TorchAPI.cs ├── Plugins │ ├── ITorchPlugin.cs │ ├── IWpfPlugin.cs │ └── PluginAttribute.cs ├── Properties │ └── AssemblyInfo.cs ├── ServerState.cs ├── Session │ ├── GameSaveResult.cs │ ├── ITorchSession.cs │ ├── ITorchSessionManager.cs │ └── TorchSessionState.cs ├── Torch.API.csproj ├── TorchBranchType.cs ├── TorchGameState.cs ├── UGCServiceType.cs ├── Utils │ ├── ColorUtils.cs │ └── StringUtils.cs ├── WebAPI │ ├── JenkinsQuery.cs │ └── PluginQuery.cs └── packages.config ├── Torch.Client.Tests ├── Properties │ └── AssemblyInfo.cs ├── Torch.Client.Tests.csproj ├── TorchClientReflectionTest.cs ├── app.config └── packages.config ├── Torch.Mod ├── Messages │ ├── DialogMessage.cs │ ├── JoinServerMessage.cs │ ├── MessageBase.cs │ ├── NotificationMessage.cs │ ├── ShowDebugShape.cs │ └── VoxelResetMessage.cs ├── ModCommunication.cs ├── Torch.Mod.projitems ├── Torch.Mod.shproj └── TorchModCore.cs ├── Torch.Server.Tests ├── Properties │ └── AssemblyInfo.cs ├── Torch.Server.Tests.csproj ├── TorchServerReflectionTest.cs ├── TorchServerSessionSettingsTest.cs ├── app.config └── packages.config ├── Torch.Server ├── Commands │ └── WhitelistCommands.cs ├── FlowDocumentTarget.cs ├── Initializer.cs ├── ListBoxExtensions.cs ├── Managers │ ├── EntityControlManager.cs │ ├── GameUpdateManager.cs │ ├── InstanceManager.cs │ ├── MultiplayerManagerDedicated.cs │ ├── MultiplayerManagerDedicatedEventShim.cs │ ├── MultiplayerManagerDedicatedPatchShim.cs │ ├── RemoteAPIManager.cs │ └── UpdateManager.cs ├── MultiTextWriter.cs ├── NativeMethods.cs ├── Patches │ ├── NlogCustomTarget.cs │ ├── PortCheckingPatch.cs │ ├── PromotePatch.cs │ ├── ServerResponsePatch.cs │ ├── SteamLoginPatch.cs │ └── WorldLoadExceptionPatch.cs ├── Program.cs ├── Properties │ ├── Annotations.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── RichTextBoxWriter.cs ├── ServerManager.cs ├── Themes │ ├── Dark Theme Animated.xaml │ ├── Dark Theme.xaml │ ├── Light Theme Animated.xaml │ └── Light Theme.xaml ├── Torch.Server.csproj ├── TorchConfig.cs ├── TorchServer.cs ├── TorchService.cs ├── TorchServiceInstaller.cs ├── ViewModels │ ├── BlockLimitViewModel.cs │ ├── CheckpointViewModel.cs │ ├── ConfigDedicatedViewModel.cs │ ├── Entities │ │ ├── Blocks │ │ │ ├── BlockViewModel.cs │ │ │ ├── BlockViewModelGenerator.cs │ │ │ └── PropertyViewModel.cs │ │ ├── CharacterViewModel.cs │ │ ├── EntityControlViewModel.cs │ │ ├── EntityViewModel.cs │ │ ├── FloatingObjectViewModel.cs │ │ ├── GridViewModel.cs │ │ └── VoxelMapViewModel.cs │ ├── EntityTreeViewModel.cs │ ├── ILazyLoad.cs │ ├── ModItemInfo.cs │ ├── PluginManagerViewModel.cs │ ├── PluginViewModel.cs │ ├── SessionSettingsViewModel.cs │ ├── SessionSettingsViewModel1.cs │ ├── SteamUserViewModel.cs │ └── WorldConfigurationViewModel.cs ├── Views │ ├── AddWorkshopItemsDialog.xaml │ ├── AddWorkshopItemsDialog.xaml.cs │ ├── ChatControl.xaml │ ├── ChatControl.xaml.cs │ ├── ConfigControl.xaml │ ├── ConfigControl.xaml.cs │ ├── Converters │ │ ├── BooleanAndConverter.cs │ │ ├── DefinitionToIdConverter.cs │ │ ├── InverseBooleanConverter.cs │ │ ├── ListConverter.cs │ │ ├── ListConverterWorkshopId.cs │ │ ├── ModToIdConverter.cs │ │ ├── StringBuilderConverter.cs │ │ ├── StringIdConverter.cs │ │ └── Vector3DConverter.cs │ ├── Entities │ │ ├── Blocks │ │ │ ├── BlockView.xaml │ │ │ ├── BlockView.xaml.cs │ │ │ ├── PropertyView.xaml │ │ │ └── PropertyView.xaml.cs │ │ ├── CharacterView.xaml │ │ ├── CharacterView.xaml.cs │ │ ├── EntityControlHost.xaml │ │ ├── EntityControlHost.xaml.cs │ │ ├── EntityControlsView.xaml │ │ ├── EntityControlsView.xaml.cs │ │ ├── GridView.xaml │ │ ├── GridView.xaml.cs │ │ ├── VoxelMapView.xaml │ │ └── VoxelMapView.xaml.cs │ ├── EntitiesControl.xaml │ ├── EntitiesControl.xaml.cs │ ├── Extensions.cs │ ├── LogEventViewer.xaml │ ├── LogEventViewer.xaml.cs │ ├── LogMessageWindow.xaml │ ├── LogMessageWindow.xaml.cs │ ├── ModListControl.xaml │ ├── ModListControl.xaml.cs │ ├── ModsControl.xaml │ ├── ModsControl.xaml.cs │ ├── PlayerListControl.xaml │ ├── PlayerListControl.xaml.cs │ ├── PluginBrowser.xaml │ ├── PluginBrowser.xaml.cs │ ├── PluginDownloader.xaml │ ├── PluginDownloader.xaml.cs │ ├── PluginsControl.xaml │ ├── PluginsControl.xaml.cs │ ├── Resources.xaml │ ├── RoleEditor.xaml │ ├── RoleEditor.xaml.cs │ ├── SessionSettingsView.xaml │ ├── SessionSettingsView.xaml.cs │ ├── ThemeControl.xaml │ ├── ThemeControl.xaml.cs │ ├── TorchUI.xaml │ ├── TorchUI.xaml.cs │ ├── ValidationRules │ │ ├── ListConverterValidationRule.cs │ │ └── NumberValidationRule.cs │ ├── WorldGeneratorDialog.xaml │ ├── WorldGeneratorDialog.xaml.cs │ ├── WorldSelectControl.xaml │ └── WorldSelectControl.xaml.cs ├── app.config ├── packages.config └── torchicon.ico ├── Torch.Tests ├── PatchTest.cs ├── Properties │ └── AssemblyInfo.cs ├── ReflectionSystemTest.cs ├── ReflectionTestManager.cs ├── TestUtils.cs ├── Torch.Tests.csproj ├── TorchReflectionTest.cs ├── app.config └── packages.config ├── Torch.sln ├── Torch.sln.DotSettings ├── Torch ├── Collections │ ├── BinaryMinHeap.cs │ ├── KeyTree.cs │ ├── MTObservableCollection.cs │ ├── MtObservableCollectionBase.cs │ ├── MtObservableEvent.cs │ ├── MtObservableList.cs │ ├── MtObservableSortedDictionary.cs │ ├── RollingAverage.cs │ ├── SortedView.cs │ ├── SystemSortedView.cs │ ├── TransformComparer.cs │ └── TransformEnumerator.cs ├── CommandLine.cs ├── Commands │ ├── CategoryAttribute.cs │ ├── Command.cs │ ├── CommandAttribute.cs │ ├── CommandContext.cs │ ├── CommandManager.cs │ ├── CommandModule.cs │ ├── CommandTree.cs │ ├── ConsoleCommandContext.cs │ ├── Permissions │ │ ├── PermissionAttribute.cs │ │ └── PermissonsSystem.cs │ └── TorchCommands.cs ├── Event │ ├── EventList.cs │ ├── EventManager.cs │ ├── EventShimAttribute.cs │ └── IEventList.cs ├── Extensions │ ├── DispatcherExtensions.cs │ ├── ICollectionExtensions.cs │ ├── LinqExtensions.cs │ ├── MyPlayerCollectionExtensions.cs │ └── StringExtensions.cs ├── Managers │ ├── ChatManager │ │ ├── ChatManagerClient.cs │ │ └── ChatManagerServer.cs │ ├── DependencyManager.cs │ ├── EntityManager.cs │ ├── FilesystemManager.cs │ ├── Manager.cs │ ├── MultiplayerManagerBase.cs │ ├── NetworkManager │ │ └── NetworkManager.cs │ └── PatchManager │ │ ├── AssemblyMemory.cs │ │ ├── DecoratedMethod.cs │ │ ├── EmitExtensions.cs │ │ ├── MSIL │ │ ├── ITokenResolver.cs │ │ ├── MsilArgument.cs │ │ ├── MsilInstruction.cs │ │ ├── MsilInstructionExtensions.cs │ │ ├── MsilLabel.cs │ │ ├── MsilLocal.cs │ │ ├── MsilOperand.cs │ │ ├── MsilOperandBrTarget.cs │ │ ├── MsilOperandInline.cs │ │ ├── MsilOperandSwitch.cs │ │ └── MsilTryCatchOperation.cs │ │ ├── MethodRewritePattern.cs │ │ ├── NativeLibrary.cs │ │ ├── PatchContext.cs │ │ ├── PatchManager.cs │ │ ├── PatchPriorityAttribute.cs │ │ ├── PatchShimAttribute.cs │ │ ├── PatchUtilities.cs │ │ └── Transpile │ │ ├── LoggingILGenerator.cs │ │ ├── MethodContext.cs │ │ └── MethodTranspiler.cs ├── MySteamServiceWrapper.cs ├── Patches │ ├── AutoSavePatch.cs │ ├── FactionPatch.cs │ ├── GameAnalyticsPatch.cs │ ├── GameStatePatchShim.cs │ ├── KeenLogPatch.cs │ ├── MessageSizeLimitPatch.cs │ ├── ModsDownloadingPatch.cs │ ├── PhysicsMemoryPatch.cs │ ├── SessionDownloadPatch.cs │ └── TorchAsyncSaving.cs ├── Persistent.cs ├── Plugins │ ├── PluginDependency.cs │ ├── PluginManager.cs │ └── PluginManifest.cs ├── Properties │ └── AssemblyInfo.cs ├── Session │ ├── TorchSession.cs │ └── TorchSessionManager.cs ├── Torch.csproj ├── TorchBase.cs ├── TorchPluginBase.cs ├── Utils │ ├── MiscExtensions.cs │ ├── ModItemUtils.cs │ ├── Reflected │ │ ├── ReflectedEventReplaceAttribute.cs │ │ ├── ReflectedEventReplacer.cs │ │ ├── ReflectedFieldInfoAttribute.cs │ │ ├── ReflectedGetterAttribute.cs │ │ ├── ReflectedLazyAttribute.cs │ │ ├── ReflectedManager.cs │ │ ├── ReflectedMemberAttribute.cs │ │ ├── ReflectedMethodAttribute.cs │ │ ├── ReflectedMethodInfoAttribute.cs │ │ ├── ReflectedPropertyInfoAttribute.cs │ │ ├── ReflectedSetterAttribute.cs │ │ └── ReflectedStaticMethodAttribute.cs │ ├── Reflection.cs │ ├── SteamWorkshopTools │ │ ├── KeyValueExtensions.cs │ │ ├── PublishedItemDetails.cs │ │ └── WebAPI.cs │ ├── SynchronizationExtensions.cs │ ├── TorchAssemblyResolver.cs │ └── TorchLauncher.cs ├── VRageGame.cs ├── ViewModels │ ├── ModViewModel.cs │ ├── PlayerViewModel.cs │ ├── PluginViewModel.cs │ └── ViewModel.cs ├── Views │ ├── CollectionEditor.xaml │ ├── CollectionEditor.xaml.cs │ ├── DictionaryEditor.xaml │ ├── DictionaryEditor.xaml.cs │ ├── DisplayAttribute.cs │ ├── EmbeddedCollectionEditor.xaml │ ├── EmbeddedCollectionEditor.xaml.cs │ ├── FlagsEditor.xaml │ ├── FlagsEditor.xaml.cs │ ├── ObjectCollectionEditor.xaml │ ├── ObjectCollectionEditor.xaml.cs │ ├── ObjectEditor.xaml │ ├── ObjectEditor.xaml.cs │ ├── PropertyGrid.xaml │ └── PropertyGrid.xaml.cs ├── app.config └── packages.config ├── TransformOnBuild.targets ├── Versioning ├── AssemblyVersion.cs └── version.ps1 └── torchicon.ico /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | - [ ] Verify that this issue is related to Torch and not a Torch plugin or the vanilla game 2 | - [ ] Ensure that the issue is reproducible for testing (provide a link to a test world if necessary) 3 | - [ ] Is this a suggestion? 4 | 5 | **Torch Version:** 1.x.xxx.xxx **SE Version:** 1.xxx.xxx 6 | 7 | ### Expected Behavior 8 | What did you expect to happen? 9 | 10 | ### Observed Behavior 11 | What actually happened? 12 | 13 | ### Steps to Reproduce 14 | 1. How did this issue get triggered? 15 | 2. Write the steps here. 16 | 17 | ### Other Information 18 | Provide links to game logs or saves here if necessary. 19 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Torch 1.1.229.265 2 | * Features 3 | - Added more lenient version parsing for plugins (v#.# should work) 4 | - Added countdown option to restart command (!restart [seconds]) 5 | * Fixes 6 | - General fixes to work with the latest SE version 7 | - Fixed config changes not saving 8 | - (hopefully) Fixed issue causing crashes on servers using the Windows Classic theme 9 | 10 | # Torch 1.1.207.7 11 | * Notes 12 | - This release makes significant changes to TorchConfig.xml. It has been renamed to Torch.cfg and has different options. 13 | * Features 14 | - Plugins, Torch, and the DS can now all update automatically 15 | - Changed command prefix to ! 16 | - Added manual save command (thanks to Maldark) 17 | - Added restart command 18 | - Improved instance creation: now creates an entire skeleton instance with blank config 19 | - Added instance name to console title 20 | * Fixes 21 | - Optimized UI so it's snappier and freezes less often 22 | - Fixed NetworkManager.RaiseEvent overload that had an off-by-one bug 23 | - Fixed chat window so it automatically scrolls down 24 | 25 | # Torch 1.0.182.329 26 | * Improved logging, logs now to go the Logs folder and aren't deleted on start 27 | * Fixed chat tab not enabling with -autostart 28 | * Fixed player list 29 | * Watchdog time-out is now configurable in TorchConfig.xml 30 | * Fixed infinario log spam 31 | * Fixed crash when sending empty message from chat tab 32 | * Fixed permissions on Torch commands 33 | * Changed plugin StoragePath to the current instance path (per-instance configs) -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Making a Pull Request 2 | * Fork this repository and make sure your local **staging** branch is up to date with the main repository. 3 | * Create a new branch from the **staging** branch for your addition with an appropriate name, e.g. **add-restart-command** 4 | * PRs work by submitting the *entire* branch, so this allows you to continue work without locking up your whole repository. 5 | * Commit your changes to that branch, making sure that you **follow the code guidelines below**. 6 | * Submit your branch as a PR to be reviewed, with Torch's **staging** branch as the base. 7 | 8 | ## Naming Conventions 9 | * Types: **PascalCase** 10 | * Prefix interfaces with "**I**" 11 | * Suffix delegates with "**Del**" 12 | * Methods: **PascalCase** 13 | * Method names should generally use verbs in the infinitive tense, for example `GetValue()` or `OpenFile()`. Callbacks and events should use present continuous (-ing) or past tense depending on the context. 14 | * Non-Private Members: **PascalCase** 15 | * Private Members: **_camelCase** 16 | 17 | ## Code Design 18 | * **One type per file** with the exception of nested types and delegate declarations. 19 | * **No public fields** except for consts, use properties instead 20 | * **No stateful static types.** These are a pain to clean up, static types should not store any information. 21 | * Use **[dependency injection](https://stackoverflow.com/a/130862)** when possible. Most Torch code uses constructor injection. 22 | * **Events and actions** should be null checked before calling or invoked with the `action?.Invoke()` syntax. 23 | 24 | ## Documentation 25 | * All types and members not marked **private** or **internal** should have XML documentation using the `/// ` tag. 26 | * Interface implementations and overridden methods should use the `/// ` tag unless the summary needs to be changed from the base/interface summary. 27 | -------------------------------------------------------------------------------- /Jenkins/jenkins-grab-se.ps1: -------------------------------------------------------------------------------- 1 | pushd 2 | 3 | $steamData = "C:/Steam/Data/" 4 | $steamCMDPath = "C:/Steam/steamcmd/" 5 | $steamCMDZip = "C:/Steam/steamcmd.zip" 6 | 7 | Add-Type -AssemblyName System.IO.Compression.FileSystem 8 | 9 | if (!(Test-Path $steamData)) { 10 | mkdir "$steamData" 11 | } 12 | if (!(Test-Path $steamCMDPath)) { 13 | if (!(Test-Path $steamCMDZip)) { 14 | (New-Object System.Net.WebClient).DownloadFile("https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip", "$steamCMDZip"); 15 | } 16 | [System.IO.Compression.ZipFile]::ExtractToDirectory($steamCMDZip, $steamCMDPath) 17 | } 18 | 19 | cd "$steamData" 20 | & "$steamCMDPath/steamcmd.exe" "+login anonymous" "+force_install_dir $steamData" "+app_update 298740 validate" "+quit" 21 | 22 | popd 23 | -------------------------------------------------------------------------------- /NLog-user.config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /NLog.config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Torch 2 | Copyright 2016-2017 TorchAPI 3 | 4 | This product includes software developed at TorchAPI. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Discord](https://discordapp.com/api/guilds/230191591640268800/widget.png)](https://discord.gg/8uHZykr) 2 | 3 | # What is Torch? 4 | Torch is the successor to SE Server Extender and gives server admins the tools they need to keep their Space Engineers servers running smoothly. It features a user interface with live management tools and a plugin system so you can run your server exactly how you'd like. Torch is still in early development so there may be bugs and incomplete features. 5 | 6 | ## Torch.Server 7 | 8 | ### Features 9 | * WPF-based user interface 10 | * Chat: interact with the game chat and run commands without having to join the game. 11 | * Entity manager: realtime modification of ingame entities such as stopping grids and changing block settings without having to join the game 12 | * Organized, easy to use configuration editor 13 | * Extensible using the Torch plugin system 14 | 15 | ### Installation 16 | 17 | * Get the latest Torch release here: https://build.torchapi.com/job/Torch/job/master/lastSuccessfulBuild/artifact/bin/torch-server.zip 18 | * Unzip the Torch release into its own directory and run the executable. It will automatically download the SE DS and generate the other necessary files. 19 | - If you already have a DS installed you can unzip the Torch files into the folder that contains the DedicatedServer64 folder. 20 | 21 | # Building 22 | To build Torch you must first have a complete SE Dedicated installation somewhere. Before you open the solution, run the Setup batch file and enter the path of that installation's DedicatedServer64 folder. The script will make a symlink to that folder so the Torch solution can find the DLL references it needs. 23 | 24 | If you have a more enjoyable server experience because of Torch, please consider supporting us on Patreon. (https://www.patreon.com/TorchSE) 25 | 26 | -------------------------------------------------------------------------------- /Setup (run before opening solution).bat: -------------------------------------------------------------------------------- 1 | :: This script creates a symlink to the game binaries to account for different installation directories on different systems. 2 | 3 | @echo off 4 | set /p path="Please enter the folder location of your SpaceEngineersDedicated.exe: " 5 | cd %~dp0 6 | mklink /J GameBinaries "%path%" 7 | if errorlevel 1 goto Error 8 | echo Done! You can now open the Torch solution without issue. 9 | goto End 10 | :Error 11 | echo An error occured creating the symlink. 12 | :End 13 | pause 14 | -------------------------------------------------------------------------------- /Torch.API/ConnectionState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Torch.API 4 | { 5 | /// 6 | /// Identifies a player's current connection state. 7 | /// 8 | [Flags] 9 | public enum ConnectionState 10 | { 11 | /// 12 | /// Unknown state. 13 | /// 14 | Unknown, 15 | 16 | /// 17 | /// Connected to game. 18 | /// 19 | Connected = 1, 20 | 21 | /// 22 | /// Left the game. 23 | /// 24 | Left = 2, 25 | 26 | /// 27 | /// Disconnected from the game. 28 | /// 29 | Disconnected = 4, 30 | 31 | /// 32 | /// Kicked from the game. 33 | /// 34 | Kicked = 8, 35 | 36 | /// 37 | /// Banned from the game. 38 | /// 39 | Banned = 16, 40 | } 41 | } -------------------------------------------------------------------------------- /Torch.API/Event/EventHandlerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Torch.API.Event 4 | { 5 | /// 6 | /// Attribute indicating that a method should be invoked when the event occurs. 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public class EventHandlerAttribute : Attribute 10 | { 11 | /// 12 | /// Events are executed from low priority to high priority. 13 | /// 14 | /// 15 | /// While this may seem unintuitive this gives the high priority events the final say on changing/canceling events. 16 | /// 17 | public int Priority { get; set; } = 0; 18 | 19 | /// 20 | /// Specifies if this handler should ignore a consumed event. 21 | /// 22 | /// 23 | /// If is true and the event is cancelled by a lower priority handler this handler won't be invoked. 24 | /// 25 | /// 26 | public bool SkipCancelled { get; set; } = false; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Torch.API/Event/IEvent.cs: -------------------------------------------------------------------------------- 1 | namespace Torch.API.Event 2 | { 3 | public interface IEvent 4 | { 5 | /// 6 | /// An event that has been cancelled will no be processed in the default manner. 7 | /// 8 | /// 9 | bool Cancelled { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Torch.API/Event/IEventHandler.cs: -------------------------------------------------------------------------------- 1 | namespace Torch.API.Event 2 | { 3 | /// 4 | /// Interface used to tag an event handler. This does not register it with the event manager. 5 | /// 6 | public interface IEventHandler 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Torch.API/Event/IEventManager.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using Torch.API.Managers; 3 | 4 | namespace Torch.API.Event 5 | { 6 | /// 7 | /// Manager class responsible for registration of event handlers. 8 | /// 9 | public interface IEventManager : IManager 10 | { 11 | /// 12 | /// Registers all event handler methods contained in the given instance 13 | /// 14 | /// Instance to register 15 | /// true if added, false otherwise 16 | [MethodImpl(MethodImplOptions.NoInlining)] 17 | bool RegisterHandler(IEventHandler handler); 18 | 19 | 20 | /// 21 | /// Unregisters all event handler methods contained in the given instance 22 | /// 23 | /// Instance to unregister 24 | /// true if removed, false otherwise 25 | [MethodImpl(MethodImplOptions.NoInlining)] 26 | bool UnregisterHandler(IEventHandler handler); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Torch.API/IPlayer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using VRage.Game.ModAPI; 7 | 8 | namespace Torch.API 9 | { 10 | /// 11 | /// Represents a player on the server. 12 | /// 13 | public interface IPlayer 14 | { 15 | /// 16 | /// The name of the player. 17 | /// 18 | string Name { get; } 19 | 20 | /// 21 | /// The SteamID of the player. 22 | /// 23 | ulong SteamId { get; } 24 | 25 | /// 26 | /// The player's current connection state. 27 | /// 28 | ConnectionState State { get; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Torch.API/IServerControls.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace Torch.API 4 | { 5 | public interface IServerControls 6 | { 7 | bool AddGUITab(string name, UserControl control); 8 | bool RemoveGUITab(string name); 9 | } 10 | } -------------------------------------------------------------------------------- /Torch.API/ITorchConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Torch.API; 4 | 5 | namespace Torch 6 | { 7 | public interface ITorchConfig 8 | { 9 | bool Autostart { get; set; } 10 | bool ForceUpdate { get; set; } 11 | bool GetPluginUpdates { get; set; } 12 | bool GetTorchUpdates { get; set; } 13 | string InstanceName { get; set; } 14 | string InstancePath { get; set; } 15 | bool NoGui { get; set; } 16 | bool NoUpdate { get; set; } 17 | List Plugins { get; set; } 18 | bool LocalPlugins { get; set; } 19 | bool RestartOnCrash { get; set; } 20 | bool ShouldUpdatePlugins { get; } 21 | bool BypassIsReloadableFlag { get; set; } 22 | bool ShouldUpdateTorch { get; } 23 | int TickTimeout { get; set; } 24 | string WaitForPID { get; set; } 25 | string ChatName { get; set; } 26 | string ChatColor { get; set; } 27 | string TestPlugin { get; set; } 28 | bool DisconnectOnRestart { get; set; } 29 | int WindowWidth { get; set; } 30 | int WindowHeight { get; set; } 31 | int FontSize { get; set; } 32 | UGCServiceType UgcServiceType { get; set; } 33 | TorchBranchType BranchName { get; set; } 34 | bool SendLogsToKeen { get; set; } 35 | bool DeleteMiniDumps { get; set; } 36 | string LoginToken { get; set; } 37 | bool RestartOnGameUpdate { get; set; } 38 | int GameUpdateRestartDelayMins { get; set; } 39 | bool EnableWhitelist { get; set; } 40 | List Whitelist { get; set; } 41 | 42 | void Save(string path = null); 43 | } 44 | } -------------------------------------------------------------------------------- /Torch.API/InformationalVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API 8 | { 9 | /// 10 | /// Version in the form v#.#.#.#-branch 11 | /// 12 | public class InformationalVersion 13 | { 14 | public Version Version { get; set; } 15 | public string Branch { get; set; } 16 | 17 | public static bool TryParse(string input, out InformationalVersion version) 18 | { 19 | version = default(InformationalVersion); 20 | var trim = input.TrimStart('v'); 21 | var info = trim.Split(new[]{'-'}, 2); 22 | if (!Version.TryParse(info[0], out Version result)) 23 | return false; 24 | 25 | version = new InformationalVersion { Version = result }; 26 | 27 | if (info.Length > 1) 28 | version.Branch = info[1]; 29 | 30 | return true; 31 | } 32 | 33 | /// 34 | public override string ToString() 35 | { 36 | if (Branch == null) 37 | return $"v{Version}"; 38 | 39 | return $"v{Version}-{string.Join("-", Branch)}"; 40 | } 41 | 42 | public static explicit operator InformationalVersion(Version v) 43 | { 44 | return new InformationalVersion { Version = v }; 45 | } 46 | 47 | public static implicit operator Version(InformationalVersion v) 48 | { 49 | return v.Version; 50 | } 51 | 52 | public static bool operator >(InformationalVersion lhs, InformationalVersion rhs) 53 | { 54 | return lhs.Version > rhs.Version; 55 | } 56 | 57 | public static bool operator <(InformationalVersion lhs, InformationalVersion rhs) 58 | { 59 | return lhs.Version < rhs.Version; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Torch.API/Managers/DependencyManagerExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Torch.API.Managers 4 | { 5 | public static class DependencyManagerExtensions 6 | { 7 | /// 8 | /// Removes a single manager from this dependency manager. 9 | /// 10 | /// The dependency type to remove 11 | /// The manager that was removed, or null if one wasn't removed 12 | /// When removing managers from an initialized dependency manager 13 | public static IManager RemoveManager(this IDependencyManager depManager, Type managerType) 14 | { 15 | IManager mgr = depManager.GetManager(managerType); 16 | return depManager.RemoveManager(mgr) ? mgr : null; 17 | } 18 | /// 19 | /// Removes a single manager from this dependency manager. 20 | /// 21 | /// The dependency type to remove 22 | /// The manager that was removed, or null if one wasn't removed 23 | /// When removing managers from an initialized dependency manager 24 | public static IManager RemoveManager(this IDependencyManager depManager) 25 | { 26 | return depManager.RemoveManager(typeof(T)); 27 | } 28 | 29 | } 30 | } -------------------------------------------------------------------------------- /Torch.API/Managers/DependencyProviderExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Torch.API.Managers 2 | { 3 | public static class DependencyProviderExtensions 4 | { 5 | /// 6 | /// Gets the manager that provides the given type. If there is no such manager, returns null. 7 | /// 8 | /// Type of manager 9 | /// manager, or null if none exists 10 | public static T GetManager(this IDependencyProvider depProvider) where T : class, IManager 11 | { 12 | return (T)depProvider.GetManager(typeof(T)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Torch.API/Managers/IDependencyProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API.Managers 8 | { 9 | public interface IDependencyProvider 10 | { 11 | /// 12 | /// Gets the manager that provides the given type. If there is no such manager, returns null. 13 | /// 14 | /// Type of manager 15 | /// manager, or null if none exists 16 | IManager GetManager(Type type); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Torch.API/Managers/IManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API.Managers 8 | { 9 | /// 10 | /// Base interface for Torch managers. 11 | /// 12 | public interface IManager 13 | { 14 | /// 15 | /// Attaches the manager to the session. Called once this manager's dependencies have been attached. 16 | /// 17 | void Attach(); 18 | 19 | /// 20 | /// Detaches the manager from the session. Called before this manager's dependencies are detached. 21 | /// 22 | void Detach(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Torch.API/Managers/IMultiplayerManagerBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using VRage.Game; 5 | using VRage.Game.ModAPI; 6 | 7 | namespace Torch.API.Managers 8 | { 9 | /// 10 | /// API for multiplayer related functions common to servers and clients. 11 | /// 12 | public interface IMultiplayerManagerBase : IManager 13 | { 14 | /// 15 | /// Fired when a player joins. 16 | /// 17 | event Action PlayerJoined; 18 | 19 | /// 20 | /// Fired when a player disconnects. 21 | /// 22 | event Action PlayerLeft; 23 | 24 | /// 25 | /// Gets a player by their Steam64 ID or returns null if the player isn't found. 26 | /// 27 | IMyPlayer GetPlayerBySteamId(ulong id); 28 | 29 | /// 30 | /// Gets a player by their display name or returns null if the player isn't found. 31 | /// 32 | IMyPlayer GetPlayerByName(string name); 33 | 34 | /// 35 | /// Gets the steam username of a member's steam ID 36 | /// 37 | /// steam ID 38 | /// steam username 39 | string GetSteamUsername(ulong steamId); 40 | } 41 | } -------------------------------------------------------------------------------- /Torch.API/Managers/IMultiplayerManagerClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API.Managers 8 | { 9 | public interface IMultiplayerManagerClient : IMultiplayerManagerBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Torch.API/Managers/INetworkManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using VRage; 7 | using VRage.Library.Collections; 8 | using VRage.Network; 9 | 10 | namespace Torch.API.Managers 11 | { 12 | /// 13 | /// API for the network intercept. 14 | /// 15 | public interface INetworkManager : IManager 16 | { 17 | /// 18 | /// Register a network handler. 19 | /// 20 | void RegisterNetworkHandler(INetworkHandler handler); 21 | 22 | /// 23 | /// Unregister a network handler. 24 | /// 25 | /// true if the handler was unregistered, false if it wasn't registered to begin with 26 | bool UnregisterNetworkHandler(INetworkHandler handler); 27 | } 28 | 29 | /// 30 | /// Handler for multiplayer network messages. 31 | /// 32 | public interface INetworkHandler 33 | { 34 | /// 35 | /// Returns if the handler can process the call site. 36 | /// 37 | bool CanHandle(CallSite callSite); 38 | 39 | /// 40 | /// Processes a network message. 41 | /// 42 | /// true if the message should be discarded 43 | bool Handle(ulong remoteUserId, CallSite site, BitStream stream, object obj, MyPacket packet); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Torch.API/Managers/IPluginManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Torch.API.Plugins; 4 | using VRage.Collections; 5 | using VRage.Plugins; 6 | 7 | namespace Torch.API.Managers 8 | { 9 | /// 10 | /// API for the Torch plugin manager. 11 | /// 12 | public interface IPluginManager : IManager, IEnumerable 13 | { 14 | /// 15 | /// Fired when plugins are loaded. 16 | /// 17 | event Action> PluginsLoaded; 18 | 19 | /// 20 | /// Collection of loaded plugins. 21 | /// 22 | IReadOnlyDictionary Plugins { get; } 23 | 24 | /// 25 | /// Updates all loaded plugins. 26 | /// 27 | void UpdatePlugins(); 28 | 29 | /// 30 | /// Load plugins. 31 | /// 32 | void LoadPlugins(); 33 | } 34 | } -------------------------------------------------------------------------------- /Torch.API/ModAPI/Ingame/GridExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Sandbox.Game.Entities.Blocks; 8 | using Sandbox.ModAPI.Ingame; 9 | using VRage.Game.ModAPI.Ingame; 10 | 11 | namespace Torch.API.ModAPI.Ingame 12 | { 13 | public static class GridExtensions 14 | { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Torch.API/ModAPI/TorchAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.CompilerServices; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | //Needed so Torch can set the instance here without exposing anything bad to mods or creating a circular dependency. 10 | [assembly: InternalsVisibleTo("Torch")] 11 | namespace Torch.API.ModAPI 12 | { 13 | /// 14 | /// Entry point for mods to access Torch. 15 | /// 16 | public static class TorchAPI 17 | { 18 | internal static ITorchBase Instance; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Torch.API/Plugins/ITorchPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography.X509Certificates; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Torch.API.Plugins 9 | { 10 | public interface ITorchPlugin : IDisposable 11 | { 12 | /// 13 | /// A unique ID for the plugin. 14 | /// 15 | Guid Id { get; } 16 | 17 | /// 18 | /// The version of the plugin. 19 | /// 20 | string Version { get; } 21 | 22 | /// 23 | /// The name of the plugin. 24 | /// 25 | string Name { get; } 26 | 27 | /// 28 | /// Enable/Disable Plugin reloading 29 | /// 30 | bool IsReloadable { get; set; } 31 | 32 | /// 33 | /// This is called before the game loop is started. 34 | /// 35 | /// Torch instance 36 | void Init(ITorchBase torchBase); 37 | 38 | /// 39 | /// This is called on the game thread after each tick. 40 | /// 41 | void Update(); 42 | 43 | /// 44 | /// Plugin's enabled state. Mainly for UI niceness 45 | /// 46 | PluginState State { get; } 47 | } 48 | 49 | public enum PluginState 50 | { 51 | NotInitialized, 52 | DisabledError, 53 | DisabledUser, 54 | UpdateRequired, 55 | UninstallRequested, 56 | NotInstalled, 57 | MissingDependency, 58 | Enabled 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Torch.API/Plugins/IWpfPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | 8 | namespace Torch.API.Plugins 9 | { 10 | public interface IWpfPlugin : ITorchPlugin 11 | { 12 | /// 13 | /// Used by the server's WPF interface to load custom plugin controls. 14 | /// You must instantiate your plugin's control object here, otherwise it will not be owned by the correct thread for WPF. 15 | /// 16 | UserControl GetControl(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Torch.API/Plugins/PluginAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Torch.API.Plugins 9 | { 10 | /// 11 | /// Indicates that the given type should be loaded by the plugin manager as a plugin. 12 | /// 13 | [Obsolete("All plugin meta-information is now defined in the manifest.xml.")] 14 | [AttributeUsage(AttributeTargets.Class)] 15 | public class PluginAttribute : Attribute 16 | { 17 | /// 18 | /// The display name of the plugin 19 | /// 20 | public string Name { get; } 21 | /// 22 | /// The version of the plugin 23 | /// 24 | public Version Version { get; } 25 | /// 26 | /// The GUID of the plugin 27 | /// 28 | public Guid Guid { get; } 29 | 30 | /// 31 | /// Creates a new plugin attribute with the given attributes 32 | /// 33 | /// 34 | /// 35 | /// 36 | public PluginAttribute(string name, string version, string guid) 37 | { 38 | Name = name; 39 | Version = Version.Parse(version); 40 | Guid = Guid.Parse(guid); 41 | } 42 | 43 | /// 44 | /// Creates a new plugin attribute with the given attributes. Version is computed as the version of the assembly containing the given type. 45 | /// 46 | /// 47 | /// Version is this type's assembly's version 48 | /// 49 | public PluginAttribute(string name, Type versionSupplier, string guid) 50 | { 51 | Name = name; 52 | Version = versionSupplier.Assembly.GetName().Version; 53 | Guid = Guid.Parse(guid); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Torch.API/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("Torch API")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyCompany("")] 7 | [assembly: AssemblyProduct("Torch")] 8 | [assembly: AssemblyCopyright("Copyright © Torch API 2017")] 9 | [assembly: AssemblyTrademark("")] 10 | [assembly: AssemblyCulture("")] 11 | [assembly: ComVisible(false)] 12 | 13 | #if DEBUG 14 | [assembly: AssemblyConfiguration("Debug")] 15 | #else 16 | [assembly: AssemblyConfiguration("Release")] 17 | #endif -------------------------------------------------------------------------------- /Torch.API/ServerState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API 8 | { 9 | /// 10 | /// Used to indicate the state of the dedicated server. 11 | /// 12 | public enum ServerState 13 | { 14 | /// 15 | /// The server is not running. 16 | /// 17 | Stopped, 18 | 19 | /// 20 | /// The server is starting/loading the session. 21 | /// 22 | Starting, 23 | 24 | /// 25 | /// The server is running. 26 | /// 27 | Running, 28 | 29 | /// 30 | /// The server encountered an error. 31 | /// 32 | Error 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Torch.API/Session/GameSaveResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API.Session 8 | { 9 | /// 10 | /// The result of a save operation 11 | /// 12 | public enum GameSaveResult 13 | { 14 | /// 15 | /// Successfully saved 16 | /// 17 | Success = 0, 18 | 19 | /// 20 | /// The game wasn't ready to be saved 21 | /// 22 | GameNotReady = -1, 23 | 24 | /// 25 | /// Failed to take the snapshot of the current world state 26 | /// 27 | FailedToTakeSnapshot = -2, 28 | 29 | /// 30 | /// Failed to save the snapshot to disk 31 | /// 32 | FailedToSaveToDisk = -3, 33 | 34 | /// 35 | /// An unknown error occurred 36 | /// 37 | UnknownError = -4, 38 | 39 | /// 40 | /// The save operation timed out 41 | /// 42 | TimedOut = -5 43 | } 44 | } -------------------------------------------------------------------------------- /Torch.API/Session/ITorchSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Sandbox.Game.World; 7 | using Torch.API.Managers; 8 | 9 | namespace Torch.API.Session 10 | { 11 | /// 12 | /// Represents the Torch code working with a single game session 13 | /// 14 | public interface ITorchSession 15 | { 16 | /// 17 | /// The Torch instance this session is bound to 18 | /// 19 | ITorchBase Torch { get; } 20 | 21 | /// 22 | /// The Space Engineers game session this session is bound to. 23 | /// 24 | MySession KeenSession { get; } 25 | 26 | /// 27 | IDependencyManager Managers { get; } 28 | 29 | /// 30 | /// The current state of the session 31 | /// 32 | TorchSessionState State { get; } 33 | 34 | /// 35 | /// Event raised when the changes. 36 | /// 37 | event TorchSessionStateChangedDel StateChanged; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Torch.API/Session/TorchSessionState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API.Session 8 | { 9 | /// 10 | /// Represents the state of a 11 | /// 12 | public enum TorchSessionState 13 | { 14 | /// 15 | /// The session has been created, and is now loading. 16 | /// 17 | Loading, 18 | /// 19 | /// The session has loaded, and is now running. 20 | /// 21 | Loaded, 22 | /// 23 | /// The session was running, and is now unloading. 24 | /// 25 | Unloading, 26 | /// 27 | /// The session was unloading, and is now unloaded and stopped. 28 | /// 29 | Unloaded 30 | } 31 | 32 | /// 33 | /// Callback raised when a session's state changes 34 | /// 35 | /// The session who had a state change 36 | /// The session's new state 37 | public delegate void TorchSessionStateChangedDel(ITorchSession session, TorchSessionState newState); 38 | } 39 | -------------------------------------------------------------------------------- /Torch.API/TorchBranchType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.API 8 | { 9 | public enum TorchBranchType 10 | { 11 | publicbeta, 12 | master, 13 | staging, 14 | dev 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Torch.API/TorchGameState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Sandbox; 7 | 8 | namespace Torch.API 9 | { 10 | /// 11 | /// Represents the state of a 12 | /// 13 | public enum TorchGameState 14 | { 15 | /// 16 | /// The game is currently being created. 17 | /// 18 | Creating, 19 | /// 20 | /// The game has been created and is ready to begin loading. 21 | /// 22 | Created, 23 | /// 24 | /// The game is currently loading. 25 | /// 26 | Loading, 27 | /// 28 | /// The game is fully loaded and ready to start sessions 29 | /// 30 | Loaded, 31 | /// 32 | /// The game is beginning the unload sequence 33 | /// 34 | Unloading, 35 | /// 36 | /// The game has been shutdown and is no longer active 37 | /// 38 | Unloaded 39 | } 40 | 41 | /// 42 | /// Callback raised when a game's state changes 43 | /// 44 | /// The game who had a state change 45 | /// The game's new state 46 | public delegate void TorchGameStateChangedDel(MySandboxGame game, TorchGameState newState); 47 | } 48 | -------------------------------------------------------------------------------- /Torch.API/UGCServiceType.cs: -------------------------------------------------------------------------------- 1 | namespace Torch.API 2 | { 3 | public enum UGCServiceType 4 | { 5 | Steam, 6 | EOS 7 | } 8 | } -------------------------------------------------------------------------------- /Torch.API/Utils/ColorUtils.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Media; 2 | using VRage.Game; 3 | using Color = VRageMath.Color; 4 | 5 | namespace Torch.Utils 6 | { 7 | public static class ColorUtils 8 | { 9 | /// 10 | /// Convert the old "font" or a RGB hex code to a Color. 11 | /// 12 | public static Color TranslateColor(string font) 13 | { 14 | if (StringUtils.IsFontEnum(font)) 15 | { 16 | // RGB values copied from Fonts.sbc 17 | switch (font) 18 | { 19 | case MyFontEnum.Blue: 20 | return new Color(220, 244, 252); 21 | case MyFontEnum.Red: 22 | return new Color(227, 65, 65); 23 | case MyFontEnum.Green: 24 | return new Color(101, 182, 193); 25 | case MyFontEnum.DarkBlue: 26 | return new Color(94, 115, 127); 27 | default: 28 | return Color.White; 29 | } 30 | } 31 | else 32 | { 33 | // VRage color doesn't have its own hex code parser and I don't want to write one 34 | var conv = (System.Windows.Media.Color)(ColorConverter.ConvertFromString(font) ?? 35 | System.Windows.Media.Color.FromRgb(255, 255, 255)); 36 | return new Color(conv.R, conv.G, conv.B); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Torch.API/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Torch.Client.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("Torch Client Tests")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyCompany("")] 7 | [assembly: AssemblyProduct("Torch")] 8 | [assembly: AssemblyCopyright("Copyright © Torch API 2017")] 9 | [assembly: AssemblyTrademark("")] 10 | [assembly: AssemblyCulture("")] 11 | [assembly: ComVisible(false)] 12 | 13 | #if DEBUG 14 | [assembly: AssemblyConfiguration("Debug")] 15 | #else 16 | [assembly: AssemblyConfiguration("Release")] 17 | #endif -------------------------------------------------------------------------------- /Torch.Client.Tests/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Torch.Client.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Torch.Mod/Messages/JoinServerMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ProtoBuf; 5 | using Sandbox.ModAPI; 6 | using VRage.Utils; 7 | 8 | namespace Torch.Mod.Messages 9 | { 10 | [ProtoContract] 11 | public class JoinServerMessage : MessageBase 12 | { 13 | [ProtoMember(201)] 14 | public int Delay; 15 | [ProtoMember(202)] 16 | public string Address; 17 | 18 | private JoinServerMessage() 19 | { 20 | 21 | } 22 | 23 | public JoinServerMessage(string address) 24 | { 25 | Address = address; 26 | } 27 | 28 | public JoinServerMessage(string address, int delay) 29 | { 30 | Address = address; 31 | Delay = delay; 32 | } 33 | 34 | public override void ProcessClient() 35 | { 36 | 37 | MyLog.Default.WriteLineAndConsole($"Torch: Joining server {Address} with delay {Delay}"); 38 | 39 | if (Delay <= 0) 40 | { 41 | MyAPIGateway.Multiplayer.JoinServer(Address); 42 | return; 43 | } 44 | 45 | MyAPIGateway.Parallel.StartBackground(() => 46 | { 47 | MyAPIGateway.Parallel.Sleep(Delay); 48 | MyAPIGateway.Multiplayer.JoinServer(Address); 49 | }); 50 | } 51 | 52 | public override void ProcessServer() 53 | { 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Torch.Mod/Messages/MessageBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using ProtoBuf; 7 | 8 | namespace Torch.Mod.Messages 9 | { 10 | #region Includes 11 | [ProtoInclude(1, typeof(DialogMessage))] 12 | [ProtoInclude(2, typeof(NotificationMessage))] 13 | [ProtoInclude(3, typeof(VoxelResetMessage))] 14 | [ProtoInclude(4, typeof(JoinServerMessage))] 15 | [ProtoInclude(5, typeof(DrawDebug))] 16 | #endregion 17 | 18 | [ProtoContract] 19 | public abstract class MessageBase 20 | { 21 | [ProtoMember(101)] 22 | public ulong SenderId; 23 | 24 | public abstract void ProcessClient(); 25 | public abstract void ProcessServer(); 26 | 27 | //members below not serialized, they're just metadata about the intended target(s) of this message 28 | internal MessageTarget TargetType; 29 | internal ulong Target; 30 | internal ulong[] Ignore; 31 | internal byte[] CompressedData; 32 | 33 | 34 | } 35 | 36 | public enum MessageTarget 37 | { 38 | /// 39 | /// Send to Target 40 | /// 41 | Single, 42 | /// 43 | /// Send to Server 44 | /// 45 | Server, 46 | /// 47 | /// Send to all Clients (only valid from server) 48 | /// 49 | AllClients, 50 | /// 51 | /// Send to all except those steam ID listed in Ignore 52 | /// 53 | AllExcept, 54 | } 55 | } -------------------------------------------------------------------------------- /Torch.Mod/Messages/NotificationMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ProtoBuf; 5 | using Sandbox.ModAPI; 6 | 7 | namespace Torch.Mod.Messages 8 | { 9 | [ProtoContract] 10 | public class NotificationMessage : MessageBase 11 | { 12 | [ProtoMember(201)] 13 | public string Message; 14 | [ProtoMember(202)] 15 | public string Font; 16 | [ProtoMember(203)] 17 | public int DisappearTimeMs; 18 | 19 | public NotificationMessage() 20 | { } 21 | 22 | public NotificationMessage(string message, int disappearTimeMs, string font) 23 | { 24 | Message = message; 25 | DisappearTimeMs = disappearTimeMs; 26 | Font = font; 27 | } 28 | 29 | public override void ProcessClient() 30 | { 31 | MyAPIGateway.Utilities.ShowNotification(Message, DisappearTimeMs, Font); 32 | } 33 | 34 | public override void ProcessServer() 35 | { 36 | throw new Exception(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Torch.Mod/Messages/VoxelResetMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ProtoBuf; 5 | using Sandbox.ModAPI; 6 | using VRage.ModAPI; 7 | using VRage.Voxels; 8 | 9 | namespace Torch.Mod.Messages 10 | { 11 | [ProtoContract] 12 | public class VoxelResetMessage : MessageBase 13 | { 14 | [ProtoMember(201)] 15 | public long[] EntityId; 16 | 17 | public VoxelResetMessage() 18 | { } 19 | 20 | public VoxelResetMessage(long[] entityId) 21 | { 22 | EntityId = entityId; 23 | } 24 | 25 | public override void ProcessClient() 26 | { 27 | //MyAPIGateway.Parallel.ForEach(EntityId, id => 28 | foreach (var id in EntityId) 29 | { 30 | IMyEntity e; 31 | if (!MyAPIGateway.Entities.TryGetEntityById(id, out e)) 32 | continue; 33 | 34 | var v = e as IMyVoxelBase; 35 | v?.Storage.Reset(MyStorageDataTypeFlags.All); 36 | } 37 | } 38 | 39 | public override void ProcessServer() 40 | { 41 | throw new Exception(); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Torch.Mod/Torch.Mod.projitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | 3ce4d2e9-b461-4f19-8233-f87e0dfddd74 7 | 8 | 9 | Torch.Mod 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Torch.Mod/Torch.Mod.shproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 3ce4d2e9-b461-4f19-8233-f87e0dfddd74 5 | 14.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Torch.Mod/TorchModCore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Sandbox.ModAPI; 7 | using Torch.Mod.Messages; 8 | using VRage.Game.Components; 9 | using VRage.Utils; 10 | 11 | namespace Torch.Mod 12 | { 13 | [MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)] 14 | public class TorchModCore : MySessionComponentBase 15 | { 16 | 17 | public const ulong MOD_ID = 3270275515; //real 18 | //public const ulong MOD_ID = 2916923149; //old 19 | private static bool _init; 20 | public static bool Debug; 21 | public static MyStringId id; 22 | 23 | public override void UpdateAfterSimulation() 24 | { 25 | if (_init) 26 | return; 27 | 28 | _init = true; 29 | ModCommunication.Register(); 30 | MyAPIGateway.Utilities.MessageEntered += Utilities_MessageEntered; 31 | id = MyStringId.GetOrCompute("Square"); 32 | 33 | } 34 | 35 | public override void Draw() 36 | { 37 | DrawDebug.refreshAllDraws(); 38 | } 39 | 40 | private void Utilities_MessageEntered(string messageText, ref bool sendToOthers) 41 | { 42 | if (messageText == "@!debug") 43 | { 44 | Debug = !Debug; 45 | MyAPIGateway.Utilities.ShowMessage("Torch", $"Debug: {Debug}"); 46 | sendToOthers = false; 47 | } 48 | } 49 | 50 | protected override void UnloadData() 51 | { 52 | try 53 | { 54 | MyAPIGateway.Utilities.MessageEntered -= Utilities_MessageEntered; 55 | ModCommunication.Unregister(); 56 | } 57 | catch 58 | { 59 | //session unloading, don't care 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Torch.Server.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("Torch Server Tests")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyCompany("")] 7 | [assembly: AssemblyProduct("Torch")] 8 | [assembly: AssemblyCopyright("Copyright © Torch API 2017")] 9 | [assembly: AssemblyTrademark("")] 10 | [assembly: AssemblyCulture("")] 11 | [assembly: ComVisible(false)] 12 | 13 | #if DEBUG 14 | [assembly: AssemblyConfiguration("Debug")] 15 | #else 16 | [assembly: AssemblyConfiguration("Release")] 17 | #endif -------------------------------------------------------------------------------- /Torch.Server.Tests/TorchServerSessionSettingsTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Torch.Server.ViewModels; 8 | using VRage.Game; 9 | using Xunit; 10 | using System.ComponentModel.DataAnnotations; 11 | 12 | namespace Torch.Server.Tests 13 | { 14 | public class TorchServerSessionSettingsTest 15 | { 16 | public static PropertyInfo[] ViewModelProperties = typeof(SessionSettingsViewModel).GetProperties(BindingFlags.Public | BindingFlags.Instance); 17 | public static IEnumerable ModelFields = typeof(MyObjectBuilder_SessionSettings).GetFields(BindingFlags.Public | BindingFlags.Instance).Select(x => new object[] { x }); 18 | 19 | [Theory] 20 | [MemberData(nameof(ModelFields))] 21 | public void MissingPropertyTest(FieldInfo modelField) 22 | { 23 | // Ignore fields that aren't applicable to SE 24 | if (modelField.GetCustomAttribute()?.RelatedTo == Game.MedievalEngineers) 25 | return; 26 | 27 | if (string.IsNullOrEmpty(modelField.GetCustomAttribute()?.Name)) 28 | return; 29 | 30 | var match = ViewModelProperties.FirstOrDefault(p => p.Name.Equals(modelField.Name, StringComparison.InvariantCultureIgnoreCase)); 31 | Assert.NotNull(match); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Torch.Server.Tests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Torch.Server.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Torch.Server/Commands/WhitelistCommands.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Torch.Commands; 7 | 8 | namespace Torch.Server.Commands 9 | { 10 | [Category("whitelist")] 11 | public class WhitelistCommands : CommandModule 12 | { 13 | private TorchConfig Config => (TorchConfig)Context.Torch.Config; 14 | 15 | [Command("on", "Enables the whitelist.")] 16 | public void On() 17 | { 18 | if (!Config.EnableWhitelist) 19 | { 20 | Config.EnableWhitelist = true; 21 | Context.Respond("Whitelist enabled."); 22 | Config.Save(); 23 | } 24 | else 25 | Context.Respond("Whitelist is already enabled."); 26 | } 27 | 28 | [Command("off", "Disables the whitelist")] 29 | public void Off() 30 | { 31 | if (Config.EnableWhitelist) 32 | { 33 | Config.EnableWhitelist = false; 34 | Context.Respond("Whitelist disabled."); 35 | Config.Save(); 36 | } 37 | else 38 | Context.Respond("Whitelist is already disabled."); 39 | } 40 | 41 | [Command("add", "Add a Steam ID to the whitelist.")] 42 | public void Add(ulong steamId) 43 | { 44 | if (!Config.Whitelist.Contains(steamId)) 45 | { 46 | Config.Whitelist.Add(steamId); 47 | Context.Respond($"Added {steamId} to the whitelist."); 48 | Config.Save(); 49 | } 50 | else 51 | Context.Respond($"{steamId} is already whitelisted."); 52 | } 53 | 54 | [Command("remove", "Remove a Steam ID from the whitelist.")] 55 | public void Remove(ulong steamId) 56 | { 57 | if (Config.Whitelist.Remove(steamId)) 58 | { 59 | Context.Respond($"Removed {steamId} from the whitelist."); 60 | Config.Save(); 61 | } 62 | else 63 | Context.Respond($"{steamId} is not whitelisted."); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Torch.Server/FlowDocumentTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Documents; 7 | using System.Windows.Media; 8 | using NLog; 9 | using NLog.Targets; 10 | 11 | namespace Torch.Server 12 | { 13 | /// 14 | /// NLog target that writes to a . 15 | /// 16 | [Target("flowDocument")] 17 | public sealed class FlowDocumentTarget : TargetWithLayout 18 | { 19 | private FlowDocument _document = new FlowDocument { Background = new SolidColorBrush(Colors.Black) }; 20 | private readonly Paragraph _paragraph = new Paragraph(); 21 | private readonly int _maxLines = 500; 22 | 23 | public FlowDocument Document => _document; 24 | 25 | public FlowDocumentTarget() 26 | { 27 | _document.Blocks.Add(_paragraph); 28 | } 29 | 30 | /// 31 | protected override void Write(LogEventInfo logEvent) 32 | { 33 | _document.Dispatcher.BeginInvoke(() => 34 | { 35 | var message = $"{Layout.Render(logEvent)}\n"; 36 | _paragraph.Inlines.Add(new Run(message) {Foreground = LogLevelColors[logEvent.Level]}); 37 | 38 | // A massive paragraph slows the UI down 39 | if (_paragraph.Inlines.Count > _maxLines) 40 | _paragraph.Inlines.Remove(_paragraph.Inlines.FirstInline); 41 | }); 42 | } 43 | 44 | private static readonly Dictionary LogLevelColors = new Dictionary 45 | { 46 | [LogLevel.Trace] = new SolidColorBrush(Colors.DimGray), 47 | [LogLevel.Debug] = new SolidColorBrush(Colors.DarkGray), 48 | [LogLevel.Info] = new SolidColorBrush(Colors.White), 49 | [LogLevel.Warn] = new SolidColorBrush(Colors.Magenta), 50 | [LogLevel.Error] = new SolidColorBrush(Colors.Yellow), 51 | [LogLevel.Fatal] = new SolidColorBrush(Colors.Red), 52 | }; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Torch.Server/Managers/MultiplayerManagerDedicatedPatchShim.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using NLog; 7 | using Sandbox.Engine.Multiplayer; 8 | using Torch.Managers.PatchManager; 9 | using Torch.API.Managers; 10 | 11 | namespace Torch.Server.Managers 12 | { 13 | [PatchShim] 14 | internal static class MultiplayerManagerDedicatedPatchShim 15 | { 16 | public static void Patch(PatchContext ctx) 17 | { 18 | ctx.GetPattern(typeof(MyDedicatedServerBase).GetMethod(nameof(MyDedicatedServerBase.BanClient))).Prefixes.Add(typeof(MultiplayerManagerDedicatedPatchShim).GetMethod(nameof(BanPrefix))); 19 | ctx.GetPattern(typeof(MyDedicatedServerBase).GetMethod(nameof(MyDedicatedServerBase.KickClient))).Prefixes.Add(typeof(MultiplayerManagerDedicatedPatchShim).GetMethod(nameof(KickPrefix))); 20 | } 21 | 22 | public static void BanPrefix(ulong userId, bool banned) 23 | { 24 | TorchBase.Instance.CurrentSession.Managers.GetManager().RaiseClientBanned(userId, banned); 25 | } 26 | 27 | public static void KickPrefix(ulong userId) 28 | { 29 | TorchBase.Instance.CurrentSession.Managers.GetManager().RaiseClientKicked(userId); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Torch.Server/Managers/RemoteAPIManager.cs: -------------------------------------------------------------------------------- 1 | using NLog; 2 | using Sandbox; 3 | using Torch.API; 4 | using Torch.Managers; 5 | using VRage.Dedicated.RemoteAPI; 6 | 7 | namespace Torch.Server.Managers 8 | { 9 | public class RemoteAPIManager : Manager 10 | { 11 | /// 12 | public RemoteAPIManager(ITorchBase torchInstance) : base(torchInstance) 13 | { 14 | 15 | } 16 | 17 | /// 18 | public override void Attach() 19 | { 20 | Torch.GameStateChanged += TorchOnGameStateChanged; 21 | base.Attach(); 22 | } 23 | 24 | /// 25 | public override void Detach() 26 | { 27 | Torch.GameStateChanged -= TorchOnGameStateChanged; 28 | base.Detach(); 29 | } 30 | 31 | private void TorchOnGameStateChanged(MySandboxGame game, TorchGameState newstate) 32 | { 33 | if (newstate == TorchGameState.Loading && MySandboxGame.ConfigDedicated.RemoteApiEnabled && !string.IsNullOrEmpty(MySandboxGame.ConfigDedicated.RemoteSecurityKey)) 34 | { 35 | var myRemoteServer = new MyRemoteServer(MySandboxGame.ConfigDedicated.RemoteApiIP, MySandboxGame.ConfigDedicated.RemoteApiPort, MySandboxGame.ConfigDedicated.RemoteSecurityKey); 36 | LogManager.GetCurrentClassLogger().Info($"Remote API started on port {myRemoteServer.Port}"); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Torch.Server/MultiTextWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Torch.Server 7 | { 8 | public class MultiTextWriter : TextWriter 9 | { 10 | private IEnumerable writers; 11 | public MultiTextWriter(IEnumerable writers) 12 | { 13 | this.writers = writers.ToList(); 14 | } 15 | public MultiTextWriter(params TextWriter[] writers) 16 | { 17 | this.writers = writers; 18 | } 19 | 20 | public override void Write(char value) 21 | { 22 | foreach (var writer in writers) 23 | writer.Write(value); 24 | } 25 | 26 | public override void Write(string value) 27 | { 28 | foreach (var writer in writers) 29 | writer.Write(value); 30 | } 31 | 32 | public override void Flush() 33 | { 34 | foreach (var writer in writers) 35 | writer.Flush(); 36 | } 37 | 38 | public override void Close() 39 | { 40 | foreach (var writer in writers) 41 | writer.Close(); 42 | } 43 | 44 | public override Encoding Encoding 45 | { 46 | get { return Encoding.ASCII; } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Torch.Server/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Torch.Server 9 | { 10 | public class NativeMethods 11 | { 12 | [DllImport("kernel32")] 13 | public static extern bool AllocConsole(); 14 | 15 | [DllImport("kernel32")] 16 | public static extern bool FreeConsole(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Torch.Server/Patches/NlogCustomTarget.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using NLog; 4 | using NLog.Targets; 5 | 6 | namespace Torch.Patches 7 | { 8 | [Target("NlogCustomTarget")] 9 | public class NlogCustomTarget : TargetWithLayout 10 | { 11 | public static event Action LogEventReceived; 12 | 13 | protected override void Write(LogEventInfo logEvent) 14 | { 15 | LogEventReceived?.Invoke(logEvent); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Torch.Server/Patches/PortCheckingPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Net.Sockets; 4 | using System.Reflection; 5 | using NLog; 6 | using Torch.Managers.PatchManager; 7 | 8 | namespace Torch.Patches 9 | { 10 | [PatchShim] 11 | internal static class PortCheckingPatch 12 | { 13 | private static Logger _log = LogManager.GetCurrentClassLogger(); 14 | 15 | public static void Patch(PatchContext ctx) 16 | { 17 | _log.Info("performing port check"); 18 | ctx.GetPattern(typeof(Sandbox.Engine.Multiplayer.MyDedicatedServerBase).GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance)) 19 | .Prefixes.Add(typeof(PortCheckingPatch).GetMethod(nameof(Initialize))); 20 | } 21 | 22 | public static void Initialize(IPEndPoint serverEndpoint) 23 | { 24 | _log.Info("Checking if port is in use"); 25 | 26 | // Create a TcpListener on localhost at the specified port 27 | TcpListener tcpListener = null; 28 | try 29 | { 30 | tcpListener = new TcpListener(IPAddress.Loopback, serverEndpoint.Port); 31 | tcpListener.Start(); 32 | } 33 | catch (SocketException) 34 | { 35 | // If an exception is caught, then the port is in use 36 | throw new Exception("Port is in use, check if another server is running on the same port"); 37 | } 38 | finally 39 | { 40 | tcpListener?.Stop(); 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Torch.Server/Patches/PromotePatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using NLog; 8 | using Sandbox.Game.World; 9 | using Torch.Managers.PatchManager; 10 | using VRage.Game.ModAPI; 11 | using Torch.API.Managers; 12 | using Torch.Server.Managers; 13 | 14 | namespace Torch.Patches 15 | { 16 | [PatchShim] 17 | internal static class PromotePatch 18 | { 19 | private static Logger _log = LogManager.GetCurrentClassLogger(); 20 | private static IMultiplayerManagerServer _backing; 21 | 22 | private static IMultiplayerManagerServer ServerManager => _backing ?? (_backing = TorchBase.Instance?.CurrentSession?.Managers.GetManager()); 23 | 24 | public static void Patch(PatchContext ctx) 25 | { 26 | _log.Info("patching promote"); 27 | ctx.GetPattern(typeof(MySession).GetMethod("OnPromoteLevelSet", BindingFlags.NonPublic | BindingFlags.Static)).Prefixes.Add(typeof(PromotePatch).GetMethod(nameof(PromotePrefix))); 28 | } 29 | 30 | public static void PromotePrefix(ulong steamId, MyPromoteLevel level) 31 | { 32 | if (ServerManager is MultiplayerManagerDedicated d) 33 | d.RaisePromoteChanged(steamId, level); 34 | else 35 | throw new NotSupportedException(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Torch.Server/Patches/ServerResponsePatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | using NLog; 6 | using Sandbox.Engine.Multiplayer; 7 | using Sandbox.Game.World; 8 | using Torch.API.Managers; 9 | using Torch.Managers.PatchManager; 10 | using Torch.Managers.PatchManager.MSIL; 11 | using Torch.Server.Managers; 12 | using VRage.Game.ModAPI; 13 | 14 | namespace Torch.Patches 15 | { 16 | [PatchShim] 17 | public static class ServerResponsePatch 18 | { 19 | private static Logger _log = LogManager.GetCurrentClassLogger(); 20 | 21 | public static void Patch(PatchContext ctx) 22 | { 23 | var transpiler = typeof(ServerResponsePatch).GetMethod(nameof(Transpile), BindingFlags.Public | BindingFlags.Static); 24 | ctx.GetPattern(typeof(MyDedicatedServerBase).GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance)) 25 | .Transpilers.Add(transpiler); 26 | _log.Info("Patching Steam response polling"); 27 | } 28 | 29 | public static IEnumerable Transpile(IEnumerable instructions) 30 | { 31 | // Reduce response timeout from 100 seconds to 5 seconds. 32 | foreach (var instruction in instructions) 33 | { 34 | if (instruction.OpCode == OpCodes.Ldc_I4 && instruction.Operand is MsilOperandInline.MsilOperandInt32 inlineI32 && inlineI32.Value == 1000) 35 | { 36 | _log.Info("Patching Steam response timeout to 5 seconds"); 37 | inlineI32.Value = 50; 38 | } 39 | 40 | yield return instruction; 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Torch.Server/Patches/SteamLoginPatch.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using NLog; 3 | using Steamworks; 4 | using Torch.Managers.PatchManager; 5 | using Torch.Utils; 6 | 7 | namespace Torch.Patches 8 | { 9 | [PatchShim] 10 | public static class SteamLoginPatch 11 | { 12 | private static readonly ILogger Log = LogManager.GetCurrentClassLogger(); 13 | 14 | #pragma warning disable CS0649 15 | [ReflectedMethodInfo(null, "LogOnAnonymous", TypeName = "VRage.Steam.MySteamGameServer, VRage.Steam")] 16 | private static readonly MethodInfo LoginMethod; 17 | [ReflectedMethodInfo(typeof(SteamLoginPatch), nameof(Prefix))] 18 | private static readonly MethodInfo PrefixMethod; 19 | 20 | [ReflectedMethodInfo(null, "WaitStart", TypeName = "VRage.Steam.MySteamGameServer, VRage.Steam")] 21 | private static readonly MethodInfo WaitStartMethod; 22 | [ReflectedMethodInfo(typeof(SteamLoginPatch), nameof(WaitStartLonger))] 23 | private static readonly MethodInfo WaitStartLongerMethod; 24 | #pragma warning restore CS0649 25 | 26 | public static void Patch(PatchContext context) 27 | { 28 | context.GetPattern(LoginMethod).Prefixes.Add(PrefixMethod); 29 | context.GetPattern(WaitStartMethod).Prefixes.Add(WaitStartLongerMethod); 30 | Log.Info("Applied custom WaitStart timeout"); 31 | } 32 | 33 | private static bool Prefix() 34 | { 35 | #pragma warning disable CS0618 36 | var token = TorchBase.Instance.Config.LoginToken; 37 | #pragma warning restore CS0618 38 | 39 | if (string.IsNullOrEmpty(token)) 40 | return true; 41 | 42 | Log.Info("Logging in to Steam with GSLT"); 43 | SteamGameServer.LogOn(token); 44 | return false; 45 | } 46 | 47 | private static void WaitStartLonger(ref int timeOut) 48 | { 49 | timeOut = 20000; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Torch.Server/Patches/WorldLoadExceptionPatch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Reflection.Emit; 7 | using NLog; 8 | using Sandbox; 9 | using Torch.Managers.PatchManager; 10 | using Torch.Managers.PatchManager.MSIL; 11 | 12 | namespace Torch.Patches 13 | { 14 | /// 15 | /// Patches MySandboxGame.InitQuickLaunch to rethrow exceptions caught during session load. 16 | /// 17 | [PatchShim] 18 | public static class WorldLoadExceptionPatch 19 | { 20 | private static readonly ILogger _log = LogManager.GetCurrentClassLogger(); 21 | 22 | public static void Patch(PatchContext ctx) 23 | { 24 | ctx.GetPattern(typeof(MySandboxGame).GetMethod("InitQuickLaunch", BindingFlags.Instance | BindingFlags.NonPublic)) 25 | .Transpilers.Add(typeof(WorldLoadExceptionPatch).GetMethod(nameof(Transpile), BindingFlags.Static | BindingFlags.NonPublic)); 26 | } 27 | 28 | private static IEnumerable Transpile(IEnumerable method) 29 | { 30 | var msil = method.ToList(); 31 | for (var i = 0; i < msil.Count; i++) 32 | { 33 | var instruction = msil[i]; 34 | if (instruction.IsLocalStore() && 35 | instruction.Operand is MsilOperandInline.MsilOperandLocal && 36 | ((MsilOperandInline.MsilOperandLocal)instruction.Operand).Value.Index == 19) 37 | { 38 | msil.Insert(i + 1, new MsilInstruction(OpCodes.Rethrow)); 39 | } 40 | } 41 | return msil; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Torch.Server/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("Torch Server")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyCompany("")] 7 | [assembly: AssemblyProduct("Torch")] 8 | [assembly: AssemblyCopyright("Copyright © Torch API 2017")] 9 | [assembly: AssemblyTrademark("")] 10 | [assembly: AssemblyCulture("")] 11 | [assembly: ComVisible(false)] 12 | 13 | #if DEBUG 14 | [assembly: AssemblyConfiguration("Debug")] 15 | #else 16 | [assembly: AssemblyConfiguration("Release")] 17 | #endif -------------------------------------------------------------------------------- /Torch.Server/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace Torch.Server.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Torch.Server/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Torch.Server/Themes/Dark Theme Animated.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | -------------------------------------------------------------------------------- /Torch.Server/Themes/Light Theme Animated.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | -------------------------------------------------------------------------------- /Torch.Server/TorchService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.ServiceProcess; 9 | using System.Threading; 10 | using NLog; 11 | using Torch.API; 12 | 13 | namespace Torch.Server 14 | { 15 | class TorchService : ServiceBase 16 | { 17 | private static readonly Logger Log = LogManager.GetCurrentClassLogger(); 18 | public const string Name = "Torch (SEDS)"; 19 | private Initializer _initializer; 20 | private string[] _args; 21 | 22 | public TorchService(string[] args) 23 | { 24 | _args = args; 25 | var workingDir = new FileInfo(typeof(TorchService).Assembly.Location).Directory.ToString(); 26 | Directory.SetCurrentDirectory(workingDir); 27 | _initializer = new Initializer(workingDir); 28 | 29 | ServiceName = Name; 30 | CanHandleSessionChangeEvent = false; 31 | CanPauseAndContinue = false; 32 | CanStop = true; 33 | } 34 | 35 | /// 36 | protected override void OnStart(string[] _) 37 | { 38 | base.OnStart(_args); 39 | 40 | _initializer.Initialize(_args); 41 | _initializer.Run(); 42 | } 43 | 44 | /// 45 | protected override void OnStop() 46 | { 47 | var mre = new ManualResetEvent(false); 48 | Task.Run(() => _initializer.Server.Stop()); 49 | if (!mre.WaitOne(TimeSpan.FromMinutes(1))) 50 | Process.GetCurrentProcess().Kill(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Torch.Server/TorchServiceInstaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Configuration.Install; 6 | using System.Linq; 7 | using System.ServiceProcess; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Torch.Server 12 | { 13 | [RunInstaller(true)] 14 | public class TorchServiceInstaller : Installer 15 | { 16 | private ServiceInstaller _serviceInstaller; 17 | 18 | public TorchServiceInstaller() 19 | { 20 | var serviceProcessInstaller = new ServiceProcessInstaller(); 21 | _serviceInstaller = new ServiceInstaller(); 22 | 23 | serviceProcessInstaller.Account = ServiceAccount.LocalSystem; 24 | serviceProcessInstaller.Username = null; 25 | serviceProcessInstaller.Password = null; 26 | 27 | _serviceInstaller.DisplayName = "Torch (SEDS)"; 28 | _serviceInstaller.Description = "Service for Torch (SE Dedicated Server)"; 29 | _serviceInstaller.StartType = ServiceStartMode.Manual; 30 | 31 | _serviceInstaller.ServiceName = TorchService.Name; 32 | 33 | Installers.Add(serviceProcessInstaller); 34 | Installers.Add(_serviceInstaller); 35 | } 36 | 37 | /// 38 | public override void Install(IDictionary stateSaver) 39 | { 40 | GetServiceName(); 41 | base.Install(stateSaver); 42 | } 43 | 44 | /// 45 | public override void Uninstall(IDictionary savedState) 46 | { 47 | GetServiceName(); 48 | base.Uninstall(savedState); 49 | } 50 | 51 | private void GetServiceName() 52 | { 53 | var name = Context.Parameters["name"]; 54 | if (string.IsNullOrEmpty(name)) 55 | return; 56 | 57 | _serviceInstaller.DisplayName = name; 58 | _serviceInstaller.ServiceName = name; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/BlockLimitViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Input; 7 | using VRage.Game; 8 | 9 | namespace Torch.Server.ViewModels 10 | { 11 | public class BlockLimitViewModel : ViewModel 12 | { 13 | private SessionSettingsViewModel _sessionSettings; 14 | private string _blockType; 15 | private short _limit; 16 | 17 | public string BlockType { get => _blockType; set { _blockType = value; OnPropertyChanged(); } } 18 | public short Limit { get => _limit; set { _limit = value; OnPropertyChanged(); } } 19 | 20 | //public CommandBinding Delete { get; } = new CommandBinding(new DeleteCommand()); 21 | 22 | public BlockLimitViewModel(SessionSettingsViewModel sessionSettings, string blockType, short limit) 23 | { 24 | _sessionSettings = sessionSettings; 25 | _blockType = blockType; 26 | _limit = limit; 27 | } 28 | 29 | /* TODO: figure out how WPF commands work 30 | public class DeleteCommand : ICommand 31 | { 32 | /// 33 | public bool CanExecute(object parameter) 34 | { 35 | return ((BlockLimitViewModel)parameter)._sessionSettings.BlockLimits.Contains(parameter); 36 | } 37 | 38 | /// 39 | public void Execute(object parameter) 40 | { 41 | ((BlockLimitViewModel)parameter)._sessionSettings.BlockLimits.Remove((BlockLimitViewModel)parameter); 42 | } 43 | 44 | /// 45 | public event EventHandler CanExecuteChanged; 46 | }*/ 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/Entities/Blocks/PropertyViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Sandbox.ModAPI; 7 | using Sandbox.ModAPI.Interfaces; 8 | 9 | namespace Torch.Server.ViewModels.Blocks 10 | { 11 | public class PropertyViewModel : PropertyViewModel 12 | { 13 | private readonly ITerminalProperty _prop; 14 | public string Name { get; } 15 | public Type PropertyType => typeof(T); 16 | 17 | public T Value 18 | { 19 | get => _prop.GetValue(Block.Block); 20 | set 21 | { 22 | TorchBase.Instance.Invoke(() => 23 | { 24 | _prop.SetValue(Block.Block, value); 25 | OnPropertyChanged(); 26 | Block.RefreshModel(); 27 | }); 28 | } 29 | } 30 | 31 | public PropertyViewModel(ITerminalProperty property, BlockViewModel blockViewModel) : base(blockViewModel) 32 | { 33 | Name = property.Id; 34 | _prop = property; 35 | } 36 | } 37 | 38 | public class PropertyViewModel : ViewModel 39 | { 40 | protected readonly BlockViewModel Block; 41 | 42 | public PropertyViewModel(BlockViewModel blockViewModel) 43 | { 44 | Block = blockViewModel; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/Entities/CharacterViewModel.cs: -------------------------------------------------------------------------------- 1 | using Sandbox.Game.Entities.Character; 2 | using Sandbox.Game.World; 3 | 4 | namespace Torch.Server.ViewModels.Entities 5 | { 6 | public class CharacterViewModel : EntityViewModel 7 | { 8 | private MyCharacter _character; 9 | public CharacterViewModel(MyCharacter character, EntityTreeViewModel tree) : base(character, tree) 10 | { 11 | _character = character; 12 | character.ControllerInfo.ControlAcquired += ControllerInfo_ControlAcquired; 13 | character.ControllerInfo.ControlReleased += ControllerInfo_ControlAcquired; 14 | } 15 | 16 | private void ControllerInfo_ControlAcquired(Sandbox.Game.World.MyEntityController obj) 17 | { 18 | OnPropertyChanged(nameof(Name)); 19 | OnPropertyChanged(nameof(CanDelete)); 20 | } 21 | 22 | public CharacterViewModel() 23 | { 24 | } 25 | 26 | public override bool CanDelete => _character.ControllerInfo?.Controller?.Player == null; 27 | 28 | public string SteamID 29 | { 30 | get 31 | { 32 | if (Entity is MyCharacter c) 33 | return $"{c.ControlInfo.SteamId}"; 34 | 35 | return "nil"; 36 | } 37 | } 38 | 39 | public string GameID 40 | { 41 | get 42 | { 43 | if (Entity is MyCharacter c) 44 | return $"{MySession.Static.Players.TryGetIdentityId(c.ControlInfo.SteamId)}"; 45 | 46 | return "nil"; 47 | } 48 | } 49 | 50 | public string LoginTime 51 | { 52 | get 53 | { 54 | if (!(Entity is MyCharacter c)) return "Unknown?"; 55 | if (c.ControlInfo.SteamId == 0) return "Unknown?"; 56 | 57 | var player = MySession.Static.Players.TryGetPlayerBySteamId(c.ControlInfo.SteamId); 58 | return player != null ? player.Identity.LastLoginTime.ToShortTimeString() : "Unknown?"; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/Entities/EntityControlViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | 8 | namespace Torch.Server.ViewModels.Entities 9 | { 10 | public class EntityControlViewModel : ViewModel 11 | { 12 | internal const string SignalPropertyInvalidateControl = 13 | "InvalidateControl-4124a476-704f-4762-8b5e-336a18e2f7e5"; 14 | 15 | internal void InvalidateControl() 16 | { 17 | // ReSharper disable once ExplicitCallerInfoArgument 18 | OnPropertyChanged(SignalPropertyInvalidateControl); 19 | } 20 | 21 | private bool _hide; 22 | 23 | /// 24 | /// Should this element be forced into the 25 | /// 26 | public bool Hide 27 | { 28 | get => _hide; 29 | protected set 30 | { 31 | if (_hide == value) 32 | return; 33 | _hide = value; 34 | OnPropertyChanged(); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/Entities/FloatingObjectViewModel.cs: -------------------------------------------------------------------------------- 1 | using Sandbox.Game.Entities; 2 | using Torch.Server.ViewModels.Entities; 3 | 4 | namespace Torch.Server.ViewModels 5 | { 6 | public class FloatingObjectViewModel : EntityViewModel 7 | { 8 | private MyFloatingObject Floating => (MyFloatingObject)Entity; 9 | 10 | public override string Name => $"{base.Name} ({Floating.Amount})"; 11 | 12 | public FloatingObjectViewModel(MyFloatingObject floating, EntityTreeViewModel tree) : base(floating, tree) { } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/Entities/VoxelMapViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Sandbox.Game.Entities; 4 | using VRage.Game.Entity; 5 | using VRage.Game.ModAPI; 6 | using System.Threading.Tasks; 7 | using Torch.Collections; 8 | 9 | namespace Torch.Server.ViewModels.Entities 10 | { 11 | public class VoxelMapViewModel : EntityViewModel 12 | { 13 | private MyVoxelBase Voxel => (MyVoxelBase)Entity; 14 | 15 | public override string Name => string.IsNullOrEmpty(Voxel.StorageName) ? "UnnamedProcedural" : Voxel.StorageName; 16 | 17 | public override bool CanStop => false; 18 | 19 | public MtObservableList AttachedGrids { get; } = new MtObservableList(); 20 | 21 | public async Task UpdateAttachedGrids() 22 | { 23 | //TODO: fix 24 | return; 25 | 26 | AttachedGrids.Clear(); 27 | var box = Entity.WorldAABB; 28 | var entities = new List(); 29 | await TorchBase.Instance.InvokeAsync(() => MyEntities.GetTopMostEntitiesInBox(ref box, entities)).ConfigureAwait(false); 30 | foreach (var entity in entities.Where(e => e is IMyCubeGrid)) 31 | { 32 | if (Tree.Grids.TryGetValue(entity.EntityId, out var gridModel)) 33 | { 34 | gridModel = new GridViewModel((MyCubeGrid)entity, Tree); 35 | Tree.Grids.Add(entity.EntityId, gridModel); 36 | } 37 | 38 | AttachedGrids.Add(gridModel); 39 | } 40 | } 41 | 42 | public VoxelMapViewModel(MyVoxelBase e, EntityTreeViewModel tree) : base(e, tree) 43 | { 44 | 45 | } 46 | 47 | public VoxelMapViewModel() 48 | { 49 | 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/ILazyLoad.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Torch.Server.ViewModels 8 | { 9 | public interface ILazyLoad 10 | { 11 | void Load(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/PluginManagerViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Torch.API; 7 | using Torch.API.Managers; 8 | using Torch.API.Plugins; 9 | using Torch.Collections; 10 | 11 | namespace Torch.Server.ViewModels 12 | { 13 | public class PluginManagerViewModel : ViewModel 14 | { 15 | public MtObservableList Plugins { get; } = new MtObservableList(); 16 | 17 | private PluginViewModel _selectedPlugin; 18 | public PluginViewModel SelectedPlugin 19 | { 20 | get => _selectedPlugin; 21 | set { _selectedPlugin = value; OnPropertyChanged(nameof(SelectedPlugin)); } 22 | } 23 | 24 | public PluginManagerViewModel() { } 25 | 26 | public PluginManagerViewModel(IPluginManager pluginManager) 27 | { 28 | foreach (var plugin in pluginManager.OrderBy(x=>x.Name)) 29 | Plugins.Add(new PluginViewModel(plugin)); 30 | pluginManager.PluginsLoaded += PluginManager_PluginsLoaded; 31 | } 32 | 33 | private void PluginManager_PluginsLoaded(IReadOnlyCollection obj) 34 | { 35 | Plugins.Clear(); 36 | foreach (var plugin in obj) 37 | { 38 | Plugins.Add(new PluginViewModel(plugin)); 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/SteamUserViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Steamworks; 7 | 8 | namespace Torch.Server.ViewModels 9 | { 10 | public class SteamUserViewModel : ViewModel 11 | { 12 | public string Name { get; } 13 | public ulong SteamId { get; } 14 | 15 | public SteamUserViewModel(ulong id) 16 | { 17 | SteamId = id; 18 | Name = SteamFriends.GetFriendPersonaName(new CSteamID(id)); 19 | } 20 | 21 | public SteamUserViewModel() : this(0) { } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Torch.Server/ViewModels/WorldConfigurationViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using VRage.Game; 3 | 4 | namespace Torch.Server.ViewModels 5 | { 6 | public class WorldConfigurationViewModel : ViewModel 7 | { 8 | private readonly MyObjectBuilder_WorldConfiguration _worldConfiguration; 9 | private SessionSettingsViewModel _sessionSettings; 10 | 11 | public WorldConfigurationViewModel(MyObjectBuilder_WorldConfiguration worldConfiguration) 12 | { 13 | _worldConfiguration = worldConfiguration; 14 | _sessionSettings = new SessionSettingsViewModel(worldConfiguration.Settings); 15 | } 16 | 17 | public static implicit operator MyObjectBuilder_WorldConfiguration(WorldConfigurationViewModel model) 18 | { 19 | return model._worldConfiguration; 20 | } 21 | 22 | public List Mods { get => _worldConfiguration.Mods; set => SetValue(ref _worldConfiguration.Mods, value); } 23 | 24 | public SessionSettingsViewModel Settings 25 | { 26 | get => _sessionSettings; 27 | set 28 | { 29 | SetValue(ref _sessionSettings, value); 30 | _worldConfiguration.Settings = _sessionSettings; 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Torch.Server/Views/AddWorkshopItemsDialog.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 |