diff --git a/minecraft-launcher-client/Launcher.LaunchGame.cs b/minecraft-launcher-client/Launcher.LaunchGame.cs index 96b71ab..0b3616b 100644 --- a/minecraft-launcher-client/Launcher.LaunchGame.cs +++ b/minecraft-launcher-client/Launcher.LaunchGame.cs @@ -4,66 +4,64 @@ namespace launcher_client; internal static partial class Launcher { - private static void LaunchGame(string javapath, string username, string uuid, - int maxmemory, int width, int height) => - gameProcess = Process.Start($"{javapath}\\javaw.exe ", - "-Djava.net.preferIPv4Stack=true \"-Dos.name=Windows 10\" -Dos.version=10.0 " + - $"-Xmn256M -Xmx{maxmemory}M -Djava.library.path=version\\natives -cp " + - "libraries\\net\\minecraftforge\\forge\\1.12.2-14.23.5.2855\\forge-1.12.2-14.23.5.2855.jar;" + - "libraries\\org\\ow2\\asm\\asm-debug-all\\5.2\\asm-debug-all-5.2.jar;" + - "libraries\\net\\minecraft\\launchwrapper\\1.12\\launchwrapper-1.12.jar;" + - "libraries\\org\\jline\\jline\\3.5.1\\jline-3.5.1.jar;" + - "libraries\\com\\typesafe\\akka\\akka-actor_2.11\\2.3.3\\akka-actor_2.11-2.3.3.jar;" + - "libraries\\com\\typesafe\\config\\1.2.1\\config-1.2.1.jar;" + - "libraries\\org\\scala-lang\\scala-actors-migration_2.11\\1.1.0\\scala-actors-migration_2.11-1.1.0.jar;" + - "libraries\\org\\scala-lang\\scala-compiler\\2.11.1\\scala-compiler-2.11.1.jar;" + - "libraries\\org\\scala-lang\\plugins\\scala-continuations-library_2.11\\1.0.2_mc\\scala-continuations-library_2.11-1.0.2_mc.jar;l" + - "ibraries\\org\\scala-lang\\plugins\\scala-continuations-plugin_2.11.1\\1.0.2_mc\\scala-continuations-plugin_2.11.1-1.0.2_mc.jar;" + - "libraries\\org\\scala-lang\\scala-library\\2.11.1\\scala-library-2.11.1.jar;" + - "libraries\\org\\scala-lang\\scala-parser-combinators_2.11\\1.0.1\\scala-parser-combinators_2.11-1.0.1.jar;" + - "libraries\\org\\scala-lang\\scala-reflect\\2.11.1\\scala-reflect-2.11.1.jar;" + - "libraries\\org\\scala-lang\\scala-swing_2.11\\1.0.1\\scala-swing_2.11-1.0.1.jar;" + - "libraries\\org\\scala-lang\\scala-xml_2.11\\1.0.2\\scala-xml_2.11-1.0.2.jar;" + - "libraries\\lzma\\lzma\\0.0.1\\lzma-0.0.1.jar;" + - "libraries\\java3d\\vecmath\\1.5.2\\vecmath-1.5.2.jar;" + - "libraries\\net\\sf\\trove4j\\trove4j\\3.0.3\\trove4j-3.0.3.jar;" + - "libraries\\org\\apache\\maven\\maven-artifact\\3.5.3\\maven-artifact-3.5.3.jar;" + - "libraries\\net\\sf\\jopt-simple\\jopt-simple\\5.0.3\\jopt-simple-5.0.3.jar;" + - "libraries\\oshi-project\\oshi-core\\1.1\\oshi-core-1.1.jar;" + - "libraries\\net\\java\\dev\\jna\\jna\\4.4.0\\jna-4.4.0.jar;" + - "libraries\\net\\java\\dev\\jna\\platform\\3.4.0\\platform-3.4.0.jar;" + - "libraries\\com\\ibm\\icu\\icu4j-core-mojang\\51.2\\icu4j-core-mojang-51.2.jar;" + - "libraries\\net\\sf\\jopt-simple\\jopt-simple\\5.0.3\\jopt-simple-5.0.3.jar;" + - "libraries\\com\\paulscode\\codecjorbis\\20101023\\codecjorbis-20101023.jar;" + - "libraries\\com\\paulscode\\codecwav\\20101023\\codecwav-20101023.jar;" + - "libraries\\com\\paulscode\\libraryjavasound\\20101123\\libraryjavasound-20101123.jar;" + - "libraries\\com\\paulscode\\librarylwjglopenal\\20100824\\librarylwjglopenal-20100824.jar;" + - "libraries\\com\\paulscode\\soundsystem\\20120107\\soundsystem-20120107.jar;" + - "libraries\\io\\netty\\netty-all\\4.1.9.Final\\netty-all-4.1.9.Final.jar;" + - "libraries\\com\\google\\guava\\guava\\21.0\\guava-21.0.jar;" + - "libraries\\org\\apache\\commons\\commons-lang3\\3.5\\commons-lang3-3.5.jar;" + - "libraries\\commons-io\\commons-io\\2.5\\commons-io-2.5.jar;" + - "libraries\\commons-codec\\commons-codec\\1.10\\commons-codec-1.10.jar;" + - "libraries\\net\\java\\jinput\\jinput\\2.0.5\\jinput-2.0.5.jar;" + - "libraries\\net\\java\\jutils\\jutils\\1.0.0\\jutils-1.0.0.jar;" + - "libraries\\com\\google\\code\\gson\\gson\\2.8.0\\gson-2.8.0.jar;" + - "libraries\\com\\mojang\\authlib\\1.5.25\\authlib-1.5.25.jar;" + - "libraries\\com\\mojang\\realms\\1.10.22\\realms-1.10.22.jar;" + - "libraries\\org\\apache\\commons\\commons-compress\\1.8.1\\commons-compress-1.8.1.jar;" + - "libraries\\org\\apache\\httpcomponents\\httpclient\\4.3.3\\httpclient-4.3.3.jar;" + - "libraries\\commons-logging\\commons-logging\\1.1.3\\commons-logging-1.1.3.jar;" + - "libraries\\org\\apache\\httpcomponents\\httpcore\\4.3.2\\httpcore-4.3.2.jar;" + - "libraries\\it\\unimi\\dsi\\fastutil\\7.1.0\\fastutil-7.1.0.jar;" + - "libraries\\org\\apache\\logging\\log4j\\log4j-api\\2.8.1\\log4j-api-2.8.1.jar;" + - "libraries\\org\\apache\\logging\\log4j\\log4j-core\\2.8.1\\log4j-core-2.8.1.jar;" + - "libraries\\org\\lwjgl\\lwjgl\\lwjgl\\2.9.4-nightly-20150209\\lwjgl-2.9.4-nightly-20150209.jar;" + - "libraries\\org\\lwjgl\\lwjgl\\lwjgl_util\\2.9.4-nightly-20150209\\lwjgl_util-2.9.4-nightly-20150209.jar;" + - "libraries\\com\\mojang\\text2speech\\1.10.3\\text2speech-1.10.3.jar;" + - "version\\1.12.2-forge-14.23.5.2855.jar " + - "-Dminecraft.applet.TargetDirectory=.\\ " + - "-Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true " + - "--gameDir .\\ --assetsDir assets --assetIndex 1.12 " + - $"net.minecraft.launchwrapper.Launch --username {username} --version 1.12.2-forge-14.23.5.2855 " + - $"--uuid {uuid} --accessToken null --userType mojang --tweakClass net.minecraftforge.fml.common.launcher.FMLTweaker " + - $"--versionType Forge --width {width} --height {height}"); + static string ConstructGameOptions(string username, string uuid, int maxmemory, int width, int height) + => @"-Djava.net.preferIPv4Stack=true ""-Dos.name=Windows 10"" -Dos.version=10.0 " + + $@"-Xmn256M -Xmx{maxmemory}M -Djava.library.path=version\natives -cp " + + @"libraries\net\minecraftforge\forge\1.12.2-14.23.5.2855\forge-1.12.2-14.23.5.2855.jar;" + + @"libraries\org\ow2\asm\asm-debug-all\5.2\asm-debug-all-5.2.jar;" + + @"libraries\net\minecraft\launchwrapper\1.12\launchwrapper-1.12.jar;" + + @"libraries\org\jline\jline\3.5.1\jline-3.5.1.jar;" + + @"libraries\com\typesafe\akka\akka-actor_2.11\2.3.3\akka-actor_2.11-2.3.3.jar;" + + @"libraries\com\typesafe\config\1.2.1\config-1.2.1.jar;" + + @"libraries\org\scala-lang\scala-actors-migration_2.11\1.1.0\scala-actors-migration_2.11-1.1.0.jar;" + + @"libraries\org\scala-lang\scala-compiler\2.11.1\scala-compiler-2.11.1.jar;" + + @"libraries\org\scala-lang\plugins\scala-continuations-library_2.11\1.0.2_mc\scala-continuations-library_2.11-1.0.2_mc.jar;l" + + @"ibraries\org\scala-lang\plugins\scala-continuations-plugin_2.11.1\1.0.2_mc\scala-continuations-plugin_2.11.1-1.0.2_mc.jar;" + + @"libraries\org\scala-lang\scala-library\2.11.1\scala-library-2.11.1.jar;" + + @"libraries\org\scala-lang\scala-parser-combinators_2.11\1.0.1\scala-parser-combinators_2.11-1.0.1.jar;" + + @"libraries\org\scala-lang\scala-reflect\2.11.1\scala-reflect-2.11.1.jar;" + + @"libraries\org\scala-lang\scala-swing_2.11\1.0.1\scala-swing_2.11-1.0.1.jar;" + + @"libraries\org\scala-lang\scala-xml_2.11\1.0.2\scala-xml_2.11-1.0.2.jar;" + + @"libraries\lzma\lzma\0.0.1\lzma-0.0.1.jar;" + + @"libraries\java3d\vecmath\1.5.2\vecmath-1.5.2.jar;" + + @"libraries\net\sf\trove4j\trove4j\3.0.3\trove4j-3.0.3.jar;" + + @"libraries\org\apache\maven\maven-artifact\3.5.3\maven-artifact-3.5.3.jar;" + + @"libraries\net\sf\jopt-simple\jopt-simple\5.0.3\jopt-simple-5.0.3.jar;" + + @"libraries\oshi-project\oshi-core\1.1\oshi-core-1.1.jar;" + + @"libraries\net\java\dev\jna\jna\4.4.0\jna-4.4.0.jar;" + + @"libraries\net\java\dev\jna\platform\3.4.0\platform-3.4.0.jar;" + + @"libraries\com\ibm\icu\icu4j-core-mojang\51.2\icu4j-core-mojang-51.2.jar;" + + @"libraries\net\sf\jopt-simple\jopt-simple\5.0.3\jopt-simple-5.0.3.jar;" + + @"libraries\com\paulscode\codecjorbis\20101023\codecjorbis-20101023.jar;" + + @"libraries\com\paulscode\codecwav\20101023\codecwav-20101023.jar;" + + @"libraries\com\paulscode\libraryjavasound\20101123\libraryjavasound-20101123.jar;" + + @"libraries\com\paulscode\librarylwjglopenal\20100824\librarylwjglopenal-20100824.jar;" + + @"libraries\com\paulscode\soundsystem\20120107\soundsystem-20120107.jar;" + + @"libraries\io\netty\netty-all\4.1.9.Final\netty-all-4.1.9.Final.jar;" + + @"libraries\com\google\guava\guava\21.0\guava-21.0.jar;" + + @"libraries\org\apache\commons\commons-lang3\3.5\commons-lang3-3.5.jar;" + + @"libraries\commons-io\commons-io\2.5\commons-io-2.5.jar;" + + @"libraries\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;" + + @"libraries\net\java\jinput\jinput\2.0.5\jinput-2.0.5.jar;" + + @"libraries\net\java\jutils\jutils\1.0.0\jutils-1.0.0.jar;" + + @"libraries\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;" + + @"libraries\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;" + + @"libraries\com\mojang\realms\1.10.22\realms-1.10.22.jar;" + + @"libraries\org\apache\commons\commons-compress\1.8.1\commons-compress-1.8.1.jar;" + + @"libraries\org\apache\httpcomponents\httpclient\4.3.3\httpclient-4.3.3.jar;" + + @"libraries\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;" + + @"libraries\org\apache\httpcomponents\httpcore\4.3.2\httpcore-4.3.2.jar;" + + @"libraries\it\unimi\dsi\fastutil\7.1.0\fastutil-7.1.0.jar;" + + @"libraries\org\apache\logging\log4j\log4j-api\2.8.1\log4j-api-2.8.1.jar;" + + @"libraries\org\apache\logging\log4j\log4j-core\2.8.1\log4j-core-2.8.1.jar;" + + @"libraries\org\lwjgl\lwjgl\lwjgl\2.9.4-nightly-20150209\lwjgl-2.9.4-nightly-20150209.jar;" + + @"libraries\org\lwjgl\lwjgl\lwjgl_util\2.9.4-nightly-20150209\lwjgl_util-2.9.4-nightly-20150209.jar;" + + @"libraries\com\mojang\text2speech\1.10.3\text2speech-1.10.3.jar;" + + @"version\1.12.2-forge-14.23.5.2855.jar " + + @"-Dminecraft.applet.TargetDirectory=.\ " + + "-Dfml.ignoreInvalidMinecraftCertificates=true -Dfml.ignorePatchDiscrepancies=true " + + $"net.minecraft.launchwrapper.Launch --username {username} --version 1.12.2-forge-14.23.5.2855 " + + @"--gameDir .\ --assetsDir assets --assetIndex 1.12 " + + $"--uuid {uuid} --accessToken null --userType mojang --tweakClass net.minecraftforge.fml.common.launcher.FMLTweaker " + + $"--versionType Forge --width {width} --height {height}"; } \ No newline at end of file diff --git a/minecraft-launcher-client/Launcher.cs b/minecraft-launcher-client/Launcher.cs index b365b81..2f159d5 100644 --- a/minecraft-launcher-client/Launcher.cs +++ b/minecraft-launcher-client/Launcher.cs @@ -4,7 +4,7 @@ using System.Dynamic; using System.Linq; using System.Net; using System.Net.Sockets; -using System.Reflection; +using System.Security.Cryptography; using System.Text; using System.Threading; using DTLib.Console; @@ -12,6 +12,7 @@ using DTLib.Dtsod; using DTLib.Extensions; using DTLib.Logging; using DTLib.Network; +using DTLib.Filesystem; using Directory = DTLib.Filesystem.Directory; using File = DTLib.Filesystem.File; @@ -19,17 +20,15 @@ namespace launcher_client; internal static partial class Launcher { - private static FileLogger _fileLogger = new FileLogger("launcher-logs", "launcher_client"); + private static FileLogger _fileLogger = new("launcher-logs", "launcher_client"); private static ILogger logger = new CompositeLogger( _fileLogger, new ConsoleLogger()); - private static Socket mainSocket; + private static Socket mainSocket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); public static bool debug, offline, updated; - private static FSP FSP; + private static FSP FSP = new(mainSocket); private static dynamic tabs = new ExpandoObject(); - private static LauncherConfig config; - private static string configFileName = "launcher.dtsod"; - public static Process gameProcess; + private static LauncherConfig config = null!; private static void Main(string[] args) { @@ -39,15 +38,22 @@ internal static partial class Launcher Console.OutputEncoding = Encoding.UTF8; Console.InputEncoding = Encoding.UTF8; Console.CursorVisible = false; - DTLibInternalLogging.SetLogger(logger); - logger.LogInfo("Main", "launcher is starting"); + +#if DEBUG + debug = true; +#else if (args.Contains("debug")) debug = true; +#endif if (args.Contains("offline")) offline = true; if (args.Contains("updated")) updated = true; - config = !File.Exists(configFileName) - ? LauncherConfig.CreateDefault(configFileName) - : new LauncherConfig(configFileName); - + config = !File.Exists(LauncherConfig.ConfigFilePath) + ? LauncherConfig.CreateDefault() + : LauncherConfig.LoadFromFile(); + + DTLibInternalLogging.SetLogger(logger); + logger.DebugLogEnabled = debug; + logger.LogInfo("Main", "launcher is starting"); + // обновление лаунчера if (!updated && !offline) { @@ -63,21 +69,9 @@ internal static partial class Launcher } // если уже обновлён - var launcherAssembly = Assembly.GetExecutingAssembly(); - - // читает текст из файлов, добавленных в сборку в виде ресурсов - string ReadResource(string resource_path) - { - using var resStream = launcherAssembly.GetManifestResourceStream(resource_path) - ?? throw new Exception($"can't find resource <{resource_path}>"); - using var resourceStreamReader = - new System.IO.StreamReader(resStream, Encoding.UTF8); - return resourceStreamReader.ReadToEnd(); - } - - tabs.Login = ReadResource("launcher_client.gui.login.gui"); - tabs.Settings = ReadResource("launcher_client.gui.settings.gui"); - tabs.Exit = ReadResource("launcher_client.gui.exit.gui"); + tabs.Login = EmbeddedResources.ReadText("launcher_client.gui.login.gui"); + tabs.Settings = EmbeddedResources.ReadText("launcher_client.gui.settings.gui"); + tabs.Exit = EmbeddedResources.ReadText("launcher_client.gui.exit.gui"); tabs.Log = ""; tabs.Current = ""; string username = ""; @@ -145,8 +139,13 @@ internal static partial class Launcher // запуск майнкрафта logger.LogInfo("Main", "launching minecraft"); - LaunchGame(config.JavaPath, config.Username, config.UUID, - config.GameMemory, config.GameWindowWidth, config.GameWindowHeight); + string gameOptions = ConstructGameOptions(config.Username, + NameUUIDFromString("OfflinePlayer:" + config.Username), + config.GameMemory, + config.GameWindowWidth, + config.GameWindowHeight); + logger.LogDebug("LaunchGame", gameOptions); + var gameProcess = Process.Start($"{config.JavaPath}\\java.exe", gameOptions); gameProcess.WaitForExit(); logger.LogInfo("Main", "minecraft closed"); } @@ -192,14 +191,16 @@ internal static partial class Launcher // подключение серверу private static void ConnectToLauncherServer() { - if (mainSocket!=null && mainSocket.Connected) + if (mainSocket.Connected) { logger.LogInfo(nameof(ConnectToLauncherServer), "socket is connected already. disconnecting..."); mainSocket.Shutdown(SocketShutdown.Both); mainSocket.Close(); + mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + FSP = new FSP(mainSocket); + FSP.debug = debug; } - mainSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); while (true) try { @@ -215,13 +216,6 @@ internal static partial class Launcher Thread.Sleep(2000); } - FSP = new FSP(mainSocket); - FSP.debug = debug; - /*FSP.PackageRecieved += (size) => - { - Console.SetCursorPosition(0, 30); - logger.LogInfo(nameof(Connect), "downloading file... [", size.ToString(), "/", FSP.Filesize = ) - };*/ mainSocket.ReceiveTimeout = 2500; mainSocket.SendTimeout = 2500; mainSocket.GetAnswer("requesting user name"); @@ -285,4 +279,22 @@ internal static partial class Launcher } } } + + //minecraft player uuid explanation + //https://gist.github.com/CatDany/0e71ca7cd9b42a254e49/ + //java uuid generation in c# + //https://stackoverflow.com/questions/18021808/uuid-interop-with-c-sharp-code + public static string NameUUIDFromString(string input) + => NameUUIDFromBytes(Encoding.UTF8.GetBytes(input)); + + public static string NameUUIDFromBytes(byte[] input) + { + byte[] hash = MD5.HashData(input); + hash[6] &= 0x0f; + hash[6] |= 0x30; + hash[8] &= 0x3f; + hash[8] |= 0x80; + string hex = BitConverter.ToString(hash).Replace("-", string.Empty).ToLower(); + return hex.Insert(8, "-").Insert(13, "-").Insert(18, "-").Insert(23, "-"); + } } \ No newline at end of file diff --git a/minecraft-launcher-client/LauncherConfig.cs b/minecraft-launcher-client/LauncherConfig.cs index 67568f2..a0cb695 100644 --- a/minecraft-launcher-client/LauncherConfig.cs +++ b/minecraft-launcher-client/LauncherConfig.cs @@ -5,21 +5,19 @@ namespace launcher_client; public class LauncherConfig { + public static string ConfigFilePath = "launcher.dtsod"; + public int GameMemory = 3000; public int GameWindowHeight = 500; public int GameWindowWidth = 900; - public string JavaPath = "java\\bin"; + public string JavaPath = "jre\\bin"; public string ServerAddress = "127.0.0.1"; public int ServerPort = 25000; public string Username = ""; - public string UUID = ""; - - public string ConfigPath; + private LauncherConfig(){} - public LauncherConfig(){} - - public LauncherConfig(DtsodV23 dtsod, string configPath) + private LauncherConfig(DtsodV23 dtsod) { GameMemory = dtsod["gameMemory"]; GameWindowHeight = dtsod["gameWindowHeight"]; @@ -28,18 +26,12 @@ public class LauncherConfig ServerAddress = dtsod["serverAddress"]; ServerPort = dtsod["serverPort"]; Username = dtsod["username"]; - UUID = dtsod["uuid"]; - - ConfigPath = configPath; } - public LauncherConfig(string configPath) : - this(new DtsodV23(File.ReadAllText(configPath)), configPath) - { } + public static LauncherConfig LoadFromFile() => new(new DtsodV23(File.ReadAllText(ConfigFilePath))); - public DtsodV23 ToDtsod() - { - return new() + public DtsodV23 ToDtsod() => + new() { { "gameMemory", GameMemory }, { "gameWindowHeight", GameWindowHeight }, @@ -48,21 +40,16 @@ public class LauncherConfig { "serverAddress", ServerAddress }, { "serverPort", ServerPort }, { "username", Username }, - { "uuid", UUID } }; - } public void Save() { - File.WriteAllText(ConfigPath, ToDtsod().ToString()); + File.WriteAllText(ConfigFilePath, ToDtsod().ToString()); } - public static LauncherConfig CreateDefault(string configPath) + public static LauncherConfig CreateDefault() { - var c = new LauncherConfig - { - ConfigPath = configPath - }; + var c = new LauncherConfig(); c.Save(); return c; } diff --git a/minecraft-launcher-client/launcher-client.csproj b/minecraft-launcher-client/launcher-client.csproj index 91f6b27..0fd9642 100644 --- a/minecraft-launcher-client/launcher-client.csproj +++ b/minecraft-launcher-client/launcher-client.csproj @@ -2,7 +2,7 @@ net8.0 disable - disable + enable Exe launcher_client minecraft-launcher diff --git a/minecraft-launcher-client/publish.sh b/minecraft-launcher-client/publish.sh new file mode 100644 index 0000000..74cc897 --- /dev/null +++ b/minecraft-launcher-client/publish.sh @@ -0,0 +1,10 @@ +dotnet publish -c release -o bin/publish \ + --self-contained \ + -r win-x64 \ + -p:PublishSingleFile=true \ + -p:PublishTrimmed=true \ + -p:TrimMode=partial \ + -p:EnableCompressionInSingleFile=true \ + -p:OptimizationPreference=Size \ + -p:InvariantGlobalization=true \ + -p:DebugType=none diff --git a/minecraft-launcher-server/Server.cs b/minecraft-launcher-server/Server.cs index 96933aa..6341224 100644 --- a/minecraft-launcher-server/Server.cs +++ b/minecraft-launcher-server/Server.cs @@ -18,7 +18,7 @@ static class Server new FileLogger("logs","launcher_server"), new ConsoleLogger()); static readonly Socket mainSocket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - static DtsodV23 config; + static DtsodV23 config = null!; static bool debug; static object manifestLocker = new(); @@ -45,7 +45,7 @@ static class Server while (true) { var userSocket = mainSocket.Accept(); - var userThread = new Thread(obj => HandleUser((Socket)obj)); + var userThread = new Thread(obj => HandleUser((Socket)obj!)); userThread.Start(userSocket); } } diff --git a/minecraft-launcher-server/launcher-server.csproj b/minecraft-launcher-server/launcher-server.csproj index 2d820b0..f792dc0 100644 --- a/minecraft-launcher-server/launcher-server.csproj +++ b/minecraft-launcher-server/launcher-server.csproj @@ -2,7 +2,7 @@ net8.0 disable - disable + enable Exe launcher_server minecraft-launcher-server