├── package.json ├── MMS_Files ├── java_latest.ini ├── bedrock_latest.ini └── java_beta_latest.ini ├── MinecraftService ├── Client │ ├── SpellingExclusions.dic │ ├── Configs │ │ └── Config.conf │ ├── mc_icon.ico │ ├── Properties │ │ ├── launchSettings.json │ │ ├── Settings.settings │ │ ├── PublishProfiles │ │ │ └── FolderProfile.pubxml │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ └── Resources.Designer.cs │ ├── App.config │ ├── Networking │ │ ├── INetworkMessage.cs │ │ ├── NetworkStrategies │ │ │ ├── UnlockUI.cs │ │ │ ├── Backup.cs │ │ │ ├── BackupCallback.cs │ │ │ ├── ClientReject.cs │ │ │ ├── LevelEditFile.cs │ │ │ ├── EnumBackups.cs │ │ │ ├── PlayersRequest.cs │ │ │ ├── ExportFile.cs │ │ │ ├── PackList.cs │ │ │ ├── VersionListRequest.cs │ │ │ ├── ConsoleLogUpdate.cs │ │ │ ├── ClientConnect.cs │ │ │ └── ServerStatusRequest.cs │ │ └── NetworkMessageLookup.cs │ ├── Forms │ │ ├── RemoveServerControl.cs │ │ ├── ExporterControl.cs │ │ ├── NewPlayerRegistrationForm.cs │ │ ├── ProgressDialog.cs │ │ ├── ManagePacksForms.resx │ │ ├── ProgressDialog.resx │ │ ├── RemoveServerControl.resx │ │ ├── NewPlayerRegistrationForm.resx │ │ ├── ClientConfigForm.cs │ │ ├── PropEditorForm.cs │ │ └── ClientConfigForm.resx │ └── Management │ │ └── FormManager.cs ├── Service │ ├── mc_icon.ico │ ├── Properties │ │ ├── launchSettings.json │ │ ├── PublishProfiles │ │ │ └── FolderProfile.pubxml │ │ └── AssemblyInfo.cs │ ├── app.config │ ├── Core │ │ └── Interfaces │ │ │ └── IService.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── Networking │ │ ├── Interfaces │ │ │ ├── IMessageParser.cs │ │ │ ├── IFlaggedMessageParser.cs │ │ │ └── ITCPObject.cs │ │ ├── NetworkStrategies │ │ │ ├── CheckUpdates.cs │ │ │ ├── ServerRestart.cs │ │ │ ├── ServerBackup.cs │ │ │ ├── ServerBackupAll.cs │ │ │ ├── ServerCommand.cs │ │ │ ├── EnumBackups.cs │ │ │ ├── PlayerRequest.cs │ │ │ ├── BackupRollback.cs │ │ │ ├── Connect.cs │ │ │ ├── StartStopServer.cs │ │ │ ├── DeleteBackups.cs │ │ │ ├── StartCmdUpdate.cs │ │ │ ├── LevelEditRequest.cs │ │ │ ├── RemoveServer.cs │ │ │ ├── ServerStatusRequest.cs │ │ │ ├── ImportFileRequest.cs │ │ │ ├── LevelEditFile.cs │ │ │ ├── VersionListRequest.cs │ │ │ ├── RemovePack.cs │ │ │ ├── AddNewServer.cs │ │ │ ├── ServerPropUpdate.cs │ │ │ ├── PackList.cs │ │ │ ├── PlayersUpdate.cs │ │ │ ├── ConsoleLogUpdate.cs │ │ │ └── PackFile.cs │ │ └── NetworkStrategyLookup.cs │ ├── Server │ │ ├── Interfaces │ │ │ └── IConsoleFilter.cs │ │ ├── ServerTypeLookup.cs │ │ ├── ConsoleFilters │ │ │ ├── SaveIncompleteFilter.cs │ │ │ ├── ServerRescErrorFilter.cs │ │ │ ├── StartupFlagFilter.cs │ │ │ ├── JavaBackupDetectFilter.cs │ │ │ ├── BackupStringFilter.cs │ │ │ ├── JavaPlayerConnectedFilter.cs │ │ │ ├── JavaPlayerDisconnectedFilter.cs │ │ │ ├── BedrockPlayerDisconnectedFilter.cs │ │ │ ├── BedrockPlayerConnectedFilter.cs │ │ │ ├── JavaPlayerLostConnectionFilter.cs │ │ │ └── JavaVersionFilter.cs │ │ └── TimerService.cs │ └── Program.cs ├── ServiceTests │ ├── SharedTests │ │ ├── MinecraftPackTests.cs │ │ ├── ExportImportFileModelTests.cs │ │ ├── MinecraftUpdatePackageProcessorTests.cs │ │ ├── JsonModelTests.cs │ │ └── UtilitiesTests │ │ │ └── FileUtilitiesTests.cs │ ├── Properties │ │ └── launchSettings.json │ ├── MMS_Tests.csproj │ └── ServiceTests │ │ └── ServiceTests.cs ├── ClientUnitTests │ ├── packages.config │ ├── Properties │ │ └── AssemblyInfo.cs │ └── FormTests.cs ├── MinecraftService.Shared │ ├── Classes │ │ ├── Service │ │ │ ├── Core │ │ │ │ ├── StartCmdEntry.cs │ │ │ │ ├── ProgressModel.cs │ │ │ │ ├── SimpleVersionModel.cs │ │ │ │ └── Property.cs │ │ │ └── Configuration │ │ │ │ ├── ServiceInfo.cs │ │ │ │ └── ClientSideServiceConfiguration.cs │ │ ├── Server │ │ │ ├── Updaters │ │ │ │ └── UpdaterContainer.cs │ │ │ ├── ServerInfo.cs │ │ │ ├── ProcessInfo.cs │ │ │ └── Configurations │ │ │ │ └── CommonDefaults.cs │ │ └── Networking │ │ │ ├── NetworkEnums.cs │ │ │ └── Message.cs │ ├── Interfaces │ │ ├── IBackupManager.cs │ │ ├── IUpdater.cs │ │ ├── IBaseConfiguration.cs │ │ ├── IServerController.cs │ │ └── IServerConfiguration.cs │ ├── JsonModels │ │ ├── Service │ │ │ ├── IFileProcessor.cs │ │ │ ├── JavaVersionHistoryModel.cs │ │ │ ├── BedrockVersionHistoryModel.cs │ │ │ └── FileProcessors │ │ │ │ └── BedrockServerArchive.cs │ │ └── Minecraft │ │ │ ├── MinecraftVersionHistoryJson.cs │ │ │ ├── PermissionsEntryJsonModel.cs │ │ │ ├── WorldPackEntryJsonModel.cs │ │ │ ├── WhitelistEntryJsonModel.cs │ │ │ └── PackManifestJsonModel.cs │ ├── SerializeModels │ │ ├── LogEntry.cs │ │ ├── ServerCombinedPropModel.cs │ │ ├── ConsoleLogUpdateCallback.cs │ │ ├── ConsoleLogUpdateRequest.cs │ │ ├── StatusModels.cs │ │ └── BackupInfoModel.cs │ ├── FileModels │ │ ├── MinecraftFileModels │ │ │ ├── PackManifestFileModel.cs │ │ │ ├── WhitelistFileModel.cs │ │ │ ├── PermissionsFileModel.cs │ │ │ └── WorldPackFileModel.cs │ │ └── BaseJsonFile.cs │ ├── PackParser │ │ └── MinecraftPackContainer.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── MinecraftService.Shared.csproj └── packages.config ├── .github └── workflows │ ├── changelog.yml │ ├── BMSBuild.yml │ └── BMSBuildStable.yml ├── BMS_Files └── plugin_repo.json ├── CHANGELOG.md ├── .gitattributes └── BdsVersionCheckTest.ps1 /package.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /MMS_Files/java_latest.ini: -------------------------------------------------------------------------------- 1 | 1.21.11 2 | -------------------------------------------------------------------------------- /MMS_Files/bedrock_latest.ini: -------------------------------------------------------------------------------- 1 | 1.21.131.1 2 | -------------------------------------------------------------------------------- /MinecraftService/Client/SpellingExclusions.dic: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MMS_Files/java_beta_latest.ini: -------------------------------------------------------------------------------- 1 | 26.1-snapshot-1 2 | -------------------------------------------------------------------------------- /MinecraftService/Client/Configs/Config.conf: -------------------------------------------------------------------------------- 1 | [Hosts] 2 | host1=127.0.0.1:19134 3 | -------------------------------------------------------------------------------- /MinecraftService/Client/mc_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crowbarmaster/BedrockManagementService/HEAD/MinecraftService/Client/mc_icon.ico -------------------------------------------------------------------------------- /MinecraftService/Service/mc_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crowbarmaster/BedrockManagementService/HEAD/MinecraftService/Service/mc_icon.ico -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/SharedTests/MinecraftPackTests.cs: -------------------------------------------------------------------------------- 1 | namespace MMS_Tests.SharedTests { 2 | public class MinecraftPackTests { 3 | 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /MinecraftService/Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "MinecraftService.Client": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "WSL": { 4 | "commandName": "WSL2", 5 | "distributionName": "" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "MinecraftService.Service": { 4 | "commandName": "Project", 5 | "nativeDebugging": true 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /MinecraftService/Service/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /MinecraftService/Service/Core/Interfaces/IService.cs: -------------------------------------------------------------------------------- 1 | namespace MinecraftService.Service.Core.Interfaces { 2 | public interface IService : IHostedService { 3 | Task InitializeHost(); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /MinecraftService/Client/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /MinecraftService/Service/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MinecraftService/Service/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /MinecraftService/ClientUnitTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/Interfaces/IMessageParser.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Networking; 2 | 3 | namespace MinecraftService.Service.Networking.Interfaces 4 | { 5 | public interface IMessageParser { 6 | Message ParseMessage(Message message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MinecraftService/Client/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Service/Core/StartCmdEntry.cs: -------------------------------------------------------------------------------- 1 | namespace MinecraftService.Shared.Classes.Service.Core 2 | { 3 | public class StartCmdEntry 4 | { 5 | public string Command = "help 1"; 6 | 7 | public StartCmdEntry(string entry) 8 | { 9 | Command = entry; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Server/Interfaces/IConsoleFilter.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 MinecraftService.Service.Server.Interfaces { 8 | public interface IConsoleFilter { 9 | public void Filter(string input); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Interfaces/IBackupManager.cs: -------------------------------------------------------------------------------- 1 | namespace MinecraftService.Shared.Interfaces { 2 | public interface IBackupManager { 3 | bool BackupRunning(); 4 | void InitializeBackup(); 5 | bool PerformBackup(string unused); 6 | void PerformRollback(string zipFilePath); 7 | bool SetBackupComplete(); 8 | } 9 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/Interfaces/IFlaggedMessageParser.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Networking; 2 | 3 | namespace MinecraftService.Service.Networking.Interfaces 4 | { 5 | public interface IFlaggedMessageParser { 6 | (byte[] data, byte srvIndex, MessageTypes type) ParseMessage(byte[] data, byte serverIndex, MessageFlags flag); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Service/IFileProcessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace MinecraftService.Shared.JsonModels.Service { 9 | public interface IFileProcessor { 10 | void Process(byte[] fileBytes); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/SerializeModels/LogEntry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MinecraftService.Shared.SerializeModels { 4 | public class LogEntry { 5 | public DateTime TimeStamp { get; set; } 6 | public string Text { get; set; } 7 | 8 | 9 | public LogEntry(string entryText) { 10 | Text = entryText; 11 | TimeStamp = DateTime.Now; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/Interfaces/ITCPObject.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Networking; 2 | 3 | namespace MinecraftService.Service.Networking.Interfaces 4 | { 5 | public interface ITCPObject { 6 | void Initialize(); 7 | Task CancelAllTasks(); 8 | void SetStrategies(Dictionary strategies); 9 | void SetServiceStarted(); 10 | void SetServiceStopped(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/SerializeModels/ServerCombinedPropModel.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Service.Core; 2 | using System.Collections.Generic; 3 | 4 | namespace MinecraftService.Shared.SerializeModels 5 | { 6 | public class ServerCombinedPropModel { 7 | public List ServerPropList { get; set; } 8 | public List ServicePropList { get; set; } 9 | public List VersionList { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Service/JavaVersionHistoryModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace MinecraftService.Shared.JsonModels.Service 6 | { 7 | public class JavaVersionHistoryModel 8 | { 9 | public string Version { get; set; } 10 | public bool IsBeta { get; set; } 11 | public string DownloadUrl { get; set; } 12 | public List PropList { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/INetworkMessage.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using MinecraftService.Shared.Classes.Networking; 7 | 8 | namespace MinecraftService.Client.Networking { 9 | internal interface INetworkMessage { 10 | Task ProcessMessage(Message message); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Minecraft/MinecraftVersionHistoryJson.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace MinecraftService.Shared.JsonModels.Minecraft { 4 | public class MinecraftVersionHistoryJson { 5 | [JsonPropertyName("version")] 6 | public string Version { get; set; } 7 | [JsonPropertyName("winurl")] 8 | public string WindowsBinUrl { get; set; } 9 | [JsonPropertyName("linurl")] 10 | public string LinuxBinUrl { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/CheckUpdates.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | 5 | namespace MinecraftService.Service.Networking.NetworkStrategies 6 | { 7 | public class CheckUpdates(MmsService service) : IMessageParser { 8 | 9 | public Message ParseMessage(Message message) { 10 | service.GetServerByIndex(message.ServerIndex).CheckUpdates(); 11 | return Message.EmptyUICallback; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/FileModels/MinecraftFileModels/PackManifestFileModel.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.JsonModels.Minecraft; 2 | 3 | namespace MinecraftService.Shared.FileModels.MinecraftFileModels 4 | { 5 | public class PackManifestFileModel : BaseJsonFile { 6 | public PackManifestJsonModel Contents { get; set; } = new(); 7 | 8 | public PackManifestFileModel(string fullPath) : base(fullPath) { 9 | Contents = LoadJsonFile(); 10 | } 11 | 12 | public PackManifestFileModel() { } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ServerRestart.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | 5 | namespace MinecraftService.Service.Networking.NetworkStrategies 6 | { 7 | public class ServerRestart(MmsService service) : IMessageParser { 8 | 9 | public Message ParseMessage(Message message) { 10 | service.GetServerByIndex(message.ServerIndex).RestartServer().Wait(); 11 | return Message.EmptyUICallback; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/SerializeModels/ConsoleLogUpdateCallback.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 MinecraftService.Shared.SerializeModels { 8 | public class ConsoleLogUpdateCallback { 9 | public byte LogTarget { get; set; } = 0xFE; 10 | public List LogEntries { get; set; } 11 | public int CurrentCount { get; set; } 12 | 13 | public ConsoleLogUpdateCallback() { 14 | LogEntries = []; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/FileModels/MinecraftFileModels/WhitelistFileModel.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.JsonModels.Minecraft; 2 | using System.Collections.Generic; 3 | 4 | namespace MinecraftService.Shared.FileModels.MinecraftFileModels 5 | { 6 | public class WhitelistFileModel : BaseJsonFile { 7 | public List Contents { get; set; } = new(); 8 | 9 | public WhitelistFileModel(string fullPath) : base(fullPath) { 10 | Contents = LoadJsonFile>(); 11 | } 12 | 13 | public WhitelistFileModel() { } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/SerializeModels/ConsoleLogUpdateRequest.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 MinecraftService.Shared.SerializeModels { 8 | public class ConsoleLogUpdateRequest { 9 | public byte LogTarget { get; set; } = 0xFE; 10 | public int CurrentCount { get; set; } 11 | 12 | public ConsoleLogUpdateRequest(byte logTarget, int currentCount) { 13 | LogTarget = logTarget; 14 | CurrentCount = currentCount; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/FileModels/MinecraftFileModels/PermissionsFileModel.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.JsonModels.Minecraft; 2 | using System.Collections.Generic; 3 | 4 | namespace MinecraftService.Shared.FileModels.MinecraftFileModels 5 | { 6 | public class PermissionsFileModel : BaseJsonFile { 7 | public List Contents { get; set; } = new(); 8 | 9 | public PermissionsFileModel(string fullPath) : base(fullPath) { 10 | Contents = LoadJsonFile>(); 11 | } 12 | 13 | public PermissionsFileModel() { } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MinecraftService/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Service/Core/ProgressModel.cs: -------------------------------------------------------------------------------- 1 | namespace MinecraftService.Shared.Classes.Service.Core 2 | { 3 | public class ProgressModel 4 | { 5 | public string Message; 6 | public double Progress; 7 | 8 | public ProgressModel(string message, double progress) 9 | { 10 | Message = message; 11 | Progress = progress; 12 | } 13 | 14 | public ProgressModel UpdateProgress(string message, double progress) 15 | { 16 | Message = message; 17 | Progress = progress; 18 | return this; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MinecraftService/ClientUnitTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("ClientUnitTests")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("")] 8 | [assembly: AssemblyProduct("ClientUnitTests")] 9 | [assembly: AssemblyCopyright("Copyright © 2021")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: Guid("550b6a98-60c3-4765-bfed-2caa0affaebb")] 16 | 17 | // [assembly: AssemblyVersion("1.0.*")] 18 | [assembly: AssemblyVersion("1.0.0.0")] 19 | [assembly: AssemblyFileVersion("1.0.0.0")] 20 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/UnlockUI.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using MinecraftService.Client.Management; 7 | using MinecraftService.Shared.Classes.Networking; 8 | 9 | namespace MinecraftService.Client.Networking.NetworkStrategies { 10 | public class UnlockUI : INetworkMessage { 11 | 12 | public Task ProcessMessage(Message _) => Task.Run(() => { 13 | FormManager.MainWindow.ServerBusy = false; 14 | return true; 15 | }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ServerBackup.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Service.Server.Interfaces; 4 | using MinecraftService.Shared.Classes.Networking; 5 | 6 | namespace MinecraftService.Service.Networking.NetworkStrategies 7 | { 8 | public class ServerBackup(MmsService service) : IMessageParser { 9 | 10 | public Message ParseMessage(Message message) { 11 | IServerController server = service.GetServerByIndex(message.ServerIndex); 12 | server.SetServerModified(true); 13 | server.GetBackupManager().InitializeBackup(); 14 | return Message.EmptyUICallback; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MinecraftService/Service/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | ..\bin\Published\ 10 | FileSystem 11 | net9.0 12 | win-x64 13 | false 14 | True 15 | False 16 | 17 | -------------------------------------------------------------------------------- /MinecraftService/Client/Properties/PublishProfiles/FolderProfile.pubxml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | Release 8 | Any CPU 9 | ..\bin\Published\ 10 | FileSystem 11 | net9.0-windows 12 | win-x64 13 | false 14 | True 15 | False 16 | 17 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ServerBackupAll.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Service.Server.Interfaces; 4 | using MinecraftService.Shared.Classes.Networking; 5 | 6 | namespace MinecraftService.Service.Networking.NetworkStrategies 7 | { 8 | class ServerBackupAll(MmsService service) : IMessageParser { 9 | 10 | public Message ParseMessage(Message message) { 11 | foreach (IServerController server in service.GetAllServers()) { 12 | server.SetServerModified(true); 13 | server.GetBackupManager().InitializeBackup(); 14 | } 15 | return Message.EmptyUICallback; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/FileModels/MinecraftFileModels/WorldPackFileModel.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.JsonModels.Minecraft; 2 | using System.Collections.Generic; 3 | 4 | namespace MinecraftService.Shared.FileModels.MinecraftFileModels 5 | { 6 | public class WorldPackFileModel : BaseJsonFile { 7 | public List Contents { get; set; } = new(); 8 | 9 | public WorldPackFileModel(string fullPath) : base(fullPath) { 10 | Contents = LoadJsonFile>(); 11 | if (Contents == null) { 12 | Contents = new(); 13 | } 14 | } 15 | 16 | public WorldPackFileModel() { } 17 | 18 | public void SaveFile() => SaveToFile(Contents); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Minecraft/PermissionsEntryJsonModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MinecraftService.Shared.JsonModels.Minecraft { 4 | public class PermissionsEntryJsonModel { 5 | public string xuid { get; set; } 6 | public string permission { get; set; } 7 | 8 | public PermissionsEntryJsonModel(string permission, string xuid) { 9 | this.permission = permission; 10 | this.xuid = xuid; 11 | } 12 | 13 | public override bool Equals(object obj) { 14 | return obj is PermissionsEntryJsonModel model && 15 | xuid == model.xuid; 16 | } 17 | 18 | public override int GetHashCode() { 19 | return HashCode.Combine(xuid); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Minecraft/WorldPackEntryJsonModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MinecraftService.Shared.JsonModels.Minecraft { 5 | public class WorldPackEntryJsonModel { 6 | public string pack_id { get; set; } 7 | public List version { get; set; } 8 | 9 | public WorldPackEntryJsonModel(string id, List ver) { 10 | pack_id = id; 11 | version = ver; 12 | } 13 | 14 | public override bool Equals(object obj) { 15 | return obj is WorldPackEntryJsonModel model && 16 | pack_id == model.pack_id; 17 | } 18 | 19 | public override int GetHashCode() { 20 | return HashCode.Combine(pack_id); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/SharedTests/ExportImportFileModelTests.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.SerializeModels; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Xunit; 9 | 10 | namespace MMS_Tests.SharedTests { 11 | public class ExportImportFileModelTests { 12 | 13 | [Fact] 14 | public void Can_Detect_Bedrock_Zip() { 15 | string _testFilePath = @"..\..\..\..\TestFiles\BedrockTest.zip"; 16 | Assert.True(File.Exists(_testFilePath)); 17 | ExportImportFileModel model = new(File.ReadAllBytes(_testFilePath)); 18 | Assert.NotNull(model); 19 | Assert.Equal(FileTypes.BedrockServer, model.Manifest.FileType); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ServerCommand.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using System.Text; 6 | 7 | namespace MinecraftService.Service.Networking.NetworkStrategies 8 | { 9 | public class ServerCommand(MmsService service, MmsLogger logger) : IMessageParser { 10 | 11 | public Message ParseMessage(Message message) { 12 | string stringData = Encoding.UTF8.GetString(message.Data); 13 | service.GetServerByIndex(message.ServerIndex).WriteToStandardIn(stringData); 14 | logger.AppendLine($"Sent command {stringData} to stdInput stream"); 15 | return Message.EmptyUICallback; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/Backup.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using MinecraftService.Shared.Classes.Networking; 7 | using MinecraftService.Shared.Classes.Service.Core; 8 | using MinecraftService.Shared.Interfaces; 9 | 10 | namespace MinecraftService.Client.Networking.NetworkStrategies { 11 | public class Backup(MmsLogger logger) : INetworkMessage { 12 | 13 | public Task ProcessMessage(Message message) => Task.Run(() => { 14 | MessageFlags msgStatus = (MessageFlags)message.Data[4]; 15 | logger.AppendLine(msgStatus.ToString()); 16 | return true; 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Interfaces/IUpdater.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Service.Core; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace MinecraftService.Shared.Interfaces 6 | { 7 | public interface IUpdater { 8 | Task Initialize(); 9 | void SetNewLogger(MmsLogger logger); 10 | bool IsInitialized(); 11 | Task CheckLatestVersion(); 12 | List GetVersionPropList(string version); 13 | List GetDefaultVersionPropList(); 14 | string GetBaseVersion(string version); 15 | bool ValidateBuildExists(string version); 16 | Task FetchBuild(string version); 17 | Task ReplaceBuild(IServerConfiguration serverConfiguration, string versionOverride = ""); 18 | List GetSimpleVersionList(); 19 | } 20 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/PackParser/MinecraftPackContainer.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.JsonModels.Minecraft; 2 | 3 | namespace MinecraftService.Shared.PackParser { 4 | public class MinecraftPackContainer { 5 | public PackManifestJsonModel JsonManifest; 6 | public string PackContentLocation; 7 | public string ManifestType; 8 | public string FolderName; 9 | public byte[] IconBytes; 10 | 11 | public override string ToString() { 12 | return JsonManifest != null ? $"{JsonManifest.header.name} ({JsonManifest.modules[0].type})" : "WorldPack"; 13 | } 14 | 15 | public string GetFixedManifestType() { 16 | return ManifestType == "data" ? 17 | "behavior" : ManifestType == "resources" ? 18 | "resource" : ManifestType; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/EnumBackups.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using Newtonsoft.Json; 5 | using System.Text; 6 | 7 | namespace MinecraftService.Service.Networking.NetworkStrategies 8 | { 9 | public class EnumBackups(UserConfigManager configurator) : IMessageParser { 10 | 11 | public Message ParseMessage(Message message) { 12 | try { 13 | string jsonString = JsonConvert.SerializeObject(configurator.EnumerateBackupsForServer(message.ServerIndex).Result, Formatting.Indented); 14 | byte[] serializeToBytes = Encoding.UTF8.GetBytes(jsonString); 15 | return new(serializeToBytes, 0, MessageTypes.EnumBackups); 16 | } catch { } 17 | return Message.Empty(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Minecraft/WhitelistEntryJsonModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace MinecraftService.Shared.JsonModels.Minecraft { 4 | public class WhitelistEntryJsonModel { 5 | public string xuid { get; set; } 6 | public string name { get; set; } 7 | public bool ignoresPlayerLimit { get; set; } 8 | 9 | public WhitelistEntryJsonModel(bool IgnoreLimits, string XUID, string username) { 10 | ignoresPlayerLimit = IgnoreLimits; 11 | xuid = XUID; 12 | name = username; 13 | } 14 | 15 | public override bool Equals(object obj) { 16 | return obj is WhitelistEntryJsonModel model && 17 | xuid == model.xuid; 18 | } 19 | 20 | public override int GetHashCode() { 21 | return HashCode.Combine(xuid); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/PlayerRequest.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service.Configuration; 5 | using MinecraftService.Shared.Classes.Service.Core; 6 | using Newtonsoft.Json; 7 | using System.Text; 8 | 9 | namespace MinecraftService.Service.Networking.NetworkStrategies 10 | { 11 | public class PlayerRequest(MmsService service) : IMessageParser { 12 | 13 | public Message ParseMessage(Message message) { 14 | message.Data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(service.GetServerByIndex(message.ServerIndex).GetPlayerManager().GetPlayerList(), Formatting.Indented, SharedStringBase.GlobalJsonSerialierSettings)); 15 | return message; 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/BackupCallback.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using MinecraftService.Client.Management; 7 | using MinecraftService.Shared.Classes.Networking; 8 | 9 | namespace MinecraftService.Client.Networking.NetworkStrategies { 10 | public class BackupCallback : INetworkMessage { 11 | 12 | public Task ProcessMessage(Message message) => Task.Run(() => { 13 | bool rollbackPassed = message.Flag == MessageFlags.Passed; 14 | FormManager.MainWindow.BackupRollbackCompleted(rollbackPassed); 15 | FormManager.MainWindow.ServerBusy = false; 16 | return true; 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/BackupRollback.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using System.Text; 5 | 6 | namespace MinecraftService.Service.Networking.NetworkStrategies 7 | { 8 | public class BackupRollback(MmsService service) : IMessageParser { 9 | 10 | public Message ParseMessage(Message message) { 11 | string stringData = Encoding.UTF8.GetString(message.Data); 12 | byte[] sendBytes = new byte[1]; 13 | 14 | if (service.GetServerByIndex(message.ServerIndex).RollbackToBackup(stringData)) { 15 | sendBytes[0] = 1; 16 | } else { 17 | sendBytes[0] = 0; 18 | } 19 | return new(sendBytes, message.ServerIndex, MessageTypes.BackupCallback); 20 | } 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Server/Updaters/UpdaterContainer.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Interfaces; 2 | using System.Collections.Generic; 3 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 4 | 5 | namespace MinecraftService.Shared.Classes.Server.Updaters 6 | { 7 | public class UpdaterContainer 8 | { 9 | private Dictionary _updatersByArch = []; 10 | 11 | public UpdaterContainer() { } 12 | 13 | public IUpdater GetUpdaterByArch(MinecraftServerArch arch) => _updatersByArch[arch]; 14 | 15 | public IUpdater GetUpdaterByArch(string archName) => _updatersByArch[GetArchFromString(archName)]; 16 | 17 | public Dictionary GetUpdaterTable() => _updatersByArch; 18 | 19 | public void SetUpdaterTable(Dictionary updaters) => _updatersByArch = updaters; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Service/Configuration/ServiceInfo.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Server; 2 | using MinecraftService.Shared.Classes.Service.Core; 3 | using MinecraftService.Shared.Interfaces; 4 | using MinecraftService.Shared.SerializeModels; 5 | using System.Collections.Generic; 6 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 7 | 8 | namespace MinecraftService.Shared.Classes.Service.Configuration 9 | { 10 | public class ServiceInfo 11 | { 12 | public PlayerManager PlayerManager { get; set; } 13 | public List serviceLog = []; 14 | public List ServerList = []; 15 | public List globals = []; 16 | public Dictionary> DefaultServerPropsByArch = []; 17 | public int TotalBackupsServiceWide { get; set; } 18 | public int TotalBackupSizeServiceWideMegabytes { get; set; } 19 | } 20 | } -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/ClientReject.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | using MinecraftService.Client.Management; 8 | 9 | namespace MinecraftService.Client.Networking.NetworkStrategies { 10 | public class ClientReject : INetworkMessage { 11 | 12 | public Task ProcessMessage(Shared.Classes.Networking.Message _) => Task.Run(() => { 13 | FormManager.MainWindow.Invoke((MethodInvoker)delegate { 14 | FormManager.MainWindow.ServerInfoBox.Text = "Connection attempt rejected by Service!"; 15 | FormManager.MainWindow.HostInfoLabel.Text = "Connection attempt rejected by Service!"; 16 | }); 17 | return true; 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/Connect.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Networking.Interfaces; 2 | using MinecraftService.Shared.Classes.Networking; 3 | using MinecraftService.Shared.Classes.Service; 4 | using MinecraftService.Shared.Classes.Service.Configuration; 5 | using MinecraftService.Shared.Classes.Service.Core; 6 | using Newtonsoft.Json; 7 | using System.Text; 8 | 9 | namespace MinecraftService.Service.Networking.NetworkStrategies 10 | { 11 | public class Connect(ServiceConfigurator serviceConfiguration) : IMessageParser { 12 | 13 | public Message ParseMessage(Message message) { 14 | Formatting indented = Formatting.Indented; 15 | string jsonString = JsonConvert.SerializeObject(serviceConfiguration, indented, SharedStringBase.GlobalJsonSerialierSettings); 16 | byte[] serializeToBytes = Encoding.UTF8.GetBytes(jsonString); 17 | return new(serializeToBytes, 0, MessageTypes.Connect); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Service/Configuration/ClientSideServiceConfiguration.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Interfaces; 2 | 3 | namespace MinecraftService.Shared.Classes.Service.Configuration 4 | { 5 | public class ClientSideServiceConfiguration 6 | { 7 | private readonly string _hostName; 8 | private readonly string _address; 9 | private readonly string _port; 10 | private readonly string _displayName; 11 | 12 | public ClientSideServiceConfiguration(string hostName, string address, string port) 13 | { 14 | _hostName = hostName; 15 | _address = address; 16 | _port = port; 17 | _displayName = $@"{hostName}@{address}:{port}"; 18 | } 19 | 20 | public string GetHostName() => _hostName; 21 | 22 | public string GetAddress() => _address; 23 | 24 | public string GetPort() => _port; 25 | 26 | public string GetDisplayName() => _displayName; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/LevelEditFile.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.IO; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using MinecraftService.Client.Management; 10 | using MinecraftService.Shared.Classes.Networking; 11 | using MinecraftService.Shared.Classes.Service.Core; 12 | 13 | namespace MinecraftService.Client.Networking.NetworkStrategies { 14 | public class LevelEditFile : INetworkMessage { 15 | 16 | public Task ProcessMessage(Message message) => Task.Run(() => { 17 | string pathToLevelDat = $@"{SharedStringBase.GetNewTempDirectory("LevelEdit")}\level.dat"; 18 | File.WriteAllBytes(pathToLevelDat, message.Data); 19 | FormManager.MainWindow.LevelDatReceived(pathToLevelDat); 20 | return true; 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/StartStopServer.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Service.Server.Interfaces; 4 | using MinecraftService.Shared.Classes.Networking; 5 | using MinecraftService.Shared.SerializeModels; 6 | 7 | namespace MinecraftService.Service.Networking.NetworkStrategies 8 | { 9 | public class StartStopServer(MmsService service) : IMessageParser { 10 | 11 | public Message ParseMessage(Message message) { 12 | IServerController server = service.GetServerByIndex(message.ServerIndex); 13 | if (server.GetServerStatus().ServerStatus == ServerStatus.Started) { 14 | server.ServerStop(true).Wait(); 15 | } else if (server.GetServerStatus().ServerStatus == ServerStatus.Stopped) { 16 | server.ServerStart().Wait(); 17 | server.StartWatchdog(); 18 | } 19 | return Message.EmptyUICallback; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/changelog.yml: -------------------------------------------------------------------------------- 1 | name: Create changelog 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | FromTag: 7 | description: 'Starting tag' 8 | required: false 9 | type: string 10 | ToTag: 11 | description: 'Ending tag' 12 | required: false 13 | type: string 14 | 15 | jobs: 16 | build: 17 | 18 | runs-on: windows-2022 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v3 22 | - name: Remove old changelog 23 | run: rm CHANGELOG.md 24 | - name: Update CHANGELOG 25 | id: changelog 26 | uses: requarks/changelog-action@v1 27 | with: 28 | token: ${{ github.token }} 29 | tag: ${{ inputs.FromTag }} 30 | includeInvalidCommits: true 31 | excludeTypes: build 32 | reverseOrder: true 33 | - name: Upload changelog artifact 34 | uses: actions/upload-artifact@v3 35 | with: 36 | name: changelog-output 37 | path: ./CHANGELOG.md 38 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Interfaces/IBaseConfiguration.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes; 2 | using MinecraftService.Shared.Classes.Service.Core; 3 | using MinecraftService.Shared.SerializeModels; 4 | using System.Collections.Generic; 5 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 6 | 7 | namespace MinecraftService.Shared.Interfaces { 8 | public interface IBaseConfiguration { 9 | bool InitializeDefaults(); 10 | void ProcessUserConfiguration(List configEntries); 11 | bool SetProp(Property propToSet); 12 | Property GetProp(string keyName); 13 | Property GetProp(ServicePropertyKeys key); 14 | Property GetSettingsProp(ServerPropertyKeys key); 15 | Property GetProp(MmsDependServerPropKeys key); 16 | void SetProp(MmsDependServerPropKeys key, string value); 17 | List GetAllProps(); 18 | void SetAllProps(List newPropList); 19 | List GetLog(); 20 | void SetLog(List newLog); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/DeleteBackups.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service; 5 | using MinecraftService.Shared.Classes.Service.Configuration; 6 | using MinecraftService.Shared.Classes.Service.Core; 7 | using System.Text; 8 | 9 | namespace MinecraftService.Service.Networking.NetworkStrategies 10 | { 11 | class DeleteBackups(MmsLogger logger, ServiceConfigurator service) : IMessageParser { 12 | 13 | public Message ParseMessage(Message message) { 14 | string stringData = Encoding.UTF8.GetString(message.Data); 15 | FileInfo file = new FileInfo(stringData); 16 | try { 17 | service.DeleteBackupForServer(message.ServerIndex, stringData); 18 | logger.AppendLine($"Deleted backup {file.Name}."); 19 | } catch (Exception ex) { 20 | logger.AppendLine(ex.Message); 21 | } 22 | return new(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/EnumBackups.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using MinecraftService.Client.Management; 9 | using MinecraftService.Shared.Classes.Networking; 10 | using MinecraftService.Shared.SerializeModels; 11 | using Newtonsoft.Json; 12 | 13 | namespace MinecraftService.Client.Networking.NetworkStrategies { 14 | public class EnumBackups : INetworkMessage { 15 | 16 | public Task ProcessMessage(Message message) => Task.Run(() => { 17 | string data = Encoding.UTF8.GetString(message.Data); 18 | List list = JsonConvert.DeserializeObject>(data); 19 | FormManager.MainWindow.Invoke(() => FormManager.MainWindow.UpdateBackupManagerData(list)); 20 | return true; 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/StartCmdUpdate.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service; 5 | using MinecraftService.Shared.Classes.Service.Configuration; 6 | using MinecraftService.Shared.Classes.Service.Core; 7 | using Newtonsoft.Json; 8 | using System.Text; 9 | 10 | namespace MinecraftService.Service.Networking.NetworkStrategies 11 | { 12 | public class StartCmdUpdate(UserConfigManager configurator, ServiceConfigurator serviceConfiguration) : IMessageParser { 13 | public Message ParseMessage(Message message) { 14 | List entries = JsonConvert.DeserializeObject>(Encoding.UTF8.GetString(message.Data), SharedStringBase.GlobalJsonSerialierSettings); 15 | serviceConfiguration.GetServerInfoByIndex(message.ServerIndex).SetStartCommands(entries); 16 | configurator.SaveServerConfiguration(serviceConfiguration.GetServerInfoByIndex(message.ServerIndex)); 17 | return Message.EmptyUICallback; 18 | } 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Server/ServerInfo.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Service.Core; 2 | using MinecraftService.Shared.SerializeModels; 3 | using System.Collections.Generic; 4 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 5 | 6 | namespace MinecraftService.Shared.Classes.Server 7 | { 8 | public class ServerInfo 9 | { 10 | public MinecraftServerArch ServerArch { get; set; } 11 | public int ProcessID { get; set; } 12 | public PlayerManager PlayerManager { get; set; } 13 | public Property ServersPath { get; set; } 14 | public int TotalBackupSizeKilobytes { get; set; } 15 | public int TotalBackupsStored { get; set; } 16 | public ServerStatusModel ServerStatus { get; set; } = new(); 17 | public List ServerLogs = new(); 18 | public List ServicePropList = new(); 19 | public List ServerPropList = new(); 20 | public List DefaultPropList = new(); 21 | public List StartCmds = new(); 22 | 23 | public ServerInfo() 24 | { 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/FileModels/BaseJsonFile.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.IO; 3 | 4 | namespace MinecraftService.Shared.FileModels 5 | { 6 | public abstract class BaseJsonFile 7 | { 8 | private readonly JsonSerializerSettings defaultJsonSettings = new() { DefaultValueHandling = DefaultValueHandling.Ignore }; 9 | public string FilePath { get; set; } 10 | 11 | public BaseJsonFile(string fullPath) => FilePath = fullPath; 12 | 13 | public BaseJsonFile() { } 14 | 15 | public T LoadJsonFile() 16 | { 17 | if (!File.Exists(FilePath)) 18 | { 19 | return default; 20 | } 21 | return JsonConvert.DeserializeObject(File.ReadAllText(FilePath)); 22 | } 23 | 24 | public void SaveToFile(T value, JsonSerializerSettings settings = null) 25 | { 26 | if (settings == null) 27 | { 28 | settings = defaultJsonSettings; 29 | } 30 | File.WriteAllText(FilePath, JsonConvert.SerializeObject(value, Formatting.Indented, settings)); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/LevelEditRequest.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Networking.Interfaces; 2 | using MinecraftService.Shared.Classes.Networking; 3 | using MinecraftService.Shared.Classes.Service; 4 | using MinecraftService.Shared.Classes.Service.Configuration; 5 | using MinecraftService.Shared.Classes.Service.Core; 6 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 7 | 8 | namespace MinecraftService.Service.Networking.NetworkStrategies 9 | { 10 | public class LevelEditRequest(ServiceConfigurator serviceConfiguration) : IMessageParser { 11 | 12 | public Message ParseMessage(Message message) { 13 | IServerConfiguration server = serviceConfiguration.GetServerInfoByIndex(message.ServerIndex); 14 | string pathToLevelDat = $@"{serviceConfiguration.GetServerInfoByIndex(message.ServerIndex).GetSettingsProp(ServerPropertyKeys.ServerPath)}\worlds\{server.GetProp(MmsDependServerPropKeys.LevelName)}\level.dat"; 15 | byte[] levelDatToBytes = File.ReadAllBytes(pathToLevelDat); 16 | return new(levelDatToBytes, 0, MessageTypes.LevelEditFile); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/PlayersRequest.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using MinecraftService.Client.Management; 9 | using MinecraftService.Shared.Classes.Server; 10 | using MinecraftService.Shared.Classes.Service.Core; 11 | using MinecraftService.Shared.Classes.Networking; 12 | using Newtonsoft.Json; 13 | 14 | namespace MinecraftService.Client.Networking.NetworkStrategies { 15 | public class PlayersRequest : INetworkMessage { 16 | 17 | public Task ProcessMessage(Message message) => Task.Run(() => { 18 | string data = Encoding.UTF8.GetString(message.Data); 19 | List fetchedPlayers = JsonConvert.DeserializeObject>(data, SharedStringBase.GlobalJsonSerialierSettings); 20 | FormManager.MainWindow.ReceivePlayerData(message.ServerIndex, fetchedPlayers); 21 | return true; 22 | }); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Service/BedrockVersionHistoryModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace MinecraftService.Shared.JsonModels.Service 5 | { 6 | public class LegacyBedrockVersionModel 7 | { 8 | [JsonPropertyName("version")] 9 | public string Version { get; set; } 10 | [JsonPropertyName("winurl")] 11 | public string WindowsBinUrl { get; set; } 12 | [JsonPropertyName("linurl")] 13 | public string LinuxBinUrl { get; set; } 14 | } 15 | 16 | public class BedrockVersionHistoryModel 17 | { 18 | [JsonPropertyName("version")] 19 | public string Version { get; set; } 20 | [JsonPropertyName("winurl")] 21 | public string WindowsBinUrl { get; set; } 22 | [JsonPropertyName("linurl")] 23 | public string LinuxBinUrl { get; set; } 24 | [JsonPropertyName("proplist")] 25 | public List PropList { get; set; } = new(); 26 | } 27 | 28 | public class PropInfoEntry 29 | { 30 | public string Key { get; set; } 31 | public string Value { get; set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/ExportFile.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using MinecraftService.Client.Management; 8 | using MinecraftService.Shared.Classes.Networking; 9 | using MinecraftService.Shared.Classes.Service.Core; 10 | using MinecraftService.Shared.SerializeModels; 11 | using Newtonsoft.Json; 12 | 13 | namespace MinecraftService.Client.Networking.NetworkStrategies { 14 | public class ExportFile : INetworkMessage { 15 | 16 | public Task ProcessMessage(Message message) => Task.Run(() => { 17 | string data = Encoding.UTF8.GetString(message.Data); 18 | ExportImportFileModel exportModel = JsonConvert.DeserializeObject(data, SharedStringBase.GlobalJsonSerialierSettings); 19 | if (exportModel != null) { 20 | FormManager.MainWindow.RecieveExportData(exportModel).Wait(); 21 | } 22 | return true; 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MinecraftService/Client/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 MinecraftService.Client.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.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 | -------------------------------------------------------------------------------- /BMS_Files/plugin_repo.json: -------------------------------------------------------------------------------- 1 | { 2 | "PluginRepo": [ 3 | { 4 | "Name": "CrowbarTools", 5 | "Description": "A toolbox of commands for LLBDS", 6 | "PluginVersion": "1.0.0.21", 7 | "ProtoVersion": 568, 8 | "ExtendedInfo": "Currently contains comands for inventory manipulation, multiple commands truncated to one, and tele2server control.", 9 | "ProtectedFiles": [ 10 | "CrowbarTools.ini" 11 | ], 12 | "ProtoBlacklist": [ 13 | 0 14 | ], 15 | "RepoURL": "https://github.com/crowbarmaster/CrowbarsLLBDSPlugins/releases/download/Latest/CrowbarTools.zip" 16 | }, 17 | { 18 | "Name": "BETweaker", 19 | "Description": "Adds features to the game, giving survival players a very rich and useful feature set. By dreamguxiang.", 20 | "PluginVersion": "2.0.0.2", 21 | "ProtoVersion": 568, 22 | "ExtendedInfo": "Current version stripped of a few functions, but is mostly complete.", 23 | "ProtectedFiles": [ 24 | "BETweaker\\*.*" 25 | ], 26 | "ProtoBlacklist": [ 27 | 0 28 | ], 29 | "RepoURL": "https://github.com/crowbarmaster/BETweaker/releases/download/2.0.0.2/BETweaker.zip" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/MMS_Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | win-x64 6 | enable 7 | 8 | false 9 | 10 | Debug;Release;Publish 11 | 12 | AnyCPU;x64 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | all 21 | runtime; build; native; contentfiles; analyzers; buildtransitive 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/PackList.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using MinecraftService.Client.Management; 9 | using MinecraftService.Shared.Classes.Networking; 10 | using MinecraftService.Shared.PackParser; 11 | using Newtonsoft.Json.Linq; 12 | 13 | namespace MinecraftService.Client.Networking.NetworkStrategies { 14 | public class PackList : INetworkMessage { 15 | 16 | public Task ProcessMessage(Message message) => Task.Run(() => { 17 | byte serverIndex = message.ServerIndex; 18 | string data = Encoding.UTF8.GetString(message.Data); 19 | List temp = new(); 20 | JArray jArray = JArray.Parse(data); 21 | foreach (JToken token in jArray) 22 | temp.Add(token.ToObject()); 23 | Task.Run(() => FormManager.MainWindow.Invoke(() => FormManager.MainWindow.ReceivePackData(serverIndex, temp))); 24 | return true; 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/SharedTests/MinecraftUpdatePackageProcessorTests.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes; 2 | using MinecraftService.Shared.Classes.Server; 3 | using MinecraftService.Shared.Classes.Server.Updaters; 4 | using MinecraftService.Shared.Classes.Service.Configuration; 5 | using MinecraftService.Shared.Interfaces; 6 | using System.IO; 7 | using Xunit; 8 | 9 | namespace MMS_Tests.SharedTests 10 | { 11 | public class MinecraftUpdatePackageProcessorTests { 12 | const string _testFilePath = @"..\..\..\..\..\TestFiles"; 13 | private readonly DirectoryInfo _directory = new(_testFilePath); 14 | [Fact] 15 | public void Can_Create_JsonFiles() { 16 | _directory.Create(); 17 | DirectoryInfo outDir = new DirectoryInfo(_testFilePath + @"\Output"); 18 | outDir.Create(); 19 | ProcessInfo processInfo = new ProcessInfo("TestHost", _directory.FullName, 0, true, true); 20 | BedrockUpdatePackageProcessor processor = new(new MinecraftService.Shared.Classes.Service.Core.MmsLogger(processInfo, new ServiceConfigurator(processInfo, new())), "1.0", outDir.FullName); 21 | processor.ExtractCoreFiles(); 22 | Assert.True(File.Exists(@$"{_testFilePath}\Output\stock_props.conf")); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Networking/NetworkEnums.cs: -------------------------------------------------------------------------------- 1 | namespace MinecraftService.Shared.Classes.Networking 2 | { 3 | public enum MessageTypes 4 | { 5 | None, 6 | Connect, 7 | AddNewServer, 8 | RemoveServer, 9 | ConsoleLogUpdate, 10 | PropUpdate, 11 | PlayersRequest, 12 | PlayersUpdate, 13 | StartCmdUpdate, 14 | CheckUpdates, 15 | PackFile, 16 | PackList, 17 | LLPluginFile, 18 | ExportFile, 19 | ImportFile, 20 | VersionListRequest, 21 | LevelEditRequest, 22 | LevelEditFile, 23 | RemovePack, 24 | Command, 25 | Backup, 26 | BackupRollback, 27 | BackupAll, 28 | DelBackups, 29 | EnumBackups, 30 | Restart, 31 | StartStop, 32 | ServerStatusRequest, 33 | Heartbeat, 34 | Disconnect, 35 | ClientReject, 36 | UICallback, 37 | BackupCallback 38 | } 39 | 40 | public enum MessageFlags 41 | { 42 | Failed, 43 | Passed, 44 | RemoveBackups, 45 | RemoveSrv, 46 | RemovePlayers, 47 | RemoveBckSrv, 48 | RemoveBckPly, 49 | RemovePlySrv, 50 | RemoveAll, 51 | None 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/RemoveServer.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Core; 3 | using MinecraftService.Service.Networking.Interfaces; 4 | using MinecraftService.Shared.Classes.Networking; 5 | using MinecraftService.Shared.Classes.Service; 6 | using MinecraftService.Shared.Classes.Service.Configuration; 7 | using MinecraftService.Shared.Classes.Service.Core; 8 | using Newtonsoft.Json; 9 | using System.Text; 10 | 11 | namespace MinecraftService.Service.Networking.NetworkStrategies 12 | { 13 | public class RemoveServer(UserConfigManager configurator, ServiceConfigurator serviceConfiguration, MmsService minecraftService) : IMessageParser { 14 | 15 | public Message ParseMessage(Message message) { 16 | minecraftService.GetServerByIndex(message.ServerIndex).ServerStop(true).Wait(); 17 | configurator.RemoveServerConfigs(serviceConfiguration.GetServerInfoByIndex(message.ServerIndex), message.Flag).Wait(); 18 | minecraftService.RemoveServerInfoByIndex(message.ServerIndex); 19 | byte[] serializeToBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(serviceConfiguration, Formatting.Indented, SharedStringBase.GlobalJsonSerialierSettings)); 20 | return new(serializeToBytes, 0, MessageTypes.Connect); 21 | } 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/VersionListRequest.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using MinecraftService.Client.Management; 10 | using MinecraftService.Shared.Classes.Networking; 11 | using MinecraftService.Shared.Classes.Service.Core; 12 | using Newtonsoft.Json; 13 | 14 | namespace MinecraftService.Client.Networking.NetworkStrategies { 15 | public class VersionListRequest : INetworkMessage { 16 | 17 | public Task ProcessMessage(Message message) => Task.Run(() => { 18 | string data = Encoding.UTF8.GetString(message.Data); 19 | FormManager.Logger.AppendLine("Received version list data from Service."); 20 | Dictionary versionLists = JsonConvert.DeserializeObject>(data, SharedStringBase.GlobalJsonSerialierSettings); 21 | FormManager.MainWindow.VersionListArrived(versionLists); 22 | return true; 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ServerTypeLookup.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.ServerControllers; 2 | using MinecraftService.Shared.Classes.Server; 3 | using MinecraftService.Shared.Classes.Service; 4 | using MinecraftService.Shared.Classes.Service.Configuration; 5 | using MinecraftService.Shared.Classes.Service.Core; 6 | using MinecraftService.Shared.Interfaces; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 13 | 14 | namespace MinecraftService.Shared.Classes 15 | { 16 | public static class ServerTypeLookup { 17 | public static IServerController PrepareNewServerController(MinecraftServerArch serverArch, IServerConfiguration server, UserConfigManager configurator, MmsLogger logger, ServiceConfigurator service, ProcessInfo processInfo) { 18 | switch (serverArch) { 19 | case MinecraftServerArch.Bedrock: 20 | return new BedrockServer(server, configurator, logger, service, processInfo); 21 | case MinecraftServerArch.Java: 22 | return new JavaServer(server, configurator, logger, service, processInfo); 23 | } 24 | return null; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ServerStatusRequest.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service; 5 | using MinecraftService.Shared.Classes.Service.Configuration; 6 | using MinecraftService.Shared.Classes.Service.Core; 7 | using MinecraftService.Shared.SerializeModels; 8 | using Newtonsoft.Json; 9 | using System.Text; 10 | 11 | namespace MinecraftService.Service.Networking.NetworkStrategies 12 | { 13 | public class ServerStatusRequest(MmsService service) : IMessageParser { 14 | 15 | public Message ParseMessage(Message message) { 16 | StatusUpdateModel model = new(); 17 | model.ServiceStatusModel = service.GetServiceStatus(); 18 | byte[] serializeToBytes = Array.Empty(); 19 | if (message.ServerIndex != 255) { 20 | model.ServerStatusModel = service.GetServerByIndex(message.ServerIndex).GetServerStatus(); 21 | } 22 | serializeToBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(model, Formatting.Indented, SharedStringBase.GlobalJsonSerialierSettings)); 23 | return new(serializeToBytes, message.ServerIndex, MessageTypes.ServerStatusRequest); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Server/ProcessInfo.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Interfaces; 2 | 3 | namespace MinecraftService.Shared.Classes.Server 4 | { 5 | public class ProcessInfo 6 | { 7 | private readonly string _declaredType; 8 | private readonly string _serviceDirectory; 9 | private readonly int _processPid; 10 | private readonly bool _debugEnabled; 11 | 12 | public ProcessInfo(string declaredType, string serviceDirectory, int processPid, bool debugEnabled, bool shouldStartService, string serverName = null) 13 | { 14 | _declaredType = declaredType; 15 | _serviceDirectory = serviceDirectory; 16 | _processPid = processPid; 17 | _debugEnabled = debugEnabled; 18 | } 19 | 20 | public ProcessInfo(ProcessInfo spi) 21 | { 22 | _declaredType = spi.DeclaredType(); 23 | _serviceDirectory = spi.GetDirectory(); 24 | _processPid = spi.GetProcessPID(); 25 | _debugEnabled = spi.IsDebugEnabled(); 26 | } 27 | 28 | public string DeclaredType() => _declaredType; 29 | 30 | public string GetDirectory() => _serviceDirectory; 31 | 32 | public int GetProcessPID() => _processPid; 33 | 34 | public bool IsDebugEnabled() => _debugEnabled; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ImportFileRequest.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Server; 5 | using MinecraftService.Shared.Classes.Service; 6 | using MinecraftService.Shared.Classes.Service.Configuration; 7 | using MinecraftService.Shared.Classes.Service.Core; 8 | using MinecraftService.Shared.PackParser; 9 | using MinecraftService.Shared.SerializeModels; 10 | using Newtonsoft.Json; 11 | using System.IO.Compression; 12 | using System.Text; 13 | 14 | namespace MinecraftService.Service.Networking.NetworkStrategies 15 | { 16 | public class ImportFileRequest(UserConfigManager configurator, MmsLogger logger, ServiceConfigurator serviceConfig) : IMessageParser { 17 | 18 | public Message ParseMessage(Message message) { 19 | ExportImportFileModel fileModel = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(message.Data)); 20 | ExportImportManifestModel manifest = fileModel.Manifest; 21 | if (fileModel == null || manifest == null) return new(); 22 | MemoryStream memStream = new(fileModel.Data); 23 | ZipArchive zip = new(memStream); 24 | 25 | if (manifest.FileType.HasFlag(FileTypes.BedrockWorld)) { 26 | 27 | } 28 | return message; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Service/FileProcessors/BedrockServerArchive.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Service.Core; 2 | using MinecraftService.Shared.Utilities; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.IO.Compression; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace MinecraftService.Shared.JsonModels.Service.FileProcessors { 12 | public class BedrockServerArchive(MmsLogger logger) : IFileProcessor { 13 | public void Process(byte[] fileBytes) { 14 | if (fileBytes == null) throw new ArgumentNullException(nameof(fileBytes)); 15 | MemoryStream stream = new MemoryStream(fileBytes); 16 | string tempPath = SharedStringBase.GetNewTempDirectory("BedrockImport"); 17 | Progress progress = new Progress((progress) => { 18 | string prog = string.Format("{0:N2}", progress.Progress); 19 | logger.AppendLine($"Extracting bedrock server contents... {prog}% completed."); 20 | }); 21 | ZipUtilities.ExtractToDirectory(stream, tempPath, progress); 22 | 23 | List serverProps = MinecraftFileUtilities.FilterLinesFromPropFile($"{tempPath}\\{SharedStringBase.GetServerFileName(SharedStringBase.ServerFileNameKeys.ServerProps)}"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/ConsoleLogUpdate.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using MinecraftService.Client.Management; 10 | using MinecraftService.Shared.Classes.Networking; 11 | using MinecraftService.Shared.Classes.Service.Core; 12 | using MinecraftService.Shared.Interfaces; 13 | using MinecraftService.Shared.SerializeModels; 14 | using Newtonsoft.Json; 15 | 16 | namespace MinecraftService.Client.Networking.NetworkStrategies { 17 | public class ConsoleLogUpdate(MmsLogger logger) : INetworkMessage { 18 | public Task ProcessMessage(Message message) => Task.Run(() => { 19 | string data = Encoding.UTF8.GetString(message.Data); 20 | try { 21 | List callbacks = JsonConvert.DeserializeObject>(data); 22 | FormManager.MainWindow.GetLogManager().ProcessIncomingLogData(callbacks); 23 | } catch (Exception e) { 24 | logger.AppendLine($"Error updating logs: {e.Message}"); 25 | return false; 26 | } 27 | return true; 28 | }); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MinecraftService/Service/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | // General Information about an assembly is controlled through the following 4 | // set of attributes. Change these attribute values to modify the information 5 | // associated with an assembly. 6 | [assembly: AssemblyTitle("MinecraftService")] 7 | [assembly: AssemblyDescription("")] 8 | [assembly: AssemblyConfiguration("")] 9 | [assembly: AssemblyCompany("CrowbarWares")] 10 | [assembly: AssemblyProduct("MinecraftService")] 11 | [assembly: AssemblyCopyright("Copyright © 2021")] 12 | [assembly: AssemblyTrademark("")] 13 | [assembly: AssemblyCulture("")] 14 | 15 | // Setting ComVisible to false makes the types in this assembly not visible 16 | // to COM components. If you need to access a type in this assembly from 17 | // COM, set the ComVisible attribute to true on that type. 18 | [assembly: ComVisible(false)] 19 | 20 | // The following GUID is for the ID of the typelib if this project is exposed to COM 21 | [assembly: Guid("f4b1f910-30b0-4f94-a49f-94142e790c9d")] 22 | 23 | // Version information for an assembly consists of the following four values: 24 | // 25 | // Major Version 26 | // Minor Version 27 | // Build Number 28 | // Revision 29 | // 30 | // You can specify all the values or you can default the Build and Revision Numbers 31 | // by using the '*' as shown below: 32 | // [assembly: AssemblyVersion("1.0.*")] 33 | [assembly: AssemblyVersion("3.1.*")] 34 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Interfaces/IServerController.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Server; 2 | using MinecraftService.Shared.Classes.Service.Core; 3 | using MinecraftService.Shared.SerializeModels; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace MinecraftService.Shared.Interfaces 9 | { 10 | public interface IServerController { 11 | void Initialize(); 12 | void StartWatchdog(); 13 | Task ServerStart(); 14 | Task ServerStop(bool stopWatchdog); 15 | void ForceKillServer(); 16 | Task RestartServer(); 17 | string GetServerName(); 18 | void WriteToStandardIn(string command); 19 | bool RollbackToBackup(string targetZip); 20 | MmsLogger GetLogger(); 21 | MmsLogger GetServiceLogger(); 22 | PlayerManager GetPlayerManager(); 23 | List GetActivePlayerList(); 24 | bool IsServerModified(); 25 | void SetServerModified(bool isModified); 26 | bool ServerAutostartEnabled(); 27 | ServerStatusModel GetServerStatus(); 28 | void SetStartupStatus(ServerStatus status); 29 | void RunStartupCommands(); 30 | bool IsPrimaryServer(); 31 | bool IsServerStarted(); 32 | bool IsServerStopped(); 33 | void CheckUpdates(); 34 | IBackupManager GetBackupManager(); 35 | void PerformOfflineServerTask(Action methodToRun); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("MinecraftService.Shared")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("CrowbarWares")] 11 | [assembly: AssemblyProduct("MinecraftService.Shared")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("f146d5e8-ef1f-4785-9150-182631f059b7")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("3.1.*")] 35 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/SaveIncompleteFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class SaveIncompleteFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _bedrockServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public SaveIncompleteFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController bedrockServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _bedrockServer = bedrockServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | Task.Delay(1000).Wait(); 32 | _bedrockServer.WriteToStandardIn("save query"); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/LevelEditFile.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service; 5 | using MinecraftService.Shared.Classes.Service.Configuration; 6 | using MinecraftService.Shared.Classes.Service.Core; 7 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 8 | 9 | namespace MinecraftService.Service.Networking.NetworkStrategies 10 | { 11 | public class LevelEditFile(ServiceConfigurator serviceConfiguration, MmsService mineraftService, MmsLogger logger) : IMessageParser { 12 | 13 | public Message ParseMessage(Message message) { 14 | byte[] stripHeaderFromBuffer = new byte[message.Data.Length - 5]; 15 | Buffer.BlockCopy(message.Data, 5, stripHeaderFromBuffer, 0, stripHeaderFromBuffer.Length); 16 | IServerConfiguration server = serviceConfiguration.GetServerInfoByIndex(message.ServerIndex); 17 | string pathToLevelDat = $@"{serviceConfiguration.GetProp(ServicePropertyKeys.ServersPath)}\{server.GetProp(MmsDependServerPropKeys.ServerName)}\worlds\{server.GetProp(MmsDependServerPropKeys.LevelName)}\level.dat"; 18 | mineraftService.GetServerByIndex(message.ServerIndex).PerformOfflineServerTask(() => { 19 | File.WriteAllBytes(pathToLevelDat, stripHeaderFromBuffer); 20 | logger.AppendLine($"level.dat writen to server {server.GetServerName()}"); 21 | }); 22 | return new(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/ServerRescErrorFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class ServerRescErrorFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _bedrockServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public ServerRescErrorFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController bedrockServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _bedrockServer = bedrockServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | _bedrockServer.PerformOfflineServerTask(() => { 32 | _serverConfiguration.GetUpdater().ReplaceBuild(_serverConfiguration).Wait(); 33 | }); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /MinecraftService/ClientUnitTests/FormTests.cs: -------------------------------------------------------------------------------- 1 | using BedrockService.Client.Forms; 2 | using BedrockService.Client.Management; 3 | using BedrockService.Shared.Classes; 4 | using BedrockService.Shared.Interfaces; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using System.Collections.Generic; 7 | using System.Diagnostics; 8 | using System.IO; 9 | using System.Reflection; 10 | using System.Threading.Tasks; 11 | 12 | namespace ClientUnitTests 13 | { 14 | [TestClass] 15 | public class FormTests 16 | { 17 | [TestMethod] 18 | public void TestClientConfigForm() 19 | { 20 | List clientSideServiceConfigurations = new List(); 21 | clientSideServiceConfigurations.Add(new ClientSideServiceConfiguration("test1", "address1", "1234")); 22 | clientSideServiceConfigurations.Add(new ClientSideServiceConfiguration("test2", "4ddr3552", "3456")); 23 | clientSideServiceConfigurations.Add(new ClientSideServiceConfiguration("test3", "address3", "5678")); 24 | 25 | using (ClientConfigForm form = new ClientConfigForm(new ConfigManager(new ClientLogger(new ServiceProcessInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Path.GetFileName(Assembly.GetExecutingAssembly().Location), Process.GetCurrentProcess().Id, false, true))))) 26 | { 27 | form.Show(); 28 | System.Timers.Timer timer = new System.Timers.Timer(6000); 29 | form.SimulateTests(); 30 | Task.Delay(6000).Wait(); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Service/Core/SimpleVersionModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MinecraftService.Shared.Classes.Service.Core 5 | { 6 | public class SimpleVersionModel : IEquatable 7 | { 8 | public string Version { get; set; } 9 | public List DefaultProps { get; set; } 10 | public bool IsBeta { get; set; } 11 | 12 | public SimpleVersionModel(string version, bool isBeta, List props) 13 | { 14 | Version = version; 15 | IsBeta = isBeta; 16 | DefaultProps = props; 17 | } 18 | 19 | public override string ToString() 20 | { 21 | return Version; 22 | } 23 | 24 | public override bool Equals(object obj) 25 | { 26 | return obj is SimpleVersionModel model && 27 | Version == model.Version && 28 | IsBeta == model.IsBeta; 29 | } 30 | 31 | public override int GetHashCode() 32 | { 33 | return HashCode.Combine(Version, IsBeta); 34 | } 35 | 36 | public bool Equals(SimpleVersionModel other) 37 | { 38 | return Equals(other); 39 | } 40 | 41 | public static bool operator ==(SimpleVersionModel left, SimpleVersionModel right) 42 | { 43 | return EqualityComparer.Default.Equals(left, right); 44 | } 45 | 46 | public static bool operator !=(SimpleVersionModel left, SimpleVersionModel right) 47 | { 48 | return !(left == right); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [2.6](https://github.com/crowbarmaster/BedrockManagementService/tree/2.6) (2022-01-07) 4 | 5 | [Full Changelog](https://github.com/crowbarmaster/BedrockManagementService/compare/2.56Beta...2.6) 6 | 7 | **Implemented enhancements:** 8 | 9 | - Enhancement: Add client setting for auto-scroll on client start [\#43](https://github.com/crowbarmaster/BedrockManagementService/issues/43) 10 | - Backups should include installed packs. [\#35](https://github.com/crowbarmaster/BedrockManagementService/issues/35) 11 | 12 | **Fixed bugs:** 13 | 14 | - Backup limit issue, not deleting oldest versions, overwriting newest backup [\#42](https://github.com/crowbarmaster/BedrockManagementService/issues/42) 15 | - Second client start and connect crashes service [\#41](https://github.com/crowbarmaster/BedrockManagementService/issues/41) 16 | - Duplicate resource pack references [\#32](https://github.com/crowbarmaster/BedrockManagementService/issues/32) 17 | - Mojang license [\#25](https://github.com/crowbarmaster/BedrockManagementService/issues/25) 18 | - Need to include pack enabler json files with backups. [\#19](https://github.com/crowbarmaster/BedrockManagementService/issues/19) 19 | 20 | **Closed issues:** 21 | 22 | - Service no longer allows client connections [\#31](https://github.com/crowbarmaster/BedrockManagementService/issues/31) 23 | - Deletion of a backup does not refresh the listing [\#23](https://github.com/crowbarmaster/BedrockManagementService/issues/23) 24 | - Service crashes on Stop [\#21](https://github.com/crowbarmaster/BedrockManagementService/issues/21) 25 | - Service does not appear to use conf files [\#20](https://github.com/crowbarmaster/BedrockManagementService/issues/20) 26 | -------------------------------------------------------------------------------- /MinecraftService/Client/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Reflection; 6 | using System.Runtime.InteropServices; 7 | 8 | // General Information about an assembly is controlled through the following 9 | // set of attributes. Change these attribute values to modify the information 10 | // associated with an assembly. 11 | [assembly: AssemblyTitle("MMSClientGUI")] 12 | [assembly: AssemblyDescription("")] 13 | [assembly: AssemblyConfiguration("")] 14 | [assembly: AssemblyCompany("CrowbarWares")] 15 | [assembly: AssemblyProduct("MMSClientGUI")] 16 | [assembly: AssemblyCopyright("Copyright © 2021")] 17 | [assembly: AssemblyTrademark("")] 18 | [assembly: AssemblyCulture("")] 19 | 20 | // Setting ComVisible to false makes the types in this assembly not visible 21 | // to COM components. If you need to access a type in this assembly from 22 | // COM, set the ComVisible attribute to true on that type. 23 | [assembly: ComVisible(false)] 24 | 25 | // The following GUID is for the ID of the typelib if this project is exposed to COM 26 | [assembly: Guid("a2daf70a-925a-4f4b-b7ee-caace75d6740")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | [assembly: AssemblyVersion("3.1.*")] 39 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/ClientConnect.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using MinecraftService.Client.Management; 9 | using MinecraftService.Shared.Classes.Networking; 10 | using MinecraftService.Shared.Classes.Service.Configuration; 11 | using MinecraftService.Shared.Classes.Service.Core; 12 | using MinecraftService.Shared.Interfaces; 13 | using Newtonsoft.Json; 14 | 15 | namespace MinecraftService.Client.Networking.NetworkStrategies { 16 | public class ClientConnect(MmsLogger logger, TCPClient client) : INetworkMessage { 17 | 18 | public Task ProcessMessage(Message message) => Task.Run(() => { 19 | try { 20 | string data = Encoding.UTF8.GetString(message.Data); 21 | if (!string.IsNullOrEmpty(data)) { 22 | logger.AppendLine("Connection to Host successful!"); 23 | FormManager.MainWindow.connectedHost = JsonConvert.DeserializeObject(data, SharedStringBase.GlobalJsonSerialierSettings); 24 | FormManager.MainWindow.ConnectedCallback(); 25 | return true; 26 | } 27 | } catch (Exception e) { 28 | logger.AppendLine($"Error: ConnectMan reported error: {e.Message}\n{e.StackTrace}"); 29 | client.CloseConnection(); 30 | client.Cancel(); 31 | return false; 32 | } 33 | return false; 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/VersionListRequest.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Networking.Interfaces; 2 | using MinecraftService.Shared.Classes; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service; 5 | using MinecraftService.Shared.Classes.Service.Configuration; 6 | using MinecraftService.Shared.Classes.Service.Core; 7 | using Newtonsoft.Json; 8 | using System.Text; 9 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 10 | 11 | namespace MinecraftService.Service.Networking.NetworkStrategies 12 | { 13 | public class VersionListRequest(MmsLogger logger, ServiceConfigurator serviceConfiguration) : IMessageParser { 14 | 15 | public Message ParseMessage(Message message) { 16 | logger.AppendLine("Client requested version list data..."); 17 | Dictionary resultDictionary = new(); 18 | foreach (KeyValuePair updaterKvp in serviceConfiguration.GetUpdaterTable()) { 19 | if (!updaterKvp.Value.IsInitialized()) 20 | updaterKvp.Value.Initialize().Wait(); 21 | List verStrings = updaterKvp.Value.GetSimpleVersionList(); 22 | verStrings.Reverse(); 23 | resultDictionary.Add(updaterKvp.Key, verStrings.ToArray()); 24 | } 25 | string jsonString = JsonConvert.SerializeObject(resultDictionary, SharedStringBase.GlobalJsonSerialierSettings); 26 | byte[] resultBytes = Encoding.UTF8.GetBytes(jsonString); 27 | return new(resultBytes, message.ServerIndex, MessageTypes.VersionListRequest); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/StartupFlagFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using MinecraftService.Shared.SerializeModels; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 13 | 14 | namespace MinecraftService.Service.Server.ConsoleFilters 15 | { 16 | public class StartupFlagFilter : IConsoleFilter { 17 | IServerConfiguration _serverConfiguration; 18 | MmsLogger _logger; 19 | UserConfigManager _configurator; 20 | IServerController _bedrockServer; 21 | ServiceConfigurator _serviceConfiguration; 22 | 23 | public StartupFlagFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController bedrockServer, ServiceConfigurator mineraftService) { 24 | _serverConfiguration = serverConfiguration; 25 | _logger = logger; 26 | _configurator = configurator; 27 | _bedrockServer = bedrockServer; 28 | _serviceConfiguration = mineraftService; 29 | } 30 | 31 | public void Filter(string input) { 32 | _bedrockServer.SetStartupStatus(ServerStatus.Started); 33 | Task.Delay(3000).Wait(); 34 | if (_serverConfiguration.GetStartCommands().Count > 0) { 35 | _bedrockServer.RunStartupCommands(); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/RemovePack.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Networking.Interfaces; 2 | using MinecraftService.Shared.Classes.Networking; 3 | using MinecraftService.Shared.Classes.Service; 4 | using MinecraftService.Shared.Classes.Service.Configuration; 5 | using MinecraftService.Shared.Classes.Service.Core; 6 | using MinecraftService.Shared.FileModels.MinecraftFileModels; 7 | using MinecraftService.Shared.PackParser; 8 | using Newtonsoft.Json; 9 | using System.Text; 10 | using System.Text.Json; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Networking.NetworkStrategies { 14 | public class RemovePack(ServiceConfigurator serviceConfiguration, MmsLogger logger) : IMessageParser { 15 | 16 | public Message ParseMessage(Message message) { 17 | string stringData = Encoding.UTF8.GetString(message.Data); 18 | string worldDirectory = $@"{serviceConfiguration.GetServerInfoByIndex(message.ServerIndex).GetSettingsProp(ServerPropertyKeys.ServerPath)}\worlds\{serviceConfiguration.GetServerInfoByIndex(message.ServerIndex).GetProp(MmsDependServerPropKeys.LevelName)}"; 19 | List? container = JsonConvert.DeserializeObject>(stringData, SharedStringBase.GlobalJsonSerialierSettings); 20 | foreach (MinecraftPackContainer content in container) { 21 | MinecraftFileUtilities.RemovePackFromServer(serviceConfiguration.GetServerInfoByIndex(message.ServerIndex), content); 22 | logger.AppendLine($@"{content.JsonManifest.header.name} removed from server."); 23 | } 24 | return Message.EmptyUICallback; 25 | } 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/SharedTests/JsonModelTests.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.FileModels.MinecraftFileModels; 2 | using System.IO; 3 | using Xunit; 4 | 5 | namespace MMS_Tests.SharedTests { 6 | public class JsonModelTests { 7 | 8 | [Fact] 9 | public void Can_Create_Pack_Manifest_File_Model() { 10 | string sampleJson = "{\"format_version\": 1, \"header\": { \"name\": \"Miniguns and Landmines (behavior)\"," + 11 | "\"description\": \"Miniguns and Landmines. Oh ho ho.\", \"uuid\": \"9edcd542-0ce1-4a00-b28d-c6d0be1fa0dc\"," + 12 | "\"version\": [2, 6, 31] }, \"modules\": [ { \"description\": \"Mech Suit\", \"type\": \"data\", \"uuid\":" + 13 | "\"5a159687-5d39-4449-b6a3-c2514a1962f3\", \"version\": [2, 6, 31] } ], \"dependencies\": [ { \"uuid\":" + 14 | "\"0a4ea708-dedc-4185-b1c1-398a9cea8a32\", \"version\": [2, 6, 31] }]}"; 15 | File.WriteAllText(".\\sample_pack_model.json", sampleJson); 16 | PackManifestFileModel fileModel = new(".\\sample_pack_model.json"); 17 | Assert.NotNull(fileModel.Contents); 18 | } 19 | 20 | [Fact] 21 | public void Can_Create_Permission_File_Model() { 22 | string sampleJson = "[{\"permission\": \"member\",\"xuid\": \"1234567801234567\"}," + 23 | "{\"permission\": \"operator\",\"xuid\": \"1234567890123456\"}," + 24 | "{\"permission\": \"operator\",\"xuid\": \"2098765432112345\"}]"; 25 | File.WriteAllText(".\\sample_permissions_model.json", sampleJson); 26 | PermissionsFileModel fileModel = new(".\\sample_permissions_model.json"); 27 | Assert.NotNull(fileModel.Contents); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Server/Configurations/CommonDefaults.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using MinecraftService.Shared.Classes.Service.Core; 3 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 4 | 5 | namespace MinecraftService.Shared.Classes.Server.Configurations 6 | { 7 | public static class CommonConfigDefaults 8 | { 9 | public static List PropList = new List() { 10 | new Property(ServerPropertyStrings[ServerPropertyKeys.ServerAutostartEnabled], "true"), 11 | new Property(ServerPropertyStrings[ServerPropertyKeys.AutoBackupEnabled], "false"), 12 | new Property(ServerPropertyStrings[ServerPropertyKeys.AutoRestartEnabled], "false"), 13 | new Property(ServerPropertyStrings[ServerPropertyKeys.BackupCron], "0 1 * * *"), 14 | new Property(ServerPropertyStrings[ServerPropertyKeys.MaxBackupCount], "25"), 15 | new Property(ServerPropertyStrings[ServerPropertyKeys.AutoBackupsContainPacks], "false"), 16 | new Property(ServerPropertyStrings[ServerPropertyKeys.IgnoreInactiveBackups], "true"), 17 | new Property(ServerPropertyStrings[ServerPropertyKeys.CheckUpdatesEnabled], "true"), 18 | new Property(ServerPropertyStrings[ServerPropertyKeys.AutoDeployUpdates], "true"), 19 | new Property(ServerPropertyStrings[ServerPropertyKeys.UpdateCron], "0 2 * * *"), 20 | new Property(ServerPropertyStrings[ServerPropertyKeys.RestartCron], "0 2 * * *"), 21 | new Property(ServerPropertyStrings[ServerPropertyKeys.ServerVersion], "None"), 22 | new Property(ServerPropertyStrings[ServerPropertyKeys.UseBetaVersions], "false"), 23 | new Property(ServerPropertyStrings[ServerPropertyKeys.UseErrorFilter], "true") 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/SharedTests/UtilitiesTests/FileUtilitiesTests.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Utilities; 2 | using System.IO; 3 | using Xunit; 4 | 5 | namespace MMS_Tests.SharedTests.UtilitiesTests { 6 | public class FileUtilitiesTests { 7 | private readonly string _testDir = @".\TestDir"; 8 | private readonly string _testCopyDir = @".\CopyDir"; 9 | private readonly string _testFile = @".\TestDir\File.file"; 10 | private readonly string _testCopyFile = @".\CopyDir\File.file"; 11 | 12 | [Fact] 13 | public void Can_Create_Inexistant_Directory() { 14 | if (Directory.Exists(@".\TestDir")) { 15 | Directory.Delete(_testDir, true); 16 | } 17 | FileUtilities.CreateInexistentDirectory(_testDir); 18 | Assert.True(Directory.Exists(_testDir)); 19 | } 20 | 21 | [Fact] 22 | public void Can_Create_Inexistant_File() { 23 | if (File.Exists(_testFile)) { 24 | File.Delete(_testFile); 25 | } 26 | FileUtilities.CreateInexistentFile(_testFile); 27 | Assert.True(File.Exists(_testFile)); 28 | } 29 | 30 | [Fact] 31 | public void CreateInexistantDirectory_Does_Not_Modify_Existing() { 32 | Can_Create_Inexistant_File(); 33 | FileUtilities.CreateInexistentDirectory(_testDir); 34 | Assert.True(File.Exists(_testFile)); 35 | } 36 | 37 | [Fact] 38 | public void Can_Copy_Folder_Tree() { 39 | FileUtilities.CreateInexistentDirectory(_testCopyDir); 40 | FileUtilities.CreateInexistentFile(_testCopyFile); 41 | FileUtilities.CopyFolderTree(new(_testCopyDir), new(@".\CopyTestDir")); 42 | Assert.True(File.Exists(@$".\CopyTestDir{_testCopyFile.Substring(1)}")); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Interfaces/IServerConfiguration.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Server; 2 | using MinecraftService.Shared.Classes.Service.Core; 3 | using MinecraftService.Shared.SerializeModels; 4 | using System.Collections.Generic; 5 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 6 | 7 | namespace MinecraftService.Shared.Interfaces 8 | { 9 | public interface IServerConfiguration : IBaseConfiguration { 10 | int GetRunningPid(); 11 | void SetRunningPid(int runningPid); 12 | string GetServerName(); 13 | string GetConfigFileName(); 14 | void AddStartCommand(string command); 15 | bool DeleteStartCommand(string command); 16 | List GetStartCommands(); 17 | void SetStartCommands(List newEntries); 18 | List GetPlayerList(); 19 | void SetPlayerList(List playerList); 20 | Player GetOrCreatePlayer(string xuid, string username = null); 21 | IServerConfiguration GetServerInfo(); 22 | MinecraftServerArch GetServerArch(); 23 | void SetServerVersion(string newVersion); 24 | string GetServerVersion(); 25 | void SetStatus(ServerStatusModel status); 26 | bool IsPrimaryServer(); 27 | ServerStatusModel GetStatus(); 28 | void SetBackupTotals(int totalBackups, int totalSize); 29 | void SetSettingsProp(ServerPropertyKeys key, string value); 30 | void SetSettingsProp(string key, string value); 31 | List GetSettingsList(); 32 | void SetAllSettings(List settingsList); 33 | void ProcessNewServerConfiguration(); 34 | string GetDeployedVersion(); 35 | void SetDeployedVersion(string version); 36 | IUpdater GetUpdater(); 37 | PlayerManager GetPlayerManager(); 38 | void ValidateDeployedServer(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkMessageLookup.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Collections.Generic; 6 | using MinecraftService.Client.Networking.NetworkStrategies; 7 | using MinecraftService.Shared.Classes.Networking; 8 | using MinecraftService.Shared.Classes.Service.Core; 9 | using MinecraftService.Shared.Interfaces; 10 | 11 | namespace MinecraftService.Client.Networking { 12 | internal class NetworkMessageLookup { 13 | public Dictionary MessageLookupContainer { get; set; } 14 | 15 | public NetworkMessageLookup(MmsLogger logger, TCPClient client) { 16 | MessageLookupContainer = new Dictionary() { 17 | { MessageTypes.Connect, new ClientConnect(logger, client) }, 18 | { MessageTypes.EnumBackups, new EnumBackups() }, 19 | { MessageTypes.CheckUpdates, new UnlockUI() }, 20 | { MessageTypes.UICallback, new UnlockUI() }, 21 | { MessageTypes.BackupCallback, new BackupCallback() }, 22 | { MessageTypes.VersionListRequest, new VersionListRequest() }, 23 | { MessageTypes.ConsoleLogUpdate, new ConsoleLogUpdate(logger) }, 24 | { MessageTypes.Backup, new Backup(logger) }, 25 | { MessageTypes.PackList, new PackList() }, 26 | { MessageTypes.PlayersRequest, new PlayersRequest() }, 27 | { MessageTypes.LevelEditFile, new LevelEditFile() }, 28 | { MessageTypes.ServerStatusRequest, new ServerStatusRequest() }, 29 | { MessageTypes.ClientReject, new ClientReject() }, 30 | { MessageTypes.ExportFile, new ExportFile() } 31 | }; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/JsonModels/Minecraft/PackManifestJsonModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace MinecraftService.Shared.JsonModels.Minecraft { 5 | public class PackManifestJsonModel { 6 | public int format_version { get; set; } 7 | public Header header { get; set; } 8 | public List modules { get; set; } 9 | public List dependencies { get; set; } 10 | 11 | public override bool Equals(object obj) { 12 | return obj is PackManifestJsonModel model && 13 | EqualityComparer
.Default.Equals(header, model.header); 14 | } 15 | 16 | public override int GetHashCode() { 17 | return HashCode.Combine(header); 18 | } 19 | 20 | public class Header { 21 | public string description { get; set; } 22 | public string name { get; set; } 23 | public string uuid { get; set; } 24 | public List version { get; set; } 25 | 26 | public override bool Equals(object obj) { 27 | return obj is Header header && 28 | uuid == header.uuid; 29 | } 30 | 31 | public override int GetHashCode() { 32 | return HashCode.Combine(uuid); 33 | } 34 | } 35 | 36 | public class Module { 37 | public string description { get; set; } 38 | public string type { get; set; } 39 | public string uuid { get; set; } 40 | public List version { get; set; } 41 | public string language { get; set; } 42 | public string entry { get; set; } 43 | } 44 | 45 | public class Dependency { 46 | public string uuid { get; set; } 47 | public object version { get; set; } 48 | public string module_name { get; set; } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /MinecraftService/Client/Networking/NetworkStrategies/ServerStatusRequest.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using MinecraftService.Client.Management; 8 | using MinecraftService.Shared.Classes.Networking; 9 | using MinecraftService.Shared.Classes.Service.Core; 10 | using MinecraftService.Shared.SerializeModels; 11 | using Newtonsoft.Json; 12 | 13 | namespace MinecraftService.Client.Networking.NetworkStrategies { 14 | public class ServerStatusRequest : INetworkMessage { 15 | 16 | public Task ProcessMessage(Message message) => Task.Run(() => { 17 | StatusUpdateModel status = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(message.Data), SharedStringBase.GlobalJsonSerialierSettings); 18 | if (status != null && status.ServerStatusModel != null && status.ServerStatusModel.ServerIndex != 255 && FormManager.MainWindow.SelectedServer != null) { 19 | ServerStatusModel formerServerStatus = FormManager.MainWindow.SelectedServer.GetStatus(); 20 | if (!status.ServerStatusModel.Equals(formerServerStatus)) { 21 | FormManager.MainWindow.connectedHost.GetServerInfoByIndex(status.ServerStatusModel.ServerIndex).SetStatus(status.ServerStatusModel); 22 | FormManager.MainWindow.Invoke(() => FormManager.MainWindow.RefreshAllCompenentStates()); 23 | FormManager.TCPClient.SendData(new() { 24 | ServerIndex = message.ServerIndex, 25 | Type = MessageTypes.EnumBackups 26 | }); 27 | } 28 | FormManager.MainWindow.ServiceStatus = status.ServiceStatusModel; 29 | } 30 | return true; 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/RemoveServerControl.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Windows.Forms; 7 | using MinecraftService.Shared.Classes.Networking; 8 | 9 | namespace MinecraftService.Client.Forms { 10 | public partial class RemoveServerControl : Form { 11 | public MessageFlags SelectedFlag; 12 | public RemoveServerControl() { 13 | InitializeComponent(); 14 | } 15 | 16 | private void saveBtn_Click(object sender, EventArgs e) { 17 | if (checkedListBox1.CheckedItems.Count == 0) { 18 | return; 19 | } 20 | foreach (var item in checkedListBox1.CheckedItems) { 21 | if (item.ToString() == "Remove server files") { 22 | SelectedFlag = MessageFlags.RemoveSrv; 23 | } 24 | if (item.ToString() == "Remove server's backups") { 25 | if (SelectedFlag == MessageFlags.RemoveSrv) { 26 | SelectedFlag = MessageFlags.RemoveBckSrv; 27 | } else { 28 | SelectedFlag = MessageFlags.RemoveBackups; 29 | } 30 | } 31 | if (item.ToString() == "Remove player record files") { 32 | if (SelectedFlag == MessageFlags.RemoveSrv) { 33 | SelectedFlag = MessageFlags.RemovePlySrv; 34 | } 35 | if (SelectedFlag == MessageFlags.RemoveBckSrv) { 36 | SelectedFlag = MessageFlags.RemoveAll; 37 | } 38 | if (SelectedFlag == MessageFlags.RemoveBackups) { 39 | SelectedFlag = MessageFlags.RemoveBckPly; 40 | } 41 | } 42 | } 43 | DialogResult = DialogResult.OK; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/JavaBackupDetectFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class JavaBackupDetectFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _javaServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public JavaBackupDetectFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController javaServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _javaServer = javaServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | _logger.AppendLine($"Save data signal for server {_serverConfiguration.GetServerName()} detected! Performing backup now!"); 32 | if (_javaServer.GetBackupManager().PerformBackup(input)) { 33 | _logger.AppendLine($"Backup for server {_serverConfiguration.GetServerName()} Completed."); 34 | if (_javaServer.GetActivePlayerList().Count == 0) { 35 | _javaServer.SetServerModified(false); 36 | } 37 | return; 38 | } 39 | _logger.AppendLine($"Backup for server {_serverConfiguration.GetServerName()} Failed. Check logs!"); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/BackupStringFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class BackupStringFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _minecraftServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public BackupStringFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController minecraftServer, ServiceConfigurator minecraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _minecraftServer = minecraftServer; 27 | _serviceConfiguration = minecraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | if (input.Contains("[Server]")) { 32 | input = input.Substring(input.IndexOf(']') + 2); 33 | } 34 | _logger.AppendLine($"Save data string {_serverConfiguration.GetServerName()} detected! Performing backup now!"); 35 | if (_minecraftServer.GetBackupManager().PerformBackup(input)) { 36 | _logger.AppendLine($"Backup for server {_serverConfiguration.GetServerName()} Completed."); 37 | if (_minecraftServer.GetActivePlayerList().Count == 0) { 38 | _minecraftServer.SetServerModified(false); 39 | } 40 | return; 41 | } 42 | _logger.AppendLine($"Backup for server {_serverConfiguration.GetServerName()} Failed. Check logs!"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/SerializeModels/StatusModels.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Shared.Classes.Server; 2 | using MinecraftService.Shared.Interfaces; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | 7 | namespace MinecraftService.Shared.SerializeModels { 8 | public enum ServiceStatus { 9 | Stopped, 10 | Starting, 11 | Stopping, 12 | Started 13 | } 14 | 15 | public enum ServerStatus { 16 | Stopped, 17 | Starting, 18 | Stopping, 19 | Started 20 | } 21 | 22 | public class StatusUpdateModel { 23 | public ServiceStatusModel ServiceStatusModel { get; set; } 24 | public ServerStatusModel ServerStatusModel { get; set; } 25 | } 26 | 27 | public class ServiceStatusModel { 28 | public DateTime ServiceUptime { get; set; } 29 | public ServiceStatus ServiceStatus { get; set; } 30 | public List ActivePlayerList { get; set; } = new List(); 31 | public int TotalBackups { get; set; } 32 | public int TotalBackupSize { get; set; } 33 | public string LatestVersion { get; set; } 34 | } 35 | 36 | public class ServerStatusModel { 37 | public DateTime ServerUptime { get; set; } 38 | public byte ServerIndex { get; set; } 39 | public ServerStatus ServerStatus { get; set; } 40 | public List ActivePlayerList { get; set; } = new List(); 41 | public int TotalBackups { get; set; } 42 | public int TotalSizeOfBackups { get; set; } 43 | public string DeployedVersion { get; set; } 44 | 45 | public override bool Equals(object obj) { 46 | return obj is ServerStatusModel model && 47 | ServerStatus == model.ServerStatus && 48 | ServerIndex == model.ServerIndex && 49 | TotalBackups == model.TotalBackups && 50 | TotalSizeOfBackups == model.TotalSizeOfBackups && 51 | DeployedVersion == model.DeployedVersion; 52 | } 53 | 54 | public override int GetHashCode() { 55 | return HashCode.Combine(ServerStatus, TotalBackups, ServerIndex, TotalSizeOfBackups, DeployedVersion); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/ExporterControl.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Windows.Forms; 7 | using MinecraftService.Shared.Classes.Networking; 8 | 9 | namespace MinecraftService.Client.Forms { 10 | public partial class ExporterControl : Form { 11 | public MessageFlags SelectedFlag; 12 | public ExporterControl() { 13 | InitializeComponent(); 14 | } 15 | 16 | private void saveBtn_Click(object sender, EventArgs e) { 17 | if (checkedListBox1.CheckedItems.Count == 0) { 18 | return; 19 | } 20 | foreach (var item in checkedListBox1.CheckedItems) { 21 | if (item.ToString() == "Remove server files") { 22 | SelectedFlag = MessageFlags.RemoveSrv; 23 | } 24 | if (item.ToString() == "Remove server's backups") { 25 | if (SelectedFlag == MessageFlags.RemoveSrv) { 26 | SelectedFlag = MessageFlags.RemoveBckSrv; 27 | } else { 28 | SelectedFlag = MessageFlags.RemoveBackups; 29 | } 30 | } 31 | if (item.ToString() == "Remove player record files") { 32 | if (SelectedFlag == MessageFlags.RemoveSrv) { 33 | SelectedFlag = MessageFlags.RemovePlySrv; 34 | } 35 | if (SelectedFlag == MessageFlags.RemoveBckSrv) { 36 | SelectedFlag = MessageFlags.RemoveAll; 37 | } 38 | if (SelectedFlag == MessageFlags.RemoveBackups) { 39 | SelectedFlag = MessageFlags.RemoveBckPly; 40 | } 41 | } 42 | } 43 | DialogResult = DialogResult.OK; 44 | } 45 | 46 | private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e) { 47 | 48 | } 49 | 50 | private void label1_Click(object sender, EventArgs e) { 51 | 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/AddNewServer.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Server; 5 | using MinecraftService.Shared.Classes.Service; 6 | using MinecraftService.Shared.Classes.Service.Configuration; 7 | using MinecraftService.Shared.Classes.Service.Core; 8 | using MinecraftService.Shared.SerializeModels; 9 | using Newtonsoft.Json; 10 | using System.Text; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Networking.NetworkStrategies 14 | { 15 | public class AddNewServer(MmsLogger logger, ProcessInfo processInfo, UserConfigManager configurator, ServiceConfigurator serviceConfiguration, MmsService minecraftService) : IMessageParser { 16 | 17 | public Message ParseMessage(Message message) { 18 | string stringData = Encoding.UTF8.GetString(message.Data); 19 | ServerCombinedPropModel propModel = JsonConvert.DeserializeObject(stringData, GlobalJsonSerialierSettings); 20 | Property? archProp = propModel?.ServicePropList?.First(x => x.KeyName == ServerPropertyStrings[ServerPropertyKeys.MinecraftType]); 21 | MinecraftServerArch selectedArch = GetArchFromString(archProp.StringValue); 22 | configurator.VerifyServerArchInit(selectedArch); 23 | IServerConfiguration newServer = serviceConfiguration.PrepareNewServerConfig(selectedArch, processInfo, logger); 24 | newServer.InitializeDefaults(); 25 | newServer.SetAllSettings(propModel?.ServicePropList); 26 | newServer.SetAllProps(propModel?.ServerPropList); 27 | newServer.ProcessNewServerConfiguration(); 28 | configurator.SaveServerConfiguration(newServer); 29 | minecraftService.InitializeNewServer(newServer); 30 | 31 | 32 | byte[] serializeToBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(serviceConfiguration, Formatting.Indented, GlobalJsonSerialierSettings)); 33 | return new Message { 34 | Data = serializeToBytes, 35 | Type = MessageTypes.Connect 36 | }; 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /MinecraftService/Client/Management/FormManager.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Windows.Forms; 8 | using MinecraftService.Client.Forms; 9 | using MinecraftService.Client.Networking; 10 | using MinecraftService.Shared.Classes.Server; 11 | using MinecraftService.Shared.Classes.Service.Configuration; 12 | using MinecraftService.Shared.Classes.Service.Core; 13 | using MinecraftService.Shared.Interfaces; 14 | 15 | namespace MinecraftService.Client.Management { 16 | public sealed class FormManager { 17 | public static readonly ProcessInfo processInfo = new ProcessInfo("Client", Path.GetDirectoryName(Application.ExecutablePath), Process.GetCurrentProcess().Id, false, true); 18 | public static readonly ServiceConfigurator ClientLogContainer; 19 | public static readonly MmsLogger Logger; 20 | private static MainWindow main; 21 | private static TCPClient client; 22 | 23 | static FormManager() { 24 | ClientLogContainer = new ServiceConfigurator(processInfo, new()); 25 | ClientLogContainer.InitializeDefaults(); 26 | Logger = new MmsLogger(processInfo, ClientLogContainer); 27 | Logger.AppendLine($"Bedrock Client version {Application.ProductVersion} has started."); 28 | Logger.AppendLine($"Working directory: {processInfo.GetDirectory()}"); 29 | SharedStringBase.SetWorkingDirectory(processInfo); 30 | client = new TCPClient(Logger); 31 | main = new MainWindow(processInfo, Logger); 32 | } 33 | 34 | public static MainWindow MainWindow { 35 | get { 36 | if (main == null || main.IsDisposed) { 37 | main = new MainWindow(processInfo, Logger); 38 | } 39 | return main; 40 | } 41 | } 42 | 43 | public static TCPClient TCPClient { 44 | get { 45 | if (client == null) { 46 | client = new TCPClient(Logger); 47 | } 48 | return client; 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ServerPropUpdate.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Core; 3 | using MinecraftService.Service.Networking.Interfaces; 4 | using MinecraftService.Shared.Classes.Networking; 5 | using MinecraftService.Shared.Classes.Service; 6 | using MinecraftService.Shared.Classes.Service.Configuration; 7 | using MinecraftService.Shared.Classes.Service.Core; 8 | using Newtonsoft.Json; 9 | using System.Text; 10 | 11 | namespace MinecraftService.Service.Networking.NetworkStrategies 12 | { 13 | public class ServerPropUpdate(MmsLogger logger, UserConfigManager configurator, ServiceConfigurator serviceConfiguration, MmsService mineraftService) : IMessageParser { 14 | 15 | public Message ParseMessage(Message message) { 16 | string stringData = Encoding.UTF8.GetString(message.Data); 17 | List propList = JsonConvert.DeserializeObject>(stringData, SharedStringBase.GlobalJsonSerialierSettings); 18 | Property prop = propList.FirstOrDefault(p => p.KeyName == "AcceptedMojangLic"); 19 | if (prop != null) { 20 | serviceConfiguration.SetAllProps(propList); 21 | configurator.SaveGlobalFile(); 22 | logger.AppendLine("Successfully wrote service configuration to file! Restarting service to apply changes!"); 23 | mineraftService.RestartService(); 24 | return new(); 25 | } 26 | prop = propList.FirstOrDefault(p => p.KeyName == "server-name"); 27 | if (prop != null) { 28 | foreach (Property property in propList) { 29 | serviceConfiguration.GetServerInfoByIndex(message.ServerIndex).SetProp(property); 30 | } 31 | } else { 32 | foreach (Property property in propList) { 33 | serviceConfiguration.GetServerInfoByIndex(message.ServerIndex).SetSettingsProp(property.KeyName, property.StringValue); 34 | } 35 | } 36 | configurator.SaveServerConfiguration(serviceConfiguration.GetServerInfoByIndex(message.ServerIndex)); 37 | logger.AppendLine("Successfully wrote server configuration to file! Restart server to apply changes!"); 38 | return Message.EmptyUICallback; 39 | } 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/MinecraftService.Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net9.0 4 | win-x64 5 | Library 6 | false 7 | Debug;Release;Publish 8 | AnyCPU;x64 9 | 10 | 11 | 2 12 | False 13 | 14 | 15 | 2 16 | False 17 | 18 | 19 | 2 20 | False 21 | 22 | 23 | 2 24 | False 25 | 26 | 27 | False 28 | 29 | 30 | False 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | all 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/BMSBuild.yml: -------------------------------------------------------------------------------- 1 | name: Build BMS 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | types: [closed] 7 | 8 | jobs: 9 | build: 10 | 11 | runs-on: windows-2022 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Setup .NET 17 | uses: actions/setup-dotnet@v3.2.0 18 | with: 19 | dotnet-version: 9.0.x 20 | 21 | - name: Setup MSBuild 22 | uses: microsoft/setup-msbuild@v1.3.1 23 | 24 | - name: Restore NuGet packages 25 | run: dotnet restore "MinecraftService\MinecraftService.sln" 26 | 27 | - name: Publish with MSBuild 28 | run: msbuild "MinecraftService\MinecraftService.sln" -property:Configuration=Release /t:publish -p:PublishProfile=FolderProfile 29 | 30 | - name: Set version string 31 | run: | 32 | $TMP = (get-item MinecraftService\bin\Published\MinecraftService.Service.exe).VersionInfo.FileVersion; 33 | echo "PROJ_VER=$TMP" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append; 34 | echo "${{ env.PROJ_VER }}" 35 | 36 | - name: Push Automatic Release 37 | uses: crowbarmaster/GH-Automatic-Releases@latest 38 | with: 39 | repo_token: "${{ secrets.REPO_TOKEN }}" 40 | automatic_release_tag: "${{ env.PROJ_VER }}" 41 | prerelease: true 42 | title: "Development Build: Version ${{ env.PROJ_VER }}" 43 | 44 | - name: Update CHANGELOG 45 | continue-on-error: true 46 | uses: requarks/changelog-action@v1 47 | id: changelog 48 | with: 49 | token: ${{ github.token }} 50 | tag: ${{ env.PROJ_VER }} 51 | includeInvalidCommits: true 52 | excludeTypes: build 53 | reverseOrder: true 54 | 55 | - name: Compress published files 56 | run: | 57 | Remove-item MinecraftService\bin\Published\Launcher.exe; 58 | Compress-Archive -path MinecraftService\bin\Published\*.exe* ".\MMS_${{ env.PROJ_VER }}.zip" -Force; 59 | 60 | - name: Push Automatic Release 61 | uses: crowbarmaster/GH-Automatic-Releases@latest 62 | with: 63 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 64 | automatic_release_tag: "${{ env.PROJ_VER }}" 65 | prerelease: true 66 | title: "Development Build: Version ${{ env.PROJ_VER }}" 67 | body: ${{ steps.changelog.outputs.changes }} 68 | files: | 69 | MMS_*.zip 70 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/NewPlayerRegistrationForm.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Windows.Forms; 7 | using MinecraftService.Client.Management; 8 | using MinecraftService.Shared.Classes.Server; 9 | using MinecraftService.Shared.Classes.Service.Core; 10 | using MinecraftService.Shared.Interfaces; 11 | 12 | namespace MinecraftService.Client.Forms { 13 | public partial class NewPlayerRegistrationForm : Form { 14 | public Player PlayerToAdd; 15 | private readonly IServerConfiguration _serverConfiguration; 16 | 17 | public NewPlayerRegistrationForm() { 18 | InitializeComponent(); 19 | _serverConfiguration = FormManager.MainWindow.SelectedServer; 20 | } 21 | 22 | private void saveClick(object sender, EventArgs e) { 23 | long curTime = DateTime.Now.Ticks; 24 | if (usernameTextBox.TextLength > 0 && xuidTextBox.TextLength == 16 || xuidTextBox.TextLength == 36 || xuidTextBox.TextLength == 32) { 25 | PlayerToAdd = 26 | new Player(xuidTextBox.Text, usernameTextBox.Text, curTime, curTime, curTime, whitelistedChkBox.Checked, 27 | _serverConfiguration.GetServerArch() == SharedStringBase.MinecraftServerArch.Java ? 28 | TranslatePermLevel(permissionComboBox.SelectedItem.ToString()) : 29 | permissionComboBox.SelectedItem.ToString(), 30 | ignoreLimitChkBox.Checked); 31 | DialogResult = DialogResult.OK; 32 | } 33 | } 34 | 35 | private string TranslatePermLevel(string permLevel) { 36 | switch (permLevel) { 37 | case "visitor": 38 | return "2"; 39 | case "member": 40 | return "3"; 41 | case "operator": 42 | return "4"; 43 | case "2": 44 | return "visitor"; 45 | case "3": 46 | return "member"; 47 | case "4": 48 | return "operator"; 49 | default: 50 | return ""; 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/ProgressDialog.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | using MinecraftService.Shared.Classes.Service.Core; 9 | 10 | namespace MinecraftService.Client.Forms { 11 | public partial class ProgressDialog : Form { 12 | private readonly IProgress _progress; 13 | private Task _onCompletion; 14 | private int _closeTimeout = 1500; 15 | private System.Timers.Timer _closeTimer; 16 | 17 | public ProgressDialog(Task callbackAction) { 18 | InitializeComponent(); 19 | _closeTimer = new System.Timers.Timer(_closeTimeout); 20 | _onCompletion = callbackAction; 21 | progressBar.Minimum = 0; 22 | progressBar.Maximum = 100; 23 | _closeTimer.AutoReset = false; 24 | _progress = new Progress((currentProgress) => { 25 | progressBar.Value = (int)currentProgress.Progress; 26 | progressLabel.Text = $"{currentProgress.Message}"; 27 | string formattedPercent = string.Format("{0:N2}", currentProgress.Progress); 28 | if (currentProgress.Progress != 0) { 29 | percentLabel.Text = $"{formattedPercent}% completed..."; 30 | } 31 | Refresh(); 32 | }); 33 | } 34 | 35 | public IProgress GetDialogProgress() { 36 | return _progress; 37 | } 38 | 39 | public void EndProgress(Task closingActions, int closeTimeout = 1500) { 40 | _closeTimeout = closeTimeout; 41 | _closeTimer.Elapsed += (s, e) => { 42 | if (closingActions != null && closingActions.Status == TaskStatus.Created) { 43 | closingActions.Start(); 44 | } 45 | if (_onCompletion != null && _onCompletion.Status == TaskStatus.Created) { 46 | _onCompletion.Start(); 47 | } 48 | }; 49 | _closeTimer.Start(); 50 | } 51 | 52 | public void SetCallback(Task action) { 53 | _onCompletion = action; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/JavaPlayerConnectedFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class JavaPlayerConnectedFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _javaServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public JavaPlayerConnectedFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController javaServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _javaServer = javaServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | var playerInfo = ExtractPlayerInfoFromString(input); 32 | _logger.AppendLine($"Player {playerInfo.username} connected to server {_serverConfiguration.GetServerName()}."); 33 | _javaServer.SetServerModified(true); 34 | _javaServer.GetActivePlayerList().Add(_javaServer.GetPlayerManager().PlayerConnected(playerInfo.username, playerInfo.uuid)); 35 | _configurator.SavePlayerDatabase(_serverConfiguration); 36 | } 37 | 38 | private (string username, string uuid) ExtractPlayerInfoFromString(string input) { 39 | int msgStartIndex = input.IndexOf("]:") + 3; 40 | int userStart = msgStartIndex + "UUID of player ".Length; 41 | int uuidLength = 36; 42 | int uuidStart = input.Length - uuidLength; 43 | int userEnd = uuidStart - 4; 44 | int userLength = userEnd - userStart; 45 | return (input.Substring(userStart, userLength), input.Substring(uuidStart, uuidLength)); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/JavaPlayerDisconnectedFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class JavaPlayerDisconnectedFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _bedrockServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public JavaPlayerDisconnectedFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController bedrockServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _bedrockServer = bedrockServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | var playerInfo = ExtractPlayerInfoFromString(input); 32 | if (_bedrockServer.GetActivePlayerList().Any()) { 33 | if(_bedrockServer.GetActivePlayerList().Remove(_bedrockServer.GetActivePlayerList().Where(x => x.GetPlayerID() == _bedrockServer.GetPlayerManager().PlayerDisconnected(playerInfo.username, playerInfo.xuid).GetPlayerID()).FirstOrDefault())) { 34 | _logger.AppendLine($"Player {playerInfo.username} disconnected from server {_serverConfiguration.GetServerName()}."); 35 | } 36 | } 37 | _configurator.SavePlayerDatabase(_serverConfiguration); 38 | } 39 | 40 | private (string username, string xuid) ExtractPlayerInfoFromString(string input) { 41 | int msgStartIndex = input.IndexOf("]:") + 3; 42 | int usernameEnd = input.IndexOf(" left the game", msgStartIndex); 43 | int usernameLength = usernameEnd - msgStartIndex; 44 | return (input.Substring(msgStartIndex, usernameLength), ""); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/PackList.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Networking.Interfaces; 2 | using MinecraftService.Shared.Classes.Networking; 3 | using MinecraftService.Shared.Classes.Server; 4 | using MinecraftService.Shared.Classes.Service; 5 | using MinecraftService.Shared.Classes.Service.Configuration; 6 | using MinecraftService.Shared.Classes.Service.Core; 7 | using MinecraftService.Shared.JsonModels.Minecraft; 8 | using MinecraftService.Shared.PackParser; 9 | using Newtonsoft.Json; 10 | using NLog.LayoutRenderers; 11 | using System.Text; 12 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 13 | 14 | namespace MinecraftService.Service.Networking.NetworkStrategies 15 | { 16 | public class PackList(ProcessInfo processInfo, ServiceConfigurator serviceConfiguration, MmsLogger logger) : IMessageParser { 17 | 18 | public Message ParseMessage(Message message) { 19 | IServerConfiguration server = serviceConfiguration.GetServerInfoByIndex(message.ServerIndex); 20 | string serverPath = server.GetSettingsProp(ServerPropertyKeys.ServerPath).StringValue; 21 | string levelName = server.GetProp(MmsDependServerPropKeys.LevelName).StringValue; 22 | string pathToWorldFolder = $@"{serverPath}\worlds\{levelName}"; 23 | List combinedList = new List(); 24 | IProgress progress = new Progress((progress) => { 25 | string percent = string.Format("{0:N2}", progress.Progress); 26 | logger.AppendLine($"{progress.Message} {percent}%"); 27 | }); 28 | MinecraftPackParser resourceParser = new(logger, progress); 29 | MinecraftPackParser behaviorParser = new(logger, progress); 30 | resourceParser.ParseDirectory(GetServerDirectory(ServerDirectoryKeys.ResourcePacksDir_LevelName, serverPath, levelName), 0); 31 | behaviorParser.ParseDirectory(GetServerDirectory(ServerDirectoryKeys.BehaviorPacksDir_LevelName, serverPath, levelName), 0); 32 | MinecraftFileUtilities.ValidateFixWorldPackFiles(serverPath, levelName).Wait(); 33 | combinedList.AddRange(resourceParser.FoundPacks); 34 | combinedList.AddRange(behaviorParser.FoundPacks); 35 | 36 | string arrayString = JsonConvert.SerializeObject(combinedList); 37 | return new(Encoding.UTF8.GetBytes(arrayString), 0, MessageTypes.PackList); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/SerializeModels/BackupInfoModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Drawing; 4 | using System.Globalization; 5 | using System.IO; 6 | 7 | namespace MinecraftService.Shared.SerializeModels { 8 | public class BackupInfoModel { 9 | public DateTime Timestamp { get; set; } 10 | public string Filename { get; set; } 11 | public int SizeInKb { get; set; } 12 | private const string _backupStringTemplate = "Backup-yyyyMMdd_HHmmssff.zip"; 13 | private const string _backupFilenamePrefix = "Backup-"; 14 | private const string _timestampTemplate = "yyyyMMdd_HHmmssff"; 15 | 16 | public BackupInfoModel(FileInfo backupFileInfo) { 17 | Filename = backupFileInfo.Name; 18 | if (backupFileInfo.Exists) { 19 | SizeInKb = (int)(backupFileInfo.Length / 1000); 20 | } else { 21 | SizeInKb = 0; 22 | } 23 | if (backupFileInfo.Name.Length != _backupStringTemplate.Length) { 24 | throw new ArgumentOutOfRangeException($"File name length of file {backupFileInfo.Name} was not as expected! Omitted from backup enumeration."); 25 | } 26 | string timeStampFromName = backupFileInfo.Name.Substring(_backupFilenamePrefix.Length, _timestampTemplate.Length); 27 | if (!DateTime.TryParseExact(timeStampFromName, "yyyyMMdd_HHmmssff", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsedTime)) { 28 | throw new FormatException($"DateTime format of file {backupFileInfo.Name} did not match! Omitted from backup enumeration."); 29 | } 30 | Timestamp = parsedTime; 31 | } 32 | 33 | public BackupInfoModel() { 34 | Filename = "-----.zip"; 35 | SizeInKb = 0; 36 | Timestamp = DateTime.MinValue; 37 | } 38 | 39 | [JsonConstructor] 40 | public BackupInfoModel(string filename, int size, DateTime stamp) { 41 | Filename = filename; 42 | SizeInKb = size; 43 | Timestamp = stamp; 44 | } 45 | 46 | public string[] GetBackupInfo() { 47 | return new string[5] { $"Filename: {Filename}", $"Created on: {Timestamp.ToString("G")}", $"Size of backup: {SizeInKb / 1000f} MB", "", "-----------------------------------------------------------" }; 48 | } 49 | 50 | public override string ToString() { 51 | return Filename; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.github/workflows/BMSBuildStable.yml: -------------------------------------------------------------------------------- 1 | name: Build BMS (Stable) 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | lastTag: 7 | description: 'Beginning of changelog history starts at this tag name.' 8 | required: true 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: windows-2022 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - name: Setup .NET 19 | uses: actions/setup-dotnet@v3.2.0 20 | with: 21 | dotnet-version: 9.0.x 22 | 23 | - name: Setup MSBuild 24 | uses: microsoft/setup-msbuild@v1.3.1 25 | 26 | - name: Restore NuGet packages 27 | run: dotnet restore "MinecraftService\MinecraftService.sln" 28 | 29 | - name: Publish with MSBuild 30 | run: msbuild "MinecraftService\MinecraftService.sln" -property:Configuration=Release /t:publish -p:PublishProfile=FolderProfile 31 | 32 | - name: Set version string 33 | run: | 34 | $TMP = (get-item MinecraftService\bin\Published\MinecraftService.Service.exe).VersionInfo.FileVersion; 35 | echo "PROJ_VER=$TMP" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf-8 -Append; 36 | echo "${{ env.PROJ_VER }}" 37 | 38 | - name: Push Automatic Release 39 | uses: crowbarmaster/GH-Automatic-Releases@latest 40 | with: 41 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 42 | automatic_release_tag: "${{ env.PROJ_VER }}" 43 | prerelease: true 44 | title: "Development Build: Version ${{ env.PROJ_VER }}" 45 | 46 | - name: Update CHANGELOG 47 | continue-on-error: true 48 | uses: requarks/changelog-action@v1 49 | id: changelog 50 | with: 51 | token: ${{ github.token }} 52 | fromtag: ${{ env.PROJ_VER }} 53 | totag: ${{ inputs.lastTag }} 54 | includeInvalidCommits: true 55 | excludeTypes: build 56 | reverseOrder: true 57 | 58 | - name: Compress published files 59 | run: | 60 | Remove-item MinecraftService\bin\Published\Launcher.exe; 61 | Compress-Archive -path MinecraftService\bin\Published\*.exe* ".\MMS_${{ env.PROJ_VER }}.zip" -Force; 62 | 63 | - name: Push Automatic Release 64 | uses: crowbarmaster/GH-Automatic-Releases@latest 65 | with: 66 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 67 | automatic_release_tag: "${{ env.PROJ_VER }}" 68 | prerelease: false 69 | title: "Stable Build: Version ${{ env.PROJ_VER }}" 70 | body: ${{ steps.changelog.outputs.changes }} 71 | files: | 72 | MMS_*.zip 73 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/BedrockPlayerDisconnectedFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class BedrockPlayerDisconnectedFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _bedrockServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public BedrockPlayerDisconnectedFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController bedrockServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _bedrockServer = bedrockServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | var playerInfo = ExtractPlayerInfoFromString(input); 32 | _logger.AppendLine($"Player {playerInfo.username} disconnected from server {_serverConfiguration.GetServerName()}."); 33 | _bedrockServer.GetActivePlayerList().Remove(_bedrockServer.GetActivePlayerList().Where(x => x.GetPlayerID() == _bedrockServer.GetPlayerManager().PlayerDisconnected(null, playerInfo.xuid).GetPlayerID()).FirstOrDefault()); 34 | _configurator.SavePlayerDatabase(_serverConfiguration); 35 | } 36 | 37 | 38 | private (string username, string xuid) ExtractPlayerInfoFromString(string input) { 39 | string playerDisconnected = "Player disconnected: "; 40 | string xuid = "xuid: "; 41 | int usernameStart = input.IndexOf(playerDisconnected); 42 | int xuidStart = input.IndexOf(xuid); 43 | int usernameLength = (xuidStart - 1) - (usernameStart + playerDisconnected.Length); 44 | return (input.Substring(usernameStart + playerDisconnected.Length, usernameLength), input.Substring(xuidStart + xuid.Length, 16)); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/PlayersUpdate.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Core; 3 | using MinecraftService.Service.Networking.Interfaces; 4 | using MinecraftService.Shared.Classes.Networking; 5 | using MinecraftService.Shared.Classes.Server; 6 | using MinecraftService.Shared.Classes.Service; 7 | using MinecraftService.Shared.Classes.Service.Configuration; 8 | using MinecraftService.Shared.Classes.Service.Core; 9 | using Newtonsoft.Json; 10 | using System.Text; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Networking.NetworkStrategies 14 | { 15 | public class PlayersUpdate(UserConfigManager configurator, ServiceConfigurator serviceConfiguration, MmsService service) : IMessageParser { 16 | 17 | public Message ParseMessage(Message message) { 18 | string stringData = Encoding.UTF8.GetString(message.Data); 19 | List fetchedPlayers = JsonConvert.DeserializeObject>(stringData, GlobalJsonSerialierSettings); 20 | foreach (Player player in fetchedPlayers) { 21 | try { 22 | service.GetServerByIndex(message.ServerIndex).GetPlayerManager().AddUpdatePlayer(player); 23 | } catch (Exception) { 24 | } 25 | } 26 | if (serviceConfiguration.GetProp(ServicePropertyKeys.GlobalizedPlayerDatabase).GetBoolValue()) { 27 | foreach (IServerConfiguration server in serviceConfiguration.GetServerList()) { 28 | configurator.SavePlayerDatabase(server); 29 | configurator.WriteJSONFiles(server); 30 | Task.Delay(500).Wait(); 31 | service.GetServerByIndex(serviceConfiguration.GetServerIndex(server)).WriteToStandardIn("ops reload"); 32 | service.GetServerByIndex(serviceConfiguration.GetServerIndex(server)).WriteToStandardIn("whitelist reload"); 33 | } 34 | } else { 35 | configurator.SavePlayerDatabase(serviceConfiguration.GetServerInfoByIndex(message.ServerIndex)); 36 | configurator.WriteJSONFiles(serviceConfiguration.GetServerInfoByIndex(message.ServerIndex)); 37 | Task.Delay(500).Wait(); 38 | service.GetServerByIndex(message.ServerIndex).WriteToStandardIn("ops reload"); 39 | service.GetServerByIndex(message.ServerIndex).WriteToStandardIn("whitelist reload"); 40 | } 41 | return Message.EmptyUICallback; 42 | } 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/BedrockPlayerConnectedFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class BedrockPlayerConnectedFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _bedrockServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public BedrockPlayerConnectedFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController bedrockServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _bedrockServer = bedrockServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | var playerInfo = ExtractPlayerInfoFromString(input); 32 | _logger.AppendLine($"Player {playerInfo.username} connected with XUID: {playerInfo.xuid} to server {_serverConfiguration.GetServerName()}."); 33 | _bedrockServer.SetServerModified(true); 34 | _bedrockServer.GetActivePlayerList().Add(_bedrockServer.GetPlayerManager().PlayerConnected(playerInfo.username, playerInfo.xuid)); 35 | _configurator.SavePlayerDatabase(_serverConfiguration); 36 | } 37 | 38 | // Player Spawned: Crowbarmast3r xuid: 0123456789012345, pfid: 0a1b2c3d4e5f6g7h 39 | private (string username, string xuid) ExtractPlayerInfoFromString(string input) { 40 | string playerConnected = "Player Spawned: "; 41 | string xuid = "xuid: "; 42 | int usernameStart = input.IndexOf(playerConnected); 43 | int xuidStart = input.IndexOf(xuid); 44 | int usernameLength = (xuidStart - 1) - (usernameStart + playerConnected.Length); 45 | return (input.Substring(usernameStart + playerConnected.Length, usernameLength), input.Substring(xuidStart + xuid.Length, 16)); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/ConsoleLogUpdate.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Core; 2 | using MinecraftService.Service.Networking.Interfaces; 3 | using MinecraftService.Shared.Classes.Networking; 4 | using MinecraftService.Shared.Classes.Service; 5 | using MinecraftService.Shared.Classes.Service.Configuration; 6 | using MinecraftService.Shared.Classes.Service.Core; 7 | using MinecraftService.Shared.SerializeModels; 8 | using Newtonsoft.Json; 9 | using System.Text; 10 | 11 | namespace MinecraftService.Service.Networking.NetworkStrategies 12 | { 13 | public class ConsoleLogUpdate(MmsLogger logger, ServiceConfigurator serviceConfiguration, MmsService service) : IMessageParser { 14 | 15 | public Message ParseMessage(Message message) { 16 | string stringData = Encoding.UTF8.GetString(message.Data); 17 | List requests = JsonConvert.DeserializeObject>(stringData); 18 | List callbackList = []; 19 | int localCount = 0; 20 | List log; 21 | foreach (ConsoleLogUpdateRequest request in requests) { 22 | ConsoleLogUpdateCallback callback = new ConsoleLogUpdateCallback(); 23 | if (request.LogTarget == 0xFF) { 24 | callback.LogTarget = 0xFF; 25 | log = serviceConfiguration.GetLog(); 26 | localCount = log.Count; 27 | while (request.CurrentCount < localCount) { 28 | callback.LogEntries.Add(log[request.CurrentCount++].Text); 29 | } 30 | callback.CurrentCount = log.Count; 31 | callbackList.Add(callback); 32 | continue; 33 | } 34 | IServerConfiguration server = serviceConfiguration.GetServerInfoByIndex(request.LogTarget); 35 | log = server.GetLog(); 36 | localCount = log.Count; 37 | callback.LogTarget = serviceConfiguration.GetServerIndex(server); 38 | while (request.CurrentCount < localCount) { 39 | callback.LogEntries.Add(log[request.CurrentCount++].Text); 40 | } 41 | callback.CurrentCount = log.Count; 42 | callbackList.Add(callback); 43 | } 44 | string jsonData = JsonConvert.SerializeObject(callbackList); 45 | byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonData); 46 | return new(jsonBytes, 0, MessageTypes.ConsoleLogUpdate); 47 | } 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/TimerService.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 11 | 12 | namespace MinecraftService.Service.Server 13 | { 14 | public class TimerService { 15 | public List ActiveTimers { get; set; } = new(); 16 | private IServerController _runningServer; 17 | private IServerConfiguration _parentServerConfig; 18 | private ServiceConfigurator _serviceConfiguration; 19 | 20 | public TimerService(IServerController runningServer, IServerConfiguration serverConfiguration, ServiceConfigurator service) { 21 | _runningServer = runningServer; 22 | _parentServerConfig = serverConfiguration; 23 | _serviceConfiguration = service; 24 | } 25 | 26 | public void StartTimerService() { 27 | for (int i = 0; i < Enum.GetNames(typeof(MmsTimerTypes)).Length; i++) { 28 | StartTimer((MmsTimerTypes)i); 29 | } 30 | } 31 | 32 | public void StopTimerService() { 33 | foreach (TimerWorker worker in ActiveTimers) { 34 | worker.Stop().Wait(); 35 | } 36 | ActiveTimers.Clear(); 37 | } 38 | 39 | public void StartTimer(MmsTimerTypes timerType) { 40 | foreach (TimerWorker entry in ActiveTimers) { 41 | if (entry.GetTimerType() == timerType) { 42 | return; 43 | } 44 | } 45 | TimerWorker worker; 46 | worker = CreateTimer(timerType); 47 | 48 | if (worker.Start().Result) { 49 | ActiveTimers.Add(worker); 50 | } 51 | } 52 | 53 | public void StopTimer(MmsTimerTypes timerType) { 54 | TimerWorker removeWorker = null; 55 | foreach (TimerWorker worker in ActiveTimers) { 56 | if (worker.GetTimerType() == timerType) { 57 | worker.Stop().Wait(); 58 | removeWorker = worker; 59 | } 60 | } 61 | if (removeWorker != null) { 62 | ActiveTimers.Remove(removeWorker); 63 | } 64 | } 65 | 66 | private TimerWorker CreateTimer(MmsTimerTypes timerType) => new TimerWorker(_runningServer, _parentServerConfig, _serviceConfiguration, timerType); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/JavaPlayerLostConnectionFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class JavaPlayerLostConnectionFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _bedrockServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public JavaPlayerLostConnectionFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController bedrockServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _bedrockServer = bedrockServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | var playerInfo = ExtractPlayerInfoFromString(input); 32 | if (_bedrockServer.GetActivePlayerList().Any()) { 33 | if(_bedrockServer.GetActivePlayerList().Remove(_bedrockServer.GetActivePlayerList().Where(x => x.GetPlayerID() == _bedrockServer.GetPlayerManager().PlayerDisconnected(playerInfo.username, playerInfo.xuid).GetPlayerID()).FirstOrDefault())) { 34 | _logger.AppendLine($"Player {playerInfo.username} has lost connection from server {_serverConfiguration.GetServerName()}, and has been removed from active players."); 35 | } 36 | } 37 | _configurator.SavePlayerDatabase(_serverConfiguration); 38 | } 39 | 40 | private (string username, string xuid) ExtractPlayerInfoFromString(string input) { 41 | int msgStartIndex = input.IndexOf("]:") + 3; 42 | int usernameEnd = 0; 43 | if (input.Contains(" (/")) { 44 | usernameEnd = input.IndexOf(" (/", msgStartIndex); 45 | } else { 46 | usernameEnd = input.IndexOf(" lost connection", msgStartIndex); 47 | } 48 | int usernameLength = usernameEnd - msgStartIndex; 49 | return (input.Substring(msgStartIndex, usernameLength), ""); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /MinecraftService/ServiceTests/ServiceTests/ServiceTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Hosting; 3 | using MinecraftService.Service; 4 | using MinecraftService.Service.Core; 5 | using MinecraftService.Service.Core.Interfaces; 6 | using MinecraftService.Shared.SerializeModels; 7 | using Newtonsoft.Json; 8 | using System; 9 | using System.Threading.Tasks; 10 | using Xunit; 11 | 12 | namespace MMS_Tests.ServiceTests { 13 | public class ServiceTests { 14 | public class TestFixture : IDisposable { 15 | 16 | public IHost Host; 17 | public MmsService MinecraftService; 18 | public JsonSerializerSettings SerializerSettings = new() { TypeNameHandling = TypeNameHandling.All }; 19 | 20 | public TestFixture() { 21 | Host = Program.CreateHostBuilder(new string[] { }).Build(); 22 | MinecraftService = Host.Services.GetRequiredService(); 23 | } 24 | 25 | public async Task StartFixture() { 26 | await Task.Run(() => { 27 | if (MinecraftService.Start(null)) { 28 | while (MinecraftService != null && MinecraftService.GetServiceStatus().ServiceStatus != ServiceStatus.Started) { 29 | Task.Delay(100).Wait(); 30 | } 31 | } 32 | }); 33 | } 34 | 35 | public void Dispose() { 36 | if (MinecraftService.Stop(null)) { 37 | while (MinecraftService != null && MinecraftService.GetServiceStatus().ServiceStatus != ServiceStatus.Stopped) { 38 | Task.Delay(100).Wait(); 39 | } 40 | } 41 | } 42 | } 43 | 44 | public class RunningServiceTests : IClassFixture { 45 | readonly TestFixture _testFixture; 46 | 47 | public RunningServiceTests() { 48 | _testFixture = new(); 49 | } 50 | 51 | [Fact] 52 | public async Task Verify_Service_Startup() { 53 | Assert.Equal(ServiceStatus.Stopped, _testFixture.MinecraftService.GetServiceStatus().ServiceStatus); 54 | await _testFixture.StartFixture(); 55 | Assert.Equal(ServiceStatus.Started, _testFixture.MinecraftService.GetServiceStatus().ServiceStatus); 56 | } 57 | 58 | [Fact] 59 | public void Verify_Service_Stop() { 60 | Assert.Equal(ServiceStatus.Started, _testFixture.MinecraftService.GetServiceStatus().ServiceStatus); 61 | _testFixture.Dispose(); 62 | Assert.Equal(ServiceStatus.Stopped, _testFixture.MinecraftService.GetServiceStatus().ServiceStatus); 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Service/Core/Property.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | 4 | namespace MinecraftService.Shared.Classes.Service.Core 5 | { 6 | public class Property 7 | { 8 | public string KeyName { get; set; } = string.Empty; 9 | public string StringValue { get; set; } = string.Empty; 10 | public string DefaultValue { get; set; } = string.Empty; 11 | 12 | [JsonConstructor] 13 | public Property(string key, string defaultValue) 14 | { 15 | KeyName = key; 16 | StringValue = defaultValue; 17 | DefaultValue = defaultValue; 18 | } 19 | 20 | public Property(Property newProp) 21 | { 22 | KeyName = newProp.KeyName; 23 | StringValue = newProp.StringValue; 24 | DefaultValue = newProp.DefaultValue; 25 | } 26 | 27 | public override string ToString() => StringValue; 28 | 29 | 30 | public string PropFileFormatString() => $"{KeyName}={StringValue}"; 31 | 32 | 33 | public void SetValue(string newValue) 34 | { 35 | StringValue = newValue; 36 | } 37 | 38 | public void SetValue(int newValue) 39 | { 40 | StringValue = newValue.ToString(); 41 | } 42 | 43 | public void SetValue(bool newValue) 44 | { 45 | StringValue = newValue.ToString(); 46 | } 47 | 48 | public bool GetBoolValue() 49 | { 50 | try 51 | { 52 | if (bool.TryParse(StringValue, out bool result)) 53 | { 54 | return result; 55 | } 56 | } 57 | catch (Exception e) 58 | { 59 | throw new FormatException($"Value for property {KeyName} tried to parse as a bool and failed! Check configs!", e); 60 | } 61 | return false; 62 | } 63 | 64 | public int GetIntValue() 65 | { 66 | try 67 | { 68 | if (int.TryParse(StringValue, out int result)) 69 | { 70 | return result; 71 | } 72 | } 73 | catch (Exception e) 74 | { 75 | throw new FormatException($"Value for property {KeyName} tried to parse as a bool and failed! Check configs!", e); 76 | } 77 | return 0; 78 | } 79 | 80 | public override bool Equals(object obj) 81 | { 82 | return obj is Property property && 83 | KeyName == property.KeyName && 84 | StringValue == property.StringValue && 85 | DefaultValue == property.DefaultValue; 86 | } 87 | 88 | public override int GetHashCode() 89 | { 90 | return HashCode.Combine(KeyName, StringValue, DefaultValue); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/ManagePacksForms.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/ProgressDialog.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/RemoveServerControl.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/NewPlayerRegistrationForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /MinecraftService/Service/Server/ConsoleFilters/JavaVersionFilter.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Server.Interfaces; 2 | using MinecraftService.Shared.Classes.Service; 3 | using MinecraftService.Shared.Classes.Service.Configuration; 4 | using MinecraftService.Shared.Classes.Service.Core; 5 | using MinecraftService.Shared.Interfaces; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 12 | 13 | namespace MinecraftService.Service.Server.ConsoleFilters 14 | { 15 | public class JavaVersionFilter : IConsoleFilter { 16 | IServerConfiguration _serverConfiguration; 17 | MmsLogger _logger; 18 | UserConfigManager _configurator; 19 | IServerController _javaServer; 20 | ServiceConfigurator _serviceConfiguration; 21 | 22 | public JavaVersionFilter(MmsLogger logger, UserConfigManager configurator, IServerConfiguration serverConfiguration, IServerController javaServer, ServiceConfigurator mineraftService) { 23 | _serverConfiguration = serverConfiguration; 24 | _logger = logger; 25 | _configurator = configurator; 26 | _javaServer = javaServer; 27 | _serviceConfiguration = mineraftService; 28 | } 29 | 30 | public void Filter(string input) { 31 | int msgStartIndex = input.IndexOf("version ") + 8; 32 | string versionString = input.Substring(msgStartIndex, input.Length - msgStartIndex); 33 | if (_serverConfiguration.GetSettingsProp(ServerPropertyKeys.ServerVersion).StringValue == "None") { 34 | _logger.AppendLine("Service detected version, restarting server to apply correct configuration."); 35 | 36 | _javaServer.ForceKillServer(); 37 | _serverConfiguration.GetSettingsProp(ServerPropertyKeys.ServerVersion).SetValue(versionString); 38 | _configurator.LoadServerConfigurations().Wait(); 39 | _configurator.SaveServerConfiguration(_serverConfiguration); 40 | _javaServer.ServerStart().Wait(); 41 | } 42 | if (_serverConfiguration.GetServerVersion() != versionString) { 43 | if (_serverConfiguration.GetSettingsProp(ServerPropertyKeys.AutoDeployUpdates).GetBoolValue()) { 44 | _logger.AppendLine($"Server {_serverConfiguration.GetServerName()} decected incorrect or out of date version! Replacing build..."); 45 | _javaServer.PerformOfflineServerTask(() => { 46 | _javaServer.ForceKillServer(); 47 | _serverConfiguration.GetUpdater().ReplaceBuild(_serverConfiguration).Wait(); 48 | }); 49 | } else { 50 | _logger.AppendLine($"Server {_serverConfiguration.GetServerName()} is out of date, Enable AutoDeployUpdates option to update to latest!"); 51 | } 52 | } 53 | 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /MinecraftService/Client/Properties/Resources.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 MinecraftService.Client.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MinecraftService.Client.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /BdsVersionCheckTest.ps1: -------------------------------------------------------------------------------- 1 | class BedrockInfo { 2 | [string]$version; 3 | [string]$winurl; 4 | [string]$linurl; 5 | [PropInfoEntry[]]$proplist; 6 | } 7 | 8 | class PropInfoEntry { 9 | [string]$Key; 10 | [string]$Value; 11 | } 12 | 13 | $ConnectionHeaders = @{ 14 | "Accept"="text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"; 15 | "Accept-Encoding"="gzip, deflate, br, zstd"; 16 | "Accept-Language"="en-US,en;q=0.9"; 17 | "User-Agent"="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" 18 | }; 19 | [Net.ServicePointManager]::SecurityProtocol = "tls12", "tls11"; 20 | $reply = Invoke-WebRequest -UseBasicParsing -Headers $ConnectionHeaders -Uri "https://net-secondary.web.minecraft-services.net/api/v1.0/download/links"; 21 | $versionJson = $reply.Content | ConvertFrom-Json; 22 | $bedrockWinUrl = ""; 23 | $bedrockLinuxUrl = ""; 24 | foreach ($entry in $versionJson.result.links) { 25 | if($entry.downloadType -eq "serverBedrockWindows") { 26 | $bedrockWinUrl = $entry.downloadUrl; 27 | } 28 | if($entry.downloadType -eq "serverBedrockLinux") { 29 | $bedrockLinuxUrl = $entry.downloadUrl; 30 | } 31 | } 32 | $propMftFile = get-content 'MMS_Files\\bedrock_version_prop_manifest.json'; 33 | if ($bedrockWinUrl -match 'bedrock-server-(?.+)\.zip') { 34 | $version = $Matches.version; 35 | if ($propMftFile) { 36 | $propMftJson = $propMftFile | ConvertFrom-Json; 37 | $latestVer = $propMftJson | Select-Object -Last 1; 38 | $entryVer = $latestVer.version; 39 | if($entryVer -ne $version) { 40 | mkdir 'BedrockTemp'; 41 | $curDir = Get-Location; 42 | $zipPath = $curDir.Path + '\\BedrockTemp\\Server.zip' 43 | Invoke-WebRequest -UseBasicParsing -Headers $ConnectionHeaders -Uri $latestVer.winurl -OutFile $zipPath; 44 | $zipStream = New-Object IO.FileStream $zipPath, 'Open', 'Read', 'Read'; 45 | $zipArchive = New-Object IO.Compression.ZipArchive $zipStream, "Read"; 46 | $propList = @(); 47 | foreach ($file in $zipArchive.Entries) { 48 | if ($file.Name -eq 'server.properties') { 49 | $fileStream = $file.Open(); 50 | $reader = New-Object IO.StreamReader $fileStream; 51 | while (($line = $reader.ReadLine()) -ne $null) { 52 | if ($line -ne "" -And !$line.StartsWith('#')) { 53 | $kvp = $line.Split('='); 54 | if ($kvp.Length -lt 2) { 55 | $temp = [string[]]; 56 | $temp[0] = $kvp[0]; 57 | $temp[1] = ""; 58 | $kvp = $temp; 59 | } 60 | $newProp = [PropInfoEntry]@{ 61 | Key = $kvp[0]; 62 | Value = $kvp[1]; 63 | } 64 | $propList += $newProp; 65 | } 66 | } 67 | } 68 | } 69 | $zipArchive.Dispose(); 70 | $zipStream.Close(); 71 | $newListEntry = [BedrockInfo]@{ 72 | version=$version; 73 | winurl=$bedrockWinUrl; 74 | linurl=$bedrockLinuxUrl; 75 | proplist= $propList; 76 | } 77 | $propMftJson += $newListEntry; 78 | $propMftJson | ConvertTo-Json -depth 100 | Out-File "MMS_Files\\bedrock_version_prop_manifest.json"; 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /MinecraftService/Service/Program.cs: -------------------------------------------------------------------------------- 1 | // This application entry point is based on ASP.NET Core new project templates and is included 2 | // as a starting point for app host configuration. 3 | // This file may need updated according to the specific scenario of the application being upgraded. 4 | // For more information on ASP.NET Core hosting, see https://docs.microsoft.com/aspnet/core/fundamentals/host/web-host 5 | 6 | global using Microsoft.Extensions.DependencyInjection; 7 | global using Microsoft.Extensions.Hosting; 8 | global using MinecraftService.Service.Core.Interfaces; 9 | global using MinecraftService.Service.Management; 10 | global using MinecraftService.Service.Networking; 11 | global using MinecraftService.Shared.Classes; 12 | global using MinecraftService.Shared.Interfaces; 13 | global using MinecraftService.Shared.Utilities; 14 | global using System; 15 | global using System.Collections.Generic; 16 | global using System.Diagnostics; 17 | global using System.IO; 18 | global using System.Linq; 19 | global using System.Reflection; 20 | global using System.Threading; 21 | global using System.Threading.Tasks; 22 | global using Topshelf; 23 | using MinecraftService.Service.Core; 24 | using MinecraftService.Service.Networking.Interfaces; 25 | using MinecraftService.Shared.Classes.Server; 26 | using MinecraftService.Shared.Classes.Server.Updaters; 27 | using MinecraftService.Shared.Classes.Service; 28 | using MinecraftService.Shared.Classes.Service.Configuration; 29 | using MinecraftService.Shared.Classes.Service.Core; 30 | 31 | namespace MinecraftService.Service 32 | { 33 | public class Program { 34 | public static bool IsExiting = false; 35 | private static readonly string _declaredType = "Service"; 36 | private static bool _isDebugEnabled = false; 37 | private static bool _shouldStartService = true; 38 | public static void Main(string[] args) { 39 | if (args.Length > 0) { 40 | _isDebugEnabled = args[0].ToLower() == "--debug"; 41 | } 42 | CreateHostBuilder(args).Build().Run(); 43 | } 44 | 45 | public static IHostBuilder CreateHostBuilder(string[] args) => 46 | Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args) 47 | .ConfigureServices((hostContext, services) => { 48 | ProcessInfo processInfo = new ProcessInfo(_declaredType, Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), Process.GetCurrentProcess().Id, _isDebugEnabled, _shouldStartService); 49 | SharedStringBase.SetWorkingDirectory(processInfo); 50 | services.AddHostedService() 51 | .AddSingleton(processInfo) 52 | .AddTransient() 53 | .AddTransient() 54 | .AddSingleton() 55 | .AddSingleton() 56 | .AddSingleton() 57 | .AddSingleton() 58 | .AddSingleton() 59 | .AddSingleton(); 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/ClientConfigForm.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Windows.Forms; 8 | using MinecraftService.Client.Management; 9 | using MinecraftService.Shared.Classes.Service.Configuration; 10 | using MinecraftService.Shared.Interfaces; 11 | 12 | namespace MinecraftService.Client.Forms { 13 | public partial class ClientConfigForm : Form { 14 | private readonly List _clientConfigs; 15 | private readonly ConfigManager _configManager; 16 | public ClientConfigForm(ConfigManager configManager) { 17 | InitializeComponent(); 18 | _configManager = configManager; 19 | _clientConfigs = _configManager.HostConnectList; 20 | scrollLockCheckbox.Checked = _configManager.DefaultScrollLock; 21 | displayTimestampCheckbox.Checked = _configManager.DisplayTimestamps; 22 | debugNetworkCheckbox.Checked = _configManager.DebugNetworkOutput; 23 | if (!string.IsNullOrEmpty(_configManager.NBTStudioPath)) { 24 | nbtPathLabel.Text = $"NBT Studio path: {_configManager.NBTStudioPath}"; 25 | } 26 | foreach (ClientSideServiceConfiguration config in _clientConfigs) { 27 | serverGridView.Rows.Add(new string[3] { config.GetHostName(), config.GetAddress(), config.GetPort() }); 28 | } 29 | } 30 | 31 | public void SimulateTests() { 32 | nbtButton.PerformClick(); 33 | } 34 | 35 | private void nbtButton_Click(object sender, EventArgs e) { 36 | using (OpenFileDialog fileDialog = new()) { 37 | fileDialog.Filter = "EXE Files|*.exe"; 38 | fileDialog.FileName = "NbtStudio.exe"; 39 | fileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 40 | if (fileDialog.ShowDialog() == DialogResult.OK) { 41 | _configManager.NBTStudioPath = fileDialog.FileName; 42 | nbtPathLabel.Text = $"NBT Studio path: {_configManager.NBTStudioPath}"; 43 | } 44 | } 45 | } 46 | 47 | private void saveBtn_Click(object sender, EventArgs e) { 48 | List newConfigs = new(); 49 | foreach (DataGridViewRow row in serverGridView.Rows) { 50 | if (!string.IsNullOrEmpty((string)row.Cells[0].Value)) { 51 | newConfigs.Add(new ClientSideServiceConfiguration((string)row.Cells[0].Value, (string)row.Cells[1].Value, (string)row.Cells[2].Value)); 52 | } 53 | } 54 | _configManager.HostConnectList = newConfigs; 55 | _configManager.DefaultScrollLock = scrollLockCheckbox.Checked; 56 | _configManager.DisplayTimestamps = displayTimestampCheckbox.Checked; 57 | _configManager.DebugNetworkOutput = debugNetworkCheckbox.Checked; 58 | _configManager.SaveConfigFile(); 59 | DialogResult = DialogResult.OK; 60 | Close(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/PropEditorForm.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | // See the LICENSE file in the project root for more information. 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Windows.Forms; 8 | using MinecraftService.Shared.Classes.Service.Core; 9 | 10 | namespace MinecraftService.Client.Forms { 11 | public partial class PropEditorForm : Form { 12 | readonly DataGridView dataGrid; 13 | public List workingProps; 14 | public List startCmds; 15 | public string RollbackFolderName = ""; 16 | 17 | public PropEditorForm() { 18 | InitializeComponent(); 19 | dataGrid = gridView; 20 | } 21 | 22 | public void PopulateBoxes(List propList) { 23 | int index = 0; 24 | workingProps = propList; 25 | this.Text = "Properties Editor"; 26 | foreach (Property prop in workingProps) { 27 | dataGrid.Rows.Add(new string[2] { prop.KeyName, prop.StringValue }); 28 | if (prop.KeyName == "server-name" || prop.KeyName == "server-port" || prop.KeyName == "server-portv6") { 29 | dataGrid.Rows[index].ReadOnly = true; 30 | dataGrid.Rows[index].DefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(225, 225, 225); 31 | } 32 | index++; 33 | } 34 | gridView.AllowUserToAddRows = false; 35 | } 36 | 37 | public void PopulateStartCmds(List list) { 38 | this.Text = "Start Command Editor"; 39 | startCmds = list; 40 | gridView.Columns.RemoveAt(0); 41 | gridView.AllowUserToDeleteRows = true; 42 | foreach (StartCmdEntry entry in startCmds) { 43 | dataGrid.Rows.Add(new string[1] { entry.Command }); 44 | } 45 | } 46 | 47 | private void CancelBtn_Click(object sender, EventArgs e) { 48 | Close(); 49 | Dispose(); 50 | } 51 | 52 | private void SaveBtn_Click(object sender, EventArgs e) { 53 | startCmds = new List(); 54 | foreach (DataGridViewRow row in dataGrid.Rows) { 55 | if (workingProps != null) { 56 | foreach (Property prop in workingProps) { 57 | if ((string)row.Cells[0].Value == prop.KeyName) { 58 | prop.StringValue = (string)row.Cells[1].Value; 59 | } 60 | } 61 | } else { 62 | if ((string)row.Cells[0].Value != null) 63 | startCmds.Add(new StartCmdEntry((string)row.Cells[0].Value)); 64 | } 65 | 66 | } 67 | DialogResult = DialogResult.OK; 68 | Close(); 69 | } 70 | 71 | private void gridView_NewRowNeeded(object sender, DataGridViewRowEventArgs e) { 72 | DataGridViewRow focusedRow = gridView.CurrentRow; 73 | focusedRow.Cells[0].Value = "Cmd:"; 74 | gridView.Refresh(); 75 | } 76 | 77 | internal void PopulateBoxes(object p) { 78 | throw new NotImplementedException(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /MinecraftService/MinecraftService.Shared/Classes/Networking/Message.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Security.Cryptography.X509Certificates; 6 | using System.Text; 7 | using System.Text.Json; 8 | using System.Threading.Tasks; 9 | 10 | namespace MinecraftService.Shared.Classes.Networking { 11 | public struct Message : IEquatable { 12 | public byte[] Data { get; set; } 13 | public byte ServerIndex { get; set; } 14 | public MessageTypes Type { get; set; } 15 | public MessageFlags Flag { get; set; } 16 | 17 | public Message() { 18 | Data = []; 19 | ServerIndex = 0; 20 | } 21 | 22 | public Message(byte[] data) { 23 | string dataString = ""; 24 | try { 25 | dataString = Encoding.UTF8.GetString(data); 26 | this = JsonConvert.DeserializeObject(dataString); 27 | } catch (JsonReaderException jre) { 28 | throw new Exception($"Json failure: line {jre.LineNumber}, pos {jre.LinePosition}. Message: {jre.Message}\r\nData: {dataString}"); 29 | } catch (Exception ex) { 30 | throw new Exception($"Error creating message from byte array: {ex.Message}"); 31 | } 32 | } 33 | 34 | public Message(byte[] data, byte serverIndex, MessageTypes messageType) { 35 | Data = data; 36 | ServerIndex = serverIndex; 37 | Type = messageType; 38 | } 39 | 40 | public byte[] GetMessageBytes() { 41 | byte[] jsonData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(this)); 42 | byte[] packetData = new byte[jsonData.Length + sizeof(int)]; 43 | Buffer.BlockCopy(BitConverter.GetBytes(jsonData.Length), 0, packetData, 0, sizeof(int)); 44 | Buffer.BlockCopy(jsonData, 0, packetData, sizeof(int), jsonData.Length); 45 | return packetData; 46 | } 47 | 48 | public readonly string GetDataString() => Encoding.UTF8.GetString(Data); 49 | 50 | public static Message Empty(MessageTypes type) => new() { Type = type }; 51 | public static Message Empty() => new(); 52 | 53 | public static readonly Message EmptyUICallback = new() { Type = MessageTypes.UICallback }; 54 | public static readonly Message Heartbeat = new() { Type = MessageTypes.Heartbeat }; 55 | public static readonly Message Connect = new() { Type = MessageTypes.Connect }; 56 | 57 | public override bool Equals(object obj) { 58 | return obj is Message message && Equals(message); 59 | } 60 | 61 | public bool Equals(Message other) { 62 | return EqualityComparer.Default.Equals(Data, other.Data) && 63 | ServerIndex == other.ServerIndex && 64 | Type == other.Type && 65 | Flag == other.Flag; 66 | } 67 | 68 | public override int GetHashCode() { 69 | return HashCode.Combine(Data, ServerIndex, Type, Flag); 70 | } 71 | 72 | public static bool operator ==(Message left, Message right) { 73 | return left.Equals(right); 74 | } 75 | 76 | public static bool operator !=(Message left, Message right) { 77 | return !(left == right); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategies/PackFile.cs: -------------------------------------------------------------------------------- 1 | using MinecraftService.Service.Networking.Interfaces; 2 | using MinecraftService.Shared.Classes.Networking; 3 | using MinecraftService.Shared.Classes.Service; 4 | using MinecraftService.Shared.Classes.Service.Configuration; 5 | using MinecraftService.Shared.Classes.Service.Core; 6 | using MinecraftService.Shared.PackParser; 7 | using static MinecraftService.Shared.Classes.Service.Core.SharedStringBase; 8 | 9 | namespace MinecraftService.Service.Networking.NetworkStrategies 10 | { 11 | public class PackFile(ServiceConfigurator serviceConfiguration, MmsLogger logger) : IMessageParser { 12 | 13 | public Message ParseMessage(Message message) { 14 | Progress progress = new Progress((progress) => { 15 | string prog = string.Format("{0:N2}", progress.Progress); 16 | logger.AppendLine($"Extracting pack contents... {prog}% completed."); 17 | }); 18 | MinecraftPackParser archiveParser = new(logger, progress); 19 | archiveParser.ProcessServerData(message.Data, () => { 20 | foreach (MinecraftPackContainer container in archiveParser.FoundPacks) { 21 | IServerConfiguration server = serviceConfiguration.GetServerInfoByIndex(message.ServerIndex); 22 | string serverPath = server.GetSettingsProp(ServerPropertyKeys.ServerPath).ToString(); 23 | string levelName = server.GetProp(MmsDependServerPropKeys.LevelName).ToString(); 24 | string filePath; 25 | 26 | if (container.ManifestType == MinecraftPackTypeStrings[MinecraftPackTypes.WorldPack]) { 27 | FileUtilities.CopyFolderTree(new DirectoryInfo(container.PackContentLocation), new DirectoryInfo(GetServerDirectory(ServerDirectoryKeys.ServerWorldDir_LevelName, serverPath, container.FolderName))); 28 | } 29 | if (container.ManifestType == MinecraftPackTypeStrings[MinecraftPackTypes.Behavior]) { 30 | filePath = GetServerFilePath(ServerFileNameKeys.WorldBehaviorPacks, server, levelName); 31 | if (MinecraftFileUtilities.UpdateWorldPackFile(filePath, container.JsonManifest)) { 32 | FileUtilities.CopyFolderTree(new DirectoryInfo(container.PackContentLocation), new DirectoryInfo($"{GetServerDirectory(ServerDirectoryKeys.BehaviorPacksDir_LevelName, serverPath, levelName)}\\{container.FolderName}")); 33 | } 34 | } 35 | if (container.ManifestType == MinecraftPackTypeStrings[MinecraftPackTypes.Resource]) { 36 | filePath = GetServerFilePath(ServerFileNameKeys.WorldResourcePacks, server, levelName); 37 | if (MinecraftFileUtilities.UpdateWorldPackFile(filePath, container.JsonManifest)) { 38 | FileUtilities.CopyFolderTree(new DirectoryInfo(container.PackContentLocation), new DirectoryInfo($"{GetServerDirectory(ServerDirectoryKeys.ResourcePacksDir_LevelName, serverPath, levelName)}\\{container.FolderName}")); 39 | } 40 | } 41 | logger.AppendLine($@"{container.GetFixedManifestType()} pack installed to server: {container.JsonManifest.header.name}."); 42 | } 43 | }); 44 | return Message.EmptyUICallback; 45 | } 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /MinecraftService/Client/Forms/ClientConfigForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | 61 | True 62 | 63 | 64 | True 65 | 66 | 67 | True 68 | 69 | -------------------------------------------------------------------------------- /MinecraftService/Service/Networking/NetworkStrategyLookup.cs: -------------------------------------------------------------------------------- 1 | 2 | using MinecraftService.Service.Core; 3 | using MinecraftService.Service.Networking.Interfaces; 4 | using MinecraftService.Service.Networking.NetworkStrategies; 5 | using MinecraftService.Shared.Classes.Networking; 6 | using MinecraftService.Shared.Classes.Server; 7 | using MinecraftService.Shared.Classes.Service; 8 | using MinecraftService.Shared.Classes.Service.Configuration; 9 | using MinecraftService.Shared.Classes.Service.Core; 10 | 11 | namespace MinecraftService.Service.Networking 12 | { 13 | public class NetworkStrategyLookup { 14 | private readonly Dictionary _standardMessageLookup; 15 | private readonly Dictionary _flaggedMessageLookup; 16 | 17 | public NetworkStrategyLookup(ITCPObject listener, MmsService service, MmsLogger logger, UserConfigManager configurator, ServiceConfigurator serviceConfiguration, ProcessInfo processInfo, FileUtilities fileUtils) { 18 | _standardMessageLookup = new Dictionary() 19 | { 20 | {MessageTypes.Connect, new Connect(serviceConfiguration) }, 21 | {MessageTypes.AddNewServer, new AddNewServer(logger, processInfo, configurator, serviceConfiguration, service) }, 22 | {MessageTypes.RemoveServer, new RemoveServer(configurator, serviceConfiguration, service) }, 23 | {MessageTypes.Command, new ServerCommand(service, logger) }, 24 | {MessageTypes.Restart, new ServerRestart(service) }, 25 | {MessageTypes.StartStop, new StartStopServer(service) }, 26 | {MessageTypes.ServerStatusRequest, new ServerStatusRequest(service) }, 27 | {MessageTypes.Backup, new ServerBackup(service) }, 28 | {MessageTypes.BackupAll, new ServerBackupAll(service) }, 29 | {MessageTypes.EnumBackups, new EnumBackups(configurator) }, 30 | {MessageTypes.BackupRollback, new BackupRollback(service) }, 31 | {MessageTypes.DelBackups, new DeleteBackups(logger, serviceConfiguration) }, 32 | {MessageTypes.PropUpdate, new ServerPropUpdate(logger, configurator, serviceConfiguration, service) }, 33 | {MessageTypes.StartCmdUpdate, new StartCmdUpdate(configurator, serviceConfiguration) }, 34 | {MessageTypes.ConsoleLogUpdate, new ConsoleLogUpdate(logger, serviceConfiguration, service) }, 35 | {MessageTypes.VersionListRequest, new VersionListRequest(logger, serviceConfiguration) }, 36 | {MessageTypes.PackList, new PackList(processInfo, serviceConfiguration, logger) }, 37 | {MessageTypes.PackFile, new PackFile(serviceConfiguration, logger) }, 38 | {MessageTypes.RemovePack, new RemovePack(serviceConfiguration, logger) }, 39 | {MessageTypes.CheckUpdates, new CheckUpdates(service) }, 40 | {MessageTypes.PlayersRequest, new PlayerRequest(service) }, 41 | {MessageTypes.PlayersUpdate, new PlayersUpdate(configurator, serviceConfiguration, service) }, 42 | {MessageTypes.LevelEditRequest, new LevelEditRequest(serviceConfiguration) }, 43 | {MessageTypes.LevelEditFile, new LevelEditFile(serviceConfiguration, service, logger) }, 44 | {MessageTypes.ExportFile, new ExportFileRequest(configurator, service, serviceConfiguration, logger) }, 45 | }; 46 | listener.SetStrategies(_standardMessageLookup); 47 | } 48 | } 49 | } 50 | --------------------------------------------------------------------------------