//private static StreamWriter CommandLog; /*======================================= * This subroutine starts up the server * and then monitors the output. * =======================================*/ public static void Run(bool BridgeMode = false) { MinecraftServer.IsBridge = BridgeMode; MinecraftServer.Loaded = false; MinecraftServer.Stopping = false; Console.ForegroundColor = ConsoleColor.Cyan; Wrapper.InputTarget = Wrapper.Modes.Menu; Wrapper.WriteLine("Preparing Minecraft server..."); string SettingsFileName = "Settings.ini"; string SettingsFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, SettingsFileName); /*======================================= * Create a settings file with some default values if it doesn't exist. * These default values probably won't actually work, but it'll at least create the file. * =======================================*/ if (!File.Exists(SettingsFilePath)) { //ds = DefaultSettings IniFile ds = new IniFile(SettingsFileName); ds.Write("Version", "1.15.1", "Minecraft"); ds.Write("Arguments", "nogui", "Minecraft"); ds.Write("WorldSelectFile", "w.ini", "Minecraft"); ds.Write("Enable", "false", "Fabric"); ds.Write("Version", "0.4.0+build.121", "Fabric"); ds.Write("CommandLogFile", "CommandLog.txt", "Wrapper"); ds.Write("ServerPIDFile", "ServerPID", "Wrapper"); ds.Write("ServerFolder", @"E:\My_Minecraft_Expansion_2\Local Server", "Windows"); ds.Write("Executable", "java", "Java"); ds.Write("Type", "-d64 -server", "Java"); ds.Write("MemMax", "4G", "Java"); ds.Write("MemMin", "4G", "Java"); ds.Write("LogConfigFile", "log4j2.xml", "Java"); ds.Write("Arguments", "-XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseAdaptiveGCBoundary -XX:MaxGCPauseMillis=500 -XX:-UseGCOverheadLimit -XX:SurvivorRatio=12 -XX:NewRatio=4 -Xnoclassgc -XX:UseSSE=3", "Java"); } /*======================================= * Read the settings file to find the server path * =======================================*/ Wrapper.WriteLine("Reading wrapper settings file..."); IniFile s = new IniFile(SettingsFileName); Console.Title = "Wrapper." + Wrapper.Version + " MinecraftServer." + s.Read("Version", "Minecraft"); RootPath = s.Read("ServerFolder", "Windows") + '\\'; //Automatically accept the EULA because screw that File.WriteAllText(RootPath + "eula.txt", "eula=TRUE"); /*======================================= * Build a huge string of startup arguments from the settings file * =======================================*/ //string MinecraftJar = "minecraft_server." + s.Read("Version", "Minecraft") + ".jar"; string MinecraftJar = s.Read("JarName", "Minecraft"); string ArgumentsString = "-Xmx" + s.Read("MemMax", "Java") + " -Xms" + s.Read("MemMin", "Java") + " " + s.Read("Type", "Java") + " " + s.BigRead("Arguments", "Java") + " -jar \"" + RootPath; //if (Convert.ToBoolean(s.Read("Enable", "Fabric"))) if (MinecraftServer.IsFabric == true) { Console.Title = Console.Title + " FabricLoader." + s.Read("Version", "Fabric"); //string FabricJar = "fabric-loader-" + s.Read("Version", "Fabric") + ".jar"; string FabricJar = s.Read("FabricJarName", "Fabric"); ArgumentsString += FabricJar + "\" \"" + RootPath; File.WriteAllText(RootPath + "fabric-server-launcher.properties", "serverJar=" + MinecraftJar); } /*======================================= * Read the world select file and add stuff * from that to the end of the arguments string * =======================================*/ Wrapper.WriteLine("Configuring universe..."); string WorldSelectFilePath = RootPath + s.Read("WorldSelectFile", "Minecraft"); if (!File.Exists(WorldSelectFilePath)) { //dw = DefaultWorld IniFile dw = new IniFile(WorldSelectFilePath); dw.Write("Selected", "_default", "Universe"); dw.Write("Selected", "world", "World"); dw.Write("UniversesFolder", "universes", "Windows"); dw.Write("RelativePath", "true", "Windows"); } IniFile w = new IniFile(WorldSelectFilePath); //The folder path is processed this way since Minecraft prefers a relative path, //but the wrapper still needs to access the folder name itself with an absolute path. string UniversesFolder = w.Read("UniversesFolderName", "Windows"); if (Convert.ToBoolean(w.Read("RelativePath", "Windows"))) { UniversesFolder = ".\\" + UniversesFolder; } if (!UniversesFolder.EndsWith(@"\")) { UniversesFolder += @"\"; } ArgumentsString += MinecraftJar + "\" " + s.Read("Arguments", "Minecraft") + " --universe " + UniversesFolder + w.Read("Selected", "Universe") + " --world " + w.Read("Selected", "World"); /*======================================= * Set up server.properties * =======================================*/ Wrapper.WriteLine("Configuring server.properties..."); Dictionary <string, string> ServerProperties = new Dictionary <string, string>(); //This is just here in case a property manages to //not get specified in any other properties file. Util.MergeDictionaryWithStream(ServerProperties, "BeeMovieHentai", "ServerWrapperTest.default_server.properties"); //Loads the defaults for the whole server. Util.MergeDictionaryWithStream(ServerProperties, RootPath + s.Read("GlobalServerPropertiesFile", "Minecraft")); //Configures the generic template for UniversePath = RootPath + w.Read("UniversesFolderName", "Windows") + "\\" + w.Read("Selected", "Universe") + "\\"; Util.MergeDictionaryWithStream(ServerProperties, UniversePath + "universe.properties"); //Update the MotD to show what universe/world is loaded ServerProperties["motd"] += " | " + w.Read("Selected", "World"); //Check for a world properties file and load that too if it exists WorldPath = UniversePath + w.Read("Selected", "World") + "\\"; Util.MergeDictionaryWithStream(ServerProperties, WorldPath + "world.properties"); ServerProperties["level-name"] = w.Read("Selected", "World"); File.WriteAllLines(RootPath + "server.properties", Util.JoinDictionaryAsArray(ServerProperties, '=')); /*======================================= * Set the server icon * =======================================*/ Wrapper.WriteLine("Setting server icon..."); //These pragma statements whats-its just make Visual Studio shut up //about these if statements being empty. I did that on purpose as a way //of short circuiting the logic involved. #pragma warning disable CS0642 if (Util.SetIcon(WorldPath + "server-icon.png")) { ; } else if (Util.SetIcon(UniversePath + "server-icon.png")) { ; } else if (Util.SetIcon(RootPath + "global-icon.png")) { ; } else if (Util.CompareDefaultIcon(RootPath + "server-icon.png")) { ; } #pragma warning restore CS0642 else { using (Stream DefaultIconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ServerWrapperTest.default-icon.png")) { byte[] ByteBuffer = new byte[DefaultIconStream.Length]; using (MemoryStream memoryStream = new MemoryStream(ByteBuffer)) { DefaultIconStream.CopyTo(memoryStream); File.WriteAllBytes(RootPath + "server-icon.png", memoryStream.ToArray()); } } } /*======================================= * Setup some files related to logs and crap * =======================================*/ //Wrapper.WriteLine("Configuring custom logging..."); //MinecraftServer.CommandLog = new StreamWriter(RootPath + s.Read("CommandLogFile", "Wrapper"), true); Wrapper.WriteLine("Checking for previous unstopped servers..."); PIDFile = RootPath + s.Read("PIDFile", "Minecraft"); if (File.Exists(PIDFile)) { Int32 PreviousPID = Int32.Parse(File.ReadAllText(PIDFile)); try { using (Process PreviousServer = Process.GetProcessById(PreviousPID)) using (StreamWriter PreviousInput = PreviousServer.StandardInput) { PreviousInput.WriteLine("stop"); //Make sure the server process has stopped while (PreviousServer.HasExited == false) { ; } } Wrapper.WriteLine("Previous server stopped successfully"); } catch (Exception) { Wrapper.WriteLine("No previous server process running"); } File.Delete(PIDFile); } /*======================================= * Configure the server process before starting it * =======================================*/ Wrapper.WriteLine("Configuring server process..."); MinecraftServer.Process = new Process(); MinecraftServer.Process.StartInfo.FileName = s.Read("Executable", "Java"); MinecraftServer.Process.StartInfo.Arguments = ArgumentsString; MinecraftServer.Process.StartInfo.CreateNoWindow = false; MinecraftServer.Process.StartInfo.WorkingDirectory = RootPath; MinecraftServer.Process.StartInfo.ErrorDialog = false; MinecraftServer.Process.StartInfo.UseShellExecute = false; MinecraftServer.Process.StartInfo.RedirectStandardError = true; MinecraftServer.Process.StartInfo.RedirectStandardOutput = true; MinecraftServer.Process.StartInfo.RedirectStandardInput = true; /*======================================= * These are what read/print/process the server log. * They'll be run whenever the server process outputs text, * even while the code continues running below. * =======================================*/ Wrapper.WriteLine("Configuring console output..."); MinecraftServer.Process.OutputDataReceived += new DataReceivedEventHandler ( (sender, OutputText) => { if (string.IsNullOrWhiteSpace(OutputText.Data) == false) { Util.WriteToLog(OutputText.Data, MinecraftServer.OutputFormat); if (MinecraftServer.Stopping == true) { MinecraftServer.Loaded = !OutputText.Data.Contains("[Server thread/INFO]: Saved the game"); } //else if (MinecraftServer.Loaded) //{ // ProcessLog(OutputText.Data.Split(Util.RightBracketSplitter, StringSplitOptions.RemoveEmptyEntries)); //} else if (!MinecraftServer.Loaded) { MinecraftServer.Loaded = OutputText.Data.Contains("[Server thread/INFO]: Done ("); } } } ); MinecraftServer.Process.ErrorDataReceived += new DataReceivedEventHandler ( (sender, ErrorText) => { if (string.IsNullOrWhiteSpace(ErrorText.Data) == false) { Util.WriteToLog(ErrorText.Data, MinecraftServer.ErrorFormat); } } ); /*======================================= * Finally start the dang server process * =======================================*/ Wrapper.WriteLine("Starting Minecraft server..."); MinecraftServer.Process.Start(); File.WriteAllText(PIDFile, MinecraftServer.Process.Id.ToString()); //Redirect the input so that the code can send text MinecraftServer.Input = MinecraftServer.Process.StandardInput; //Start checking for output MinecraftServer.Process.BeginOutputReadLine(); MinecraftServer.Process.BeginErrorReadLine(); //Don't try to do anything else until the server finishes loading while (MinecraftServer.Loaded == false) { ; } Wrapper.WriteLine("Minecraft server loaded!"); MinecraftServer.Running = true; if (!MinecraftServer.IsBridge) { Wrapper.Command("InputMode 1"); Wrapper.WriteLine("Use \"wrapper InputMode 0\" to access Wrapper mode."); /*======================================= * This loop monitors for user input in the console * and sends it to the appropriate process * =======================================*/ string ConsoleInput = ""; do { try { //Get user input ConsoleInput = Console.In.ReadLine(); //If the user wasn't a squit if (string.IsNullOrWhiteSpace(ConsoleInput) == false) { switch (Wrapper.InputTarget) { //Default to wrapper case Wrapper.Modes.Menu: Wrapper.Command(ConsoleInput); break; //Default to Minecraft server case Wrapper.Modes.MinecraftServer: MinecraftServer.ProcessInput(ConsoleInput); break; default: Wrapper.InputTarget = Wrapper.Modes.Menu; throw new TrashMonkeyException("Invalid input mode! Defaulting to wrapper mode."); } } } catch (TrashMonkeyException e) //Handled errors { Wrapper.ErrorWriteLine(e.Message); } catch (Exception e) //Something actually broke errors { Util.PrintErrorInfo(e); } ConsoleInput = ""; } while (MinecraftServer.Running == true); //Exiting this loop should return to the menu } }
public static void Run() { FactorioServer.Run(true); MinecraftServer.Run(true); Wrapper.WriteLine("Preparing FMCBridge..."); string SettingsFileName = "Settings.ini"; string SettingsFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, SettingsFileName); IniFile s = new IniFile(SettingsFileName); RootPath = s.Read("ServerFolder", "Windows") + '\\'; /* * Load in the item mappings file. */ DualDictionary <String, String> itemMappings = new DualDictionary <String, String>(); Dictionary <String, double> minecraftRatios = new Dictionary <String, double>(); Dictionary <String, double> factorioRatios = new Dictionary <String, double>(); //Open up the file stream for the item mappings string itemMappingsPath = Path.Combine(RootPath, s.Read("MappingsFile", "FMCBridge")); FileStream fileStream = new FileStream(itemMappingsPath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read); StreamReader streamReader = new StreamReader(fileStream, Encoding.Default); //This loops needs to do a couple of things. //The first is it needs to read in the mappings into the DualDictionary for better translation of names. //The second it needs to bind the item ratios to their respective lists. while (!streamReader.EndOfStream) { //Item Name Mappings first String readString = streamReader.ReadLine(); if (readString.Contains("#") || readString.Equals("") || readString.Equals("\n")) { continue; } String[] split = readString.Split('='); itemMappings.Add(split[0], split[1]); //Split the string again to get the ratios if (split.Length > 2) { String[] ratios = split[2].Split(':'); minecraftRatios.Add(split[0], Double.Parse(ratios[0])); factorioRatios.Add(split[1], Double.Parse(ratios[1])); } } streamReader.Close(); fileStream.Close(); RCON rcon2 = new RCON(IPAddress.Parse("127.0.0.1"), (ushort)25575, "test_password"); FMCBridge.Running = true; Wrapper.Command("InputMode 3"); Wrapper.WriteLine("Use \"wrapper InputMode 0\" to access Wrapper mode."); /*======================================= * This loop monitors for user input in the console * and sends it to the appropriate process * =======================================*/ string ConsoleInput = ""; System.Threading.Tasks.Task.Run (async() => { do { if (Console.IsInputRedirected == false) { //BridgeInput = await Console.In.ReadLineAsync(); ConsoleInput = await Console.In.ReadLineAsync(); //BridgeInput = Console.ReadLine(); } } while (FMCBridge.Running == true); } ); List <ItemPair> factorioItems; List <ItemPair> minecraftItems; do { try { //If the user wasn't a squit if (string.IsNullOrWhiteSpace(ConsoleInput) == false) { switch (Wrapper.InputTarget) { //Default to wrapper case Wrapper.Modes.Menu: Wrapper.Command(ConsoleInput); break; case Wrapper.Modes.MinecraftServer: if (MinecraftServer.Running) { MinecraftServer.ProcessInput(ConsoleInput); } break; case Wrapper.Modes.FactorioServer: if (FactorioServer.Running) { FactorioServer.ProcessInput(ConsoleInput); } break; case Wrapper.Modes.FMCBridge: FMCBridge.ProcessInput(ConsoleInput); break; default: Wrapper.InputTarget = Wrapper.Modes.Menu; throw new TrashMonkeyException("Invalid input mode! Defaulting to wrapper mode."); } } factorioItems = parseFactorio(itemMappings, factorioRatios); minecraftItems = parseVanillaMinecraft(itemMappings, minecraftRatios, rcon2).Result; sendToFactorioExperimentalIO(minecraftItems); sendToVanillaExperimentalIO(factorioItems); } catch (TrashMonkeyException e) { //Handled errors Wrapper.ErrorWriteLine(e.Message); } catch (Exception e) { //Something actually broke errors Util.PrintErrorInfo(e); } ConsoleInput = ""; } while (FMCBridge.Running == true); //Exiting this loop should return to the menu }