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 }
/*======================================= * This subroutine starts up the server * and then monitors the output. * =======================================*/ public static void Run(bool BridgeMode = false) { FactorioServer.IsBridge = BridgeMode; FactorioServer.Loaded = false; FactorioServer.Stopping = false; Console.ForegroundColor = ConsoleColor.Cyan; Wrapper.InputTarget = Wrapper.Modes.Menu; Wrapper.WriteLine("Preparing Factorio 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. * =======================================*/ if (!File.Exists(SettingsFilePath)) { IniFile ds = new IniFile(SettingsFileName); ds.Write("Version", "0.18.10", "Factorio"); ds.Write("ExePath", @"E:\Factorio\Game\steamapps\common\Factorio\bin\x64\factorio.exe", "Factorio"); ds.Write("ServerArgs", @"--start-server E:\Factorio\Data\saves\Minecraft_Bridge_Tests\Minecraft_Bridge_Test_1 --bind 127.0.0.1:30000 --no-log-rotation", "Factorio"); } /*======================================= * 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 + " FactorioServer." + s.Read("Version", "Factorio"); RootPath = s.Read("ServerFolder", "Windows") + '\\'; ScriptOutputPath = s.Read("ScriptOutputPath", "Factorio") + '\\'; /*======================================= * Setup some files related to logs and crap * =======================================*/ Wrapper.WriteLine("Checking for previous unstopped servers..."); PIDFile = RootPath + s.Read("PIDFile", "Factorio"); 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("/quit"); //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..."); FactorioServer.Process = new Process(); FactorioServer.Process.StartInfo.FileName = s.Read("ExePath", "Factorio"); FactorioServer.Process.StartInfo.Arguments = s.BigRead("ServerArgs", "Factorio"); FactorioServer.Process.StartInfo.CreateNoWindow = true; FactorioServer.Process.StartInfo.ErrorDialog = false; FactorioServer.Process.StartInfo.UseShellExecute = false; FactorioServer.Process.StartInfo.RedirectStandardError = true; FactorioServer.Process.StartInfo.RedirectStandardOutput = true; FactorioServer.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..."); FactorioServer.Process.OutputDataReceived += new DataReceivedEventHandler ( (sender, OutputText) => { if (string.IsNullOrWhiteSpace(OutputText.Data) == false) { if (!FactorioServer.NoConsole) { Util.WriteToLog(OutputText.Data, FactorioServer.OutputFormat); } if (FactorioServer.Stopping == true) { FactorioServer.Loaded = !OutputText.Data.Contains("changing state from(Disconnected) to(Closed)"); FactorioServer.Running = !OutputText.Data.EndsWith("Goodbye"); } else if (!FactorioServer.Loaded) { FactorioServer.Loaded = OutputText.Data.Contains("changing state from(CreatingGame) to(InGame)"); } } } ); FactorioServer.Process.ErrorDataReceived += new DataReceivedEventHandler ( (sender, ErrorText) => { if (string.IsNullOrWhiteSpace(ErrorText.Data) == false) { if (!FactorioServer.NoConsole) { Util.WriteToLog(ErrorText.Data, FactorioServer.ErrorFormat); } } } ); /*======================================= * Finally start the dang server process * =======================================*/ Wrapper.WriteLine("Starting Factorio server..."); FactorioServer.NoConsole = true; FreeConsole(); FactorioServer.Process.Start(); File.WriteAllText(PIDFile, FactorioServer.Process.Id.ToString()); //Redirect the input so that the code can send text FactorioServer.Input = FactorioServer.Process.StandardInput; //Start checking for output FactorioServer.Process.BeginOutputReadLine(); FactorioServer.Process.BeginErrorReadLine(); //Don't try to do anything else until the server finishes loading while (FactorioServer.Loaded == false) { ; } AllocConsole(); FactorioServer.NoConsole = false; Console.Title = "Wrapper." + Wrapper.Version + " FactorioServer." + s.Read("Version", "Factorio"); Wrapper.WriteLine("Factorio server loaded!"); FactorioServer.Running = true; if (!FactorioServer.IsBridge) { Wrapper.Command("InputMode 2"); 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 Factorio server case Wrapper.Modes.FactorioServer: FactorioServer.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 (FactorioServer.Running == true); //Exiting this loop should return to the menu } }