Advertisement
LJack2k

Untitled

Dec 5th, 2015
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 94.50 KB | None | 0 0
  1. /* v:1.114 [Countdown, DateTime with format, Mass of cargo, Centered Time & Date, multiline separator \, Booting text]
  2.  * In-game script by MMaster
  3.  !  
  4.  ! You can now use LCD Private Text to enter commands line by line by using command UseTextCommands
  5.  !
  6.  * Last update: Countdown, DateTime with format, ChargeX, better Inventory performance
  7.  *  ingots and ores translatable, Oxygen & Hydrogen bottles now in single category
  8.  *  
  9.  * Previous updates: Mass of items in cargo
  10.  * Centered TimeC & DateC, Multiline separator \ in Private Text commands
  11.  * Booting text (automatic/manual using 'boot' argument) + Clear LCDs using 'clear' argument
  12.  * Hydrogen & Superconductors + Support for any gas tank using Tanks command
  13.  * Working command now shows updated recharge status of batteries (+), (-) or (±)
  14.  * DamageNoC command variants to not show deconstructed blocks
  15.  * Commands in Private Text by using UseTextCommands command!
  16.  * Battery charge state in Working command, Oxygen and Working command when air is leaking instead of showing 0%
  17.  * Date & Time offset, PosGPS showing position in gps format, TextLCD to append text from another LCD
  18.  * and more.. look at change logs on steam page.
  19.  *  
  20. Customize these: (do not report problems with modified values!) */
  21. // Use this tag to identify LCDs managed by this script
  22. public static string LCD_TAG = "[HANNIBAL]";
  23.  
  24. // How many panels to update per one step
  25. public static int PANELS_PER_STEP = 1;
  26. // How many lines to scroll per step
  27. public static int SCROLL_LINES_PER_STEP = 5;
  28.  
  29. // Force redraw of panels? (EXPERIMENTAL, default = true)
  30. // false - Massively reduces lag caused by LCD redraw, but can be buggy
  31. public static bool FORCE_REDRAW = true;
  32.  
  33. // Enable initial boot sequence (after compile / world load)
  34. public static bool ENABLE_BOOT = true;
  35.  
  36. // (for developer) Enable debug to LCD marked with [DEBUG]
  37. public static bool EnableDebug = false;
  38.  
  39. /*
  40. READ THIS FULL GUIDE
  41. http://steamcommunity.com/sharedfiles/filedetails/?id=407158161
  42.  
  43. Basic video guide
  44. Please watch the video guide even if you don't understand my English. You can see how things are done there.
  45.  
  46. http://www.youtube.com/watch?v=oopzyQ0t6Dk
  47.  
  48. EXAMPLE WORLD
  49. http://steamcommunity.com/sharedfiles/filedetails/?id=412154340
  50.  
  51. Read Change Notes (above screenshots) for latest updates and new features.
  52. I notify about updates on twitter so follow if interested.  
  53.  
  54. Please carefully read the FULL GUIDE before asking questions I had to remove guide from here to add more features :(
  55. Please DO NOT publish this script or its derivations without my permission! Feel free to use it in blueprints!
  56.  
  57. Special Thanks
  58. bssespaceengineers.com - awesome server
  59. Rhedd - for his contribution to modded items entries
  60. Textor and CyberVic for their great script related contributions on Keen forums.
  61.  
  62. Watch Twitter: https://twitter.com/MattsPlayCorner
  63. and Facebook: https://www.facebook.com/MattsPlayCorner1080p
  64. for more crazy stuff from me in the future :)
  65.  */
  66.  
  67. // For german clients
  68. public static string SECONDARY_TAG = "!LCD!";
  69.  
  70. public static int step;
  71. void Main(string argument)
  72. {
  73.   if (LCDsProgram.bootFrames == null) {
  74.   LCDsProgram.bootFrames = new List<string>()
  75.   {
  76. /* BOOT FRAMES  
  77.  * Each @"<text>" marks single frame, add as many as you want each will be displayed for one second
  78.  * @"" is multiline string so you can write multiple lines
  79.  */
  80. @"
  81.  Initializing systems"
  82. ,
  83. @"
  84.  Verifying connections"
  85. ,
  86. @"
  87.  Loading commands"
  88. /* END OF BOOT FRAMES */
  89.  
  90. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  91. // DO NOT MODIFY ANYTHING BELOW THIS
  92. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  93.   };
  94.   LCDsProgram.bootStep = (ENABLE_BOOT ? 0 : int.MaxValue);
  95.   LCDsProgram.bootScreens = ENABLE_BOOT;
  96.   }
  97.   // Init MMAPI and debug panels marked with [DEBUG]
  98.   MM.EnableDebug = EnableDebug;
  99.   MM.Me = Me;
  100.   MM.ElapsedTime = ElapsedTime;
  101.   MM.Init(GridTerminalSystem);
  102.   MMLCDMgr.forceRedraw = FORCE_REDRAW;
  103.   LCDsProgram.SECONDARY_TAG = SECONDARY_TAG;
  104.   LCDsProgram lcdProg = new LCDsProgram(LCD_TAG, SCROLL_LINES_PER_STEP, PANELS_PER_STEP);
  105.   lcdProg.Run(argument.ToLower(), step++);
  106. }
  107. }
  108.  
  109. public static class MMItems
  110. {
  111. public static Dictionary<string, MMItem> items = new Dictionary<string, MMItem>();
  112. public static List<string> keys = new List<string>();
  113. public static Dictionary<string, MMItem> itemsByShort = new Dictionary<string, MMItem>();
  114.  
  115. public static void Init()
  116. {
  117.   if (items.Count > 0)
  118.     return;
  119.  
  120. // **************************************************
  121. // OK MAYBE YOU CAN ADD MODDED ITEMS AND MODIFY QUOTAS  
  122. //    IF THAT WARNING DIDN'T SCARE YOU
  123. // **************************************************
  124. // ITEMS AND QUOTAS LIST  
  125. // (subType, mainType, quota, display name, short name)
  126. // ADD MODDED ITEMS TO THIS LIST
  127. // !! MAIN TYPES MUST GO TOGETHER FOR INV CATEGORIES !!
  128. // VANILLA ITEMS
  129. Add("Stone", "Ore");
  130. Add("Iron", "Ore");
  131. Add("Nickel", "Ore");
  132. Add("Cobalt", "Ore");
  133. Add("Magnesium", "Ore");
  134. Add("Silicon", "Ore");
  135. Add("Silver", "Ore");
  136. Add("Gold", "Ore");
  137. Add("Platinum", "Ore");
  138. Add("Uranium", "Ore");
  139. Add("Ice", "Ore");
  140. Add("Stone", "Ingot", 40000, "Gravel", "gravel");
  141. Add("Iron", "Ingot", 100000);
  142. Add("Nickel", "Ingot", 80000);
  143. Add("Cobalt", "Ingot", 30000);
  144. Add("Magnesium", "Ingot", 30000);
  145. Add("Silicon", "Ingot", 50000);
  146. Add("Silver", "Ingot", 50000);
  147. Add("Gold", "Ingot", 60000);
  148. Add("Platinum", "Ingot", 40000);
  149. Add("Uranium", "Ingot", 10000);
  150. Add("Scrap", "Ingot");
  151. Add("AutomaticRifleItem", "PhysicalGunObject", 10, "Automatic Rifle");
  152. Add("WelderItem", "PhysicalGunObject", 0, "Welder");
  153. Add("AngleGrinderItem", "PhysicalGunObject", 0, "Angle Grinder");
  154. Add("HandDrillItem", "PhysicalGunObject", 0, "Hand Drill");
  155. Add("Construction", "Component", 40000);
  156. Add("MetalGrid", "Component", 8000, "Metal Grid");
  157. Add("InteriorPlate", "Component", 25000, "Interior Plate");
  158. Add("SteelPlate", "Component", 200000, "Steel Plate");
  159. Add("Girder", "Component", 2000);
  160. Add("SmallTube", "Component", 16000, "Small Tube");
  161. Add("LargeTube", "Component", 3000, "Large Tube");
  162. Add("Motor", "Component", 3000);
  163. Add("Display", "Component", 350);
  164. Add("BulletproofGlass", "Component", 3000, "Bulletp. Glass", "bpglass");
  165. Add("Computer", "Component", 5000);
  166. Add("Reactor", "Component", 10000);
  167. Add("Thrust", "Component", 16000, "Thruster", "thruster");
  168. Add("GravityGenerator", "Component", 50, "GravGen", "gravgen");
  169. Add("Medical", "Component", 120);
  170. Add("RadioCommunication", "Component", 200, "Radio-comm", "radio");
  171. Add("Detector", "Component", 100);
  172. Add("Explosives", "Component", 100);
  173. Add("SolarCell", "Component", 1500, "Solar Cell");
  174. Add("PowerCell", "Component", 1500, "Power Cell");
  175. Add("Superconductor", "Component", 300);
  176. Add("NATO_5p56x45mm", "AmmoMagazine", 1000, "5.56x45mm", "5.56x45mm");
  177. Add("NATO_25x184mm", "AmmoMagazine", 2000, "25x184mm", "25x184mm");
  178. Add("Missile200mm", "AmmoMagazine", 1600, "200mm Missile", "200mmmissile");
  179. Add("OxygenBottle", "OxygenContainerObject", 0, "Oxygen Bottle");
  180. Add("HydrogenBottle", "GasContainerObject", 0, "Hydrogen Bottle");
  181.  
  182. // MODDED ITEMS  
  183. // (subType, mainType, quota, display name, short name, used)
  184. // * if used is true, item will be shown in inventory even for 0 items
  185. // * if used is false, item will be used only for display name and short name
  186. // AzimuthSupercharger  
  187. Add("AzimuthSupercharger", "Component", 1600, "Supercharger", "supercharger", false);
  188. // OKI Ammo
  189. Add("OKI23mmAmmo", "AmmoMagazine", 500, "23x180mm", "23x180mm", false);
  190. Add("OKI50mmAmmo", "AmmoMagazine", 500, "50x450mm", "50x450mm", false);
  191. Add("OKI122mmAmmo", "AmmoMagazine", 200, "122x640mm", "122x640mm", false);
  192. Add("OKI230mmAmmo", "AmmoMagazine", 100, "230x920mm", "230x920mm", false);
  193. }
  194.  
  195. /* REALLY REALLY REALLY
  196.   * DO NOT MODIFY ANYTHING BELOW THIS
  197.   */
  198.  
  199. // displayName - how the item will be displayed
  200. // shortName - how the item can be called in arguments (eg: +supercharger)
  201. public static void Add(string subType, string mainType, int quota = 0, string displayName = "", string shortName = "", bool used = true)
  202. {
  203.   string fullType = subType + ' ' + mainType;
  204.   MMItem item = new MMItem(subType, mainType, quota, displayName, shortName, used);
  205.   items.Add(fullType, item);
  206.   if (shortName != "")
  207.     itemsByShort.Add(shortName.ToLower(), item);
  208.   keys.Add(fullType);
  209. }
  210.  
  211. public static MMItem GetItemOfType(string subType = "", string mainType = "")
  212. {
  213.   if (items.ContainsKey(subType + " " + mainType))
  214.     return items[subType + " " + mainType];
  215.  
  216.   if (mainType == "")
  217.     for (int i = 0; i < items.Count; i++)
  218.     {
  219.       MMItem item = items[keys[i]];
  220.       if (subType == item.subType)
  221.         return item;
  222.     }
  223.  
  224.   if (subType == "")
  225.     for (int i = 0; i < items.Count; i++)
  226.     {
  227.       MMItem item = items[keys[i]];
  228.       if (mainType == item.mainType)
  229.         return item;
  230.     }
  231.   return null;
  232. }
  233. }
  234.  
  235. public class LCDsProgram
  236. {
  237. // for german clients
  238. public static string SECONDARY_TAG = "";
  239. // approximate width of LCD panel line
  240. public const float LCD_LINE_WIDTH = 730;
  241. // x position of inventory numbers
  242. public const float LCD_LINE_NUMERS_POS = LCD_LINE_WIDTH - 30;
  243.  
  244. public const float LCD_LINE_INV_NUMBERS_POS = LCD_LINE_WIDTH - 130;
  245. public const float LCD_LINE_INGOT_NUMBERS_POS = 375;
  246. public const float LCD_LINE_DMG_NUMBERS_POS = LCD_LINE_WIDTH - 230;
  247. public const float LCD_LINE_WORK_STATE_POS = LCD_LINE_WIDTH - 30;
  248. public const float LCD_LINE_BLOCK_COUNT_POS = LCD_LINE_WIDTH - 30;
  249.  
  250. public const float PERCENT_TEXT_SIZE = 110f;
  251.  
  252. // number of component progress bar characters
  253. public const int INV_PROGRESS_CHARS = 38;
  254. // full line of progress bar
  255. public const int FULL_PROGRESS_CHARS = 116;
  256.    
  257. public static int PANELS_PER_STEP = 1;
  258.  
  259. public MMPanelDict panels = new MMPanelDict();
  260. public double velocity;
  261. public static VRageMath.Vector3D lastPos;
  262. public static int bootStep = 0;
  263. public static bool bootScreens = true;
  264. public static List<string> bootFrames = null;
  265. public LCDsProgram(string nameLike, int sps, int pps)
  266. {
  267.   MMBlockCollection lcds = new MMBlockCollection();
  268.   PANELS_PER_STEP = pps;
  269.   lcds.AddBlocksOfType("textpanel", nameLike);
  270.   if (nameLike == "[LCD]" && SECONDARY_TAG != "")
  271.     lcds.AddBlocksOfType("textpanel", SECONDARY_TAG);
  272.  
  273.   for (int i = 0; i < lcds.Count(); i++)
  274.   {
  275.     IMyTextPanel panel = (lcds.Blocks[i] as IMyTextPanel);
  276.     string text = panel.CustomName + " " + panel.NumberInGrid + " " + panel.GetPosition().ToString("F0");
  277.     MMPanel p = null;
  278.  
  279.     int joinpos = text.IndexOf("!LINK:");
  280.  
  281.     if (joinpos < 0 || text.Length == joinpos + 6)
  282.     {
  283.       p = new MMPanel();
  284.       p.panels.AddItem(text, panel);
  285.       panels.AddItem(text, p);
  286.       p.SCROLL_LINES = sps;
  287.       continue;
  288.     }
  289.  
  290.     text = text.Substring(joinpos + 6);
  291.        
  292.     string[] subs = text.Split(' ');
  293.     string group = subs[0];
  294.     p = panels.GetItem(group);
  295.     if (p == null)
  296.     {
  297.       p = new MMPanel();
  298.       panels.AddItem(group, p);
  299.     }
  300.     p.panels.AddItem(text, panel);
  301.     p.SCROLL_LINES = sps;
  302.   }
  303. }
  304.  
  305. public void Run(string argument, int step)
  306. {
  307.   if (panels.CountAll() == 0)
  308.     return;
  309.  
  310.   velocity = (MM.Me.GetPosition() - lastPos).Length() / MM.ElapsedTime.TotalSeconds;
  311.  
  312.   if (argument == "clear")
  313.   {
  314.     bootStep = (bootScreens ? 0 : int.MaxValue);
  315.     for (int i = 0; i < panels.CountAll(); i++)
  316.     {
  317.       MMPanel p = panels.GetItemAt(i);
  318.       p.SortPanels();
  319.       MMLCDMgr.SetupLCDText(p);
  320.       MMLCDMgr.ClearText(p);
  321.       MMLCDMgr.UpdatePanel(p);
  322.     }
  323.   } else
  324.   if (argument == "boot" || bootStep <= bootFrames.Count)
  325.   {
  326.     if (bootStep > bootFrames.Count)
  327.       bootStep = 0;
  328.  
  329.     for (int i = 0; i < panels.CountAll(); i++)
  330.     {
  331.       MMPanel p = panels.GetItemAt(i);
  332.       p.SortPanels();
  333.       MMLCDMgr.SetupLCDText(p);
  334.       MMLCDMgr.ClearText(p);
  335.       // don't display on LCDs with really large font
  336.       if (p.first.GetValueFloat("FontSize") > 3f)
  337.         continue;
  338.       MMLCDMgr.AddCenterLn(p, "Booting up...", LCD_LINE_WIDTH / 2);
  339.       double perc = (double)bootStep / bootFrames.Count * 100;
  340.       MMLCDMgr.AddProgressBarLn(p, perc, FULL_PROGRESS_CHARS);
  341.       if (bootStep == bootFrames.Count)
  342.       {
  343.         MMLCDMgr.AddLn(p, "");
  344.         MMLCDMgr.AddCenterLn(p, "Configurable Automatic LCDs", LCD_LINE_WIDTH / 2);
  345.         MMLCDMgr.AddCenterLn(p, "by MMaster", LCD_LINE_WIDTH / 2);
  346.       } else
  347.         MMLCDMgr.AddMultiLn(p, bootFrames[bootStep]);
  348.       MMLCDMgr.UpdatePanel(p);
  349.     }
  350.     bootStep++;
  351.   } else {  
  352.     for (int i = 0; i < PANELS_PER_STEP; i++)
  353.     {
  354.       RunSingle(panels.GetItemAt((step * PANELS_PER_STEP + i) % panels.CountAll()));
  355.     }
  356.   }
  357.  
  358.   lastPos = MM.Me.GetPosition();
  359. }
  360.  
  361. public void RunSingle(MMPanel panel)
  362. {
  363.  
  364. bool useText = false;
  365. panel.SortPanels();
  366. MMLCDMgr.SetupLCDText(panel);
  367.  
  368. string pubText = panel.first.CustomName;
  369. pubText = (pubText.Contains("#") ? pubText.Substring(pubText.LastIndexOf('#') + 1) : "");
  370. MMLCDMgr.ClearText(panel);
  371.  
  372. if (pubText != "")
  373.   MMLCDMgr.AddLn(panel, pubText);
  374.  
  375. string title = panel.first.GetPrivateTitle();
  376. if (title == "Title" || title == "")
  377.   title = panel.first.GetPublicTitle();
  378.  
  379. if (title.Trim() == "UseTextCommands")
  380. {
  381.   useText = true;
  382.   title = panel.first.GetPrivateText();
  383.   title = title.Replace("\\\n", " ");
  384. }
  385.      
  386. if (title.StartsWith("Public") || title == "")
  387. {
  388.   if (useText)
  389.     MMLCDMgr.AddLn(panel, "Write commands to Private Text.");
  390.   else
  391.     MMLCDMgr.AddLn(panel, "Write commands to Public or Private Title.");
  392.   MMLCDMgr.UpdatePanel(panel);
  393.   return;
  394. }
  395.  
  396. char[] delim = { ';', '\n' };
  397. string[] cmds = title.Split(delim);
  398. for (int i = 0; i < cmds.Length; i++)
  399. {
  400.   MM.Debug("Running command " + cmds[i]);
  401.   MMCommand cmd = new MMCommand(cmds[i]);
  402.  
  403.   if (cmd.cmdstr.StartsWith("inventory") ||
  404.     cmd.cmdstr == "missing" ||
  405.     cmd.cmdstr.StartsWith("invlist"))
  406.     RunInvListing(panel, cmd);
  407.   else
  408.   if (cmd.cmdstr.StartsWith("cargo"))
  409.     RunCargoStatus(panel, cmd);
  410.   else
  411.   if (cmd.cmdstr.StartsWith("mass"))
  412.     RunMass(panel, cmd);
  413.   else
  414.   if (cmd.cmdstr == "oxygen")
  415.     RunOxygenStatus(panel, cmd);
  416.   else
  417.   if (cmd.cmdstr == "tanks")
  418.     RunTankStatus(panel, cmd);
  419.   else
  420.   if (cmd.cmdstr.StartsWith("power"))
  421.     RunPowerStatus(panel, cmd);
  422.   else
  423.   if (cmd.cmdstr == "speed")
  424.     RunVelocity(panel, cmd);
  425.   else
  426.   if (cmd.cmdstr.StartsWith("charge"))
  427.     RunCharge(panel, cmd);
  428.   else
  429.   if (cmd.cmdstr.StartsWith("time") ||
  430.     cmd.cmdstr.StartsWith("date"))
  431.     RunCurrentTime(panel, cmd);
  432.   else
  433.   if (cmd.cmdstr.StartsWith("countdown"))
  434.     RunCountdown(panel, cmd);
  435.   else
  436.   if (cmd.cmdstr == "echo" ||
  437.     cmd.cmdstr == "center")
  438.     RunEcho(panel, cmd);
  439.   else
  440.   if (cmd.cmdstr.StartsWith("text"))
  441.     RunText(panel, cmd);
  442.   else
  443.   if (cmd.cmdstr.EndsWith("count"))
  444.     RunBlockCount(panel, cmd);
  445.   else
  446.   if (cmd.cmdstr.StartsWith("working"))
  447.     RunWorkingList(panel, cmd);
  448.   else
  449.   if (cmd.cmdstr.StartsWith("damage"))
  450.     RunDamage(panel, cmd);
  451.   else
  452.   if (cmd.cmdstr.StartsWith("amount"))
  453.     RunItemAmount(panel, cmd);
  454.   else
  455.   if (cmd.cmdstr.StartsWith("pos"))
  456.     RunPosition(panel, cmd);
  457.   else
  458.   if (cmd.cmdstr.StartsWith("details"))
  459.     RunDetails(panel, cmd);
  460.   else
  461.     MMLCDMgr.AddLn(panel, "Unknown command: " + cmd.cmdstr);
  462.  
  463.   MM.Debug("Done.");
  464. }
  465.  
  466. MMLCDMgr.UpdatePanel(panel);
  467.  
  468. }
  469.  
  470. public void RunCharge(MMPanel panel, MMCommand cmd)
  471. {
  472.   bool simple = cmd.cmdstr.Contains("x");
  473.   MMBlockCollection blocks = new MMBlockCollection();
  474.   blocks.AddBlocksOfType("jumpdrive", cmd.nameLike);
  475.  
  476.   if (blocks.Count() <= 0)
  477.   {
  478.     MMLCDMgr.AddLn(panel, "Charge: No blocks found.");
  479.     return;
  480.   }
  481.  
  482.   for (int i = 0; i < blocks.Count(); i++)
  483.   {
  484.     IMyJumpDrive jd = blocks.Blocks[i] as IMyJumpDrive;
  485.        
  486.     double cur, max, perc;
  487.     perc = MMStatus.GetJumpDriveChargeValues(jd, out cur, out max);
  488.  
  489.     MMLCDMgr.Add(panel, jd.CustomName);
  490.     if (!simple)
  491.     {
  492.       MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(cur) + "Wh / " + MM.FormatLargeNumber(max) + "Wh", LCD_LINE_WIDTH);
  493.       MMLCDMgr.AddProgressBar(panel, perc, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  494.     }
  495.     MMLCDMgr.AddRightAlignLn(panel, ' ' + perc.ToString("0.0") + "%", LCD_LINE_WIDTH);
  496.   }
  497. }
  498.  
  499. public void RunVelocity(MMPanel panel, MMCommand cmd)
  500. {
  501.   MMLCDMgr.Add(panel, "Speed:");
  502.   MMLCDMgr.AddRightAlignLn(panel, velocity.ToString("F1") + " m/s", LCD_LINE_WIDTH);
  503. }
  504.  
  505. public void RunText(MMPanel panel, MMCommand cmd)
  506. {
  507.   bool fromLCD = (cmd.cmdstr == "textlcd");
  508.  
  509.   IMyTextPanel p = panel.first;
  510.   if (p == null)
  511.     return;
  512.  
  513.   string text = p.GetPrivateText();
  514.  
  515.   if (fromLCD)
  516.   {
  517.     if (cmd.nameLike != "" && cmd.nameLike != "*")
  518.     {
  519.       IMyTextPanel tp = MM._GridTerminalSystem.GetBlockWithName(cmd.nameLike) as IMyTextPanel;
  520.       if (tp == null)
  521.       {
  522.         MMLCDMgr.AddLn(panel, "TextLCD source LCD not found: " + cmd.nameLike);
  523.         return;
  524.       }
  525.  
  526.       text = tp.GetPublicText();
  527.     }
  528.     else
  529.     {
  530.       MMLCDMgr.AddLn(panel, "TextLCD is missing source LCD name");
  531.       return;
  532.     }
  533.   }
  534.  
  535.   string[] lines = text.Split('\n');
  536.   if (lines.Length == 0)
  537.   {
  538.     if (!fromLCD)
  539.       MMLCDMgr.AddLn(panel, "Text: LCD Private Text is empty");
  540.     return;
  541.   }
  542.  
  543.   for (int i = 0; i < lines.Length; i++)
  544.     MMLCDMgr.AddLn(panel, lines[i]);
  545. }
  546.  
  547. private void PrintDetails(MMPanel panel, IMyTerminalBlock block)
  548. {
  549.   string[] lines = block.DetailedInfo.Split('\n');
  550.   for (int j = 0; j < lines.Length; j++)
  551.     if (lines[j] != "")
  552.       MMLCDMgr.AddLn(panel, "  " + lines[j]);
  553. }
  554.  
  555. public void RunDetails(MMPanel panel, MMCommand cmd)
  556. {
  557.   if (cmd.nameLike == "" || cmd.nameLike == "*")
  558.   {
  559.     MMLCDMgr.AddLn(panel, "Details: You need to enter name.");
  560.     return;
  561.   }
  562.  
  563.   MMBlockCollection blocks = new MMBlockCollection();
  564.   blocks.AddBlocksOfNameLike(cmd.nameLike);
  565.  
  566.   if (blocks.Count() <= 0)
  567.   {
  568.     MMLCDMgr.AddLn(panel, "Details: No blocks found.");
  569.     return;
  570.   }
  571.  
  572.   IMyTerminalBlock block = blocks.Blocks[0];
  573.   MMLCDMgr.AddLn(panel, block.CustomName);
  574.   PrintDetails(panel, block);
  575.  
  576.   for (int i = 1; i < blocks.Count(); i++)
  577.   {
  578.     block = blocks.Blocks[i];
  579.     MMLCDMgr.AddLn(panel, "");
  580.     MMLCDMgr.AddLn(panel, block.CustomName);
  581.     PrintDetails(panel, block);
  582.   }
  583. }
  584.  
  585. public void RunPosition(MMPanel panel, MMCommand cmd)
  586. {
  587.   bool posxyz = (cmd.cmdstr == "posxyz");
  588.   bool gps = (cmd.cmdstr == "posgps");
  589.      
  590.   IMyTerminalBlock block = panel.first;
  591.   if (cmd.nameLike != "" && cmd.nameLike != "*")
  592.   {
  593.     block = MM._GridTerminalSystem.GetBlockWithName(cmd.nameLike);
  594.     if (block == null)
  595.     {
  596.       MMLCDMgr.AddLn(panel, "Block not found: " + cmd.nameLike);
  597.       return;
  598.     }
  599.   }
  600.  
  601.   if (gps)
  602.   {
  603.     VRageMath.Vector3D pos = block.GetPosition();
  604.  
  605.     MMLCDMgr.AddLn(panel, "GPS:Location:" +
  606.         pos.GetDim(0).ToString("F2") + ":" +
  607.         pos.GetDim(1).ToString("F2") + ":" +
  608.         pos.GetDim(2).ToString("F2") + ":");
  609.     return;
  610.   }
  611.  
  612.   MMLCDMgr.Add(panel, "Location: ");
  613.   if (!posxyz)
  614.   {
  615.     MMLCDMgr.AddRightAlignLn(panel, block.GetPosition().ToString("F0"), LCD_LINE_WORK_STATE_POS);
  616.     return;
  617.   }
  618.  
  619.   MMLCDMgr.AddLn(panel, "");
  620.   MMLCDMgr.Add(panel, " X: ");
  621.   MMLCDMgr.AddRightAlignLn(panel, block.GetPosition().GetDim(0).ToString("F0"), LCD_LINE_WORK_STATE_POS);
  622.   MMLCDMgr.Add(panel, " Y: ");
  623.   MMLCDMgr.AddRightAlignLn(panel, block.GetPosition().GetDim(1).ToString("F0"), LCD_LINE_WORK_STATE_POS);
  624.   MMLCDMgr.Add(panel, " Z: ");
  625.   MMLCDMgr.AddRightAlignLn(panel, block.GetPosition().GetDim(2).ToString("F0"), LCD_LINE_WORK_STATE_POS);
  626. }
  627.  
  628. public void RunBlockCount(MMPanel panel, MMCommand cmd)
  629. {
  630.   bool enabledCnt = (cmd.cmdstr == "enabledcount");
  631.   bool producingCnt = (cmd.cmdstr == "prodcount");
  632.  
  633.   for (int i = 0; i < cmd.args.Count; i++)
  634.   {
  635.     MMArgument arg = cmd.args[i];
  636.  
  637.     for (int subi = 0; subi < arg.sub.Count; subi++)
  638.     {
  639.       MMBlockCollection blocks = new MMBlockCollection();
  640.       blocks.AddBlocksOfType(arg.sub[subi], cmd.nameLike);
  641.  
  642.       string name;
  643.  
  644.       if (blocks.Count() == 0)
  645.       {
  646.         name = arg.sub[subi];
  647.         name = char.ToUpper(name[0]) + name.Substring(1).ToLower();
  648.         MMLCDMgr.Add(panel, name + " count: ");
  649.         string countstr = (enabledCnt || producingCnt ? "0 / 0" : "0");
  650.         MMLCDMgr.AddRightAlignLn(panel, countstr, LCD_LINE_BLOCK_COUNT_POS);
  651.       }
  652.       else
  653.       {
  654.         Dictionary<string, int> typeCount = new Dictionary<string, int>();
  655.         Dictionary<string, int> typeWorkingCount = new Dictionary<string, int>();
  656.         List<string> blockTypes = new List<string>();
  657.  
  658.         for (int j = 0; j < blocks.Count(); j++)
  659.         {
  660.           IMyProductionBlock prod = blocks.Blocks[j] as IMyProductionBlock;
  661.           name = blocks.Blocks[j].DefinitionDisplayNameText;
  662.           if (blockTypes.Contains(name))
  663.           {
  664.             typeCount[name]++;
  665.             if ((enabledCnt && blocks.Blocks[j].IsWorking) ||
  666.               (producingCnt && prod != null && prod.IsProducing))
  667.               typeWorkingCount[name]++;
  668.           }
  669.           else
  670.           {
  671.             typeCount.Add(name, 1);
  672.             blockTypes.Add(name);
  673.             if (enabledCnt || producingCnt)  
  674.               if ((enabledCnt && blocks.Blocks[j].IsWorking) ||
  675.                 (producingCnt && prod != null && prod.IsProducing))
  676.                 typeWorkingCount.Add(name, 1);
  677.               else
  678.                 typeWorkingCount.Add(name, 0);
  679.           }
  680.         }
  681.         for (int j = 0; j < typeCount.Count; j++)
  682.         {
  683.           MMLCDMgr.Add(panel, blockTypes[j] + " count: ");
  684.           string countstr = (enabledCnt || producingCnt ?  
  685.             typeWorkingCount[blockTypes[j]] + " / "  : "") +  
  686.             typeCount[blockTypes[j]];
  687.  
  688.           MMLCDMgr.AddRightAlignLn(panel, countstr, LCD_LINE_BLOCK_COUNT_POS);
  689.         }
  690.       }
  691.     }
  692.   }
  693. }
  694.  
  695. public string GetWorkingString(IMyTerminalBlock block)
  696. {
  697.   if (!block.IsWorking)
  698.     return "OFF";
  699.  
  700.   IMyProductionBlock prod = block as IMyProductionBlock;
  701.   if (prod != null)
  702.     if (prod.IsProducing)
  703.       return "WORK";
  704.     else
  705.       return "IDLE";
  706.  
  707.   IMyAirVent vent = block as IMyAirVent;
  708.   if (vent != null)
  709.   {
  710.     if (vent.CanPressurize)
  711.       return (vent.GetOxygenLevel() * 100).ToString("F1") + "%";
  712.     else
  713.       return "LEAK";
  714.   }
  715.  
  716.   IMyOxygenTank tank = block as IMyOxygenTank;
  717.   if (tank != null)
  718.     return (tank.GetOxygenLevel() * 100).ToString("F1") + "%";
  719.  
  720.   IMyBatteryBlock battery = block as IMyBatteryBlock;
  721.   if (battery != null)
  722.     return MMStatus.GetBatteryWorkingString(battery);
  723.  
  724.   IMyJumpDrive jd = block as IMyJumpDrive;
  725.   if (jd != null)
  726.     return MMStatus.GetJumpDriveCharge(jd).ToString("0.0") + "%";
  727.  
  728.   IMyLandingGear gear = block as IMyLandingGear;
  729.   if (gear != null)
  730.     return MMStatus.GetLandingGearStatus(gear);
  731.  
  732.   IMyDoor door = block as IMyDoor;
  733.   if (door != null)
  734.   {
  735.     if (door.Open)
  736.       return "OPEN";
  737.     return "CLOSED";
  738.   }
  739.  
  740.   IMyShipConnector conn = block as IMyShipConnector;
  741.   if (conn != null)
  742.     if (conn.IsLocked)
  743.       return "LOCK";
  744.     else
  745.       return "UNLOCK";
  746.  
  747.   IMyLaserAntenna lasant = block as IMyLaserAntenna;
  748.   if (lasant != null)
  749.     return MMStatus.GetLaserAntennaStatus(lasant);
  750.  
  751.   IMyRadioAntenna ant = block as IMyRadioAntenna;
  752.   if (ant != null)
  753.     return MM.FormatLargeNumber(ant.Radius) + "m";
  754.  
  755.   IMyBeacon beacon = block as IMyBeacon;
  756.   if (beacon != null)
  757.     return MM.FormatLargeNumber(beacon.Radius) + "m";
  758.  
  759.   return "ON";
  760. }
  761.  
  762. public void RunWorkingList(MMPanel panel, MMCommand cmd)
  763. {
  764.   bool enabledList = (cmd.cmdstr == "workingx");
  765.  
  766.   for (int i = 0; i < cmd.args.Count; i++)
  767.   {
  768.     MMArgument arg = cmd.args[i];
  769.  
  770.     for (int subi = 0; subi < arg.sub.Count; subi++)
  771.     {
  772.       MMBlockCollection blocks = new MMBlockCollection();
  773.       if (arg.sub[subi] == "")
  774.         continue;
  775.       string[] subparts = arg.sub[subi].Split(':');
  776.       string subargtype = subparts[0];
  777.       string subargstate = (subparts.Length > 1 ? subparts[1].ToLower() : "");
  778.       blocks.AddBlocksOfType(subargtype, cmd.nameLike);
  779.  
  780.       if (blocks.Count() > 0) {
  781.         for (int j = 0; j < blocks.Count(); j++)
  782.         {
  783.           IMyTerminalBlock block = blocks.Blocks[j];
  784.           string onoff = (enabledList ? (block.IsWorking ? "ON" : "OFF") : GetWorkingString(block));
  785.           if (subargstate != "" && onoff.ToLower() != subargstate)
  786.             continue;
  787.           if (enabledList)
  788.             onoff = GetWorkingString(block);
  789.  
  790.           string blockName = block.CustomName;
  791.           blockName = MMStringFunc.GetStringTrimmed(blockName, LCD_LINE_WORK_STATE_POS - 100);
  792.           MMLCDMgr.Add(panel, blockName);
  793.           MMLCDMgr.AddRightAlignLn(panel, onoff, LCD_LINE_WORK_STATE_POS);
  794.         }
  795.       }
  796.     }
  797.   }
  798. }
  799.  
  800. public void RunItemAmount(MMPanel panel, MMCommand cmd)
  801. {
  802.   bool progressbars = true;
  803.   if (cmd.cmdstr[cmd.cmdstr.Length - 1] == 'x')
  804.   {
  805.     cmd.cmdstr = cmd.cmdstr.Substring(0, cmd.cmdstr.Length - 1);
  806.     progressbars = false;
  807.   }
  808.  
  809.   if (cmd.args.Count == 0)
  810.     cmd.args.Add(new MMArgument(
  811.       "reactor,gatlingturret,missileturret,interiorturret,gatlinggun,launcherreload,launcher,oxygenerator"));
  812.  
  813.   for (int i = 0; i < cmd.args.Count; i++)
  814.   {
  815.     MMArgument arg = cmd.args[i];
  816.  
  817.     for (int subi = 0; subi < arg.sub.Count; subi++)
  818.     {
  819.       MMBlockCollection blocks = new MMBlockCollection();
  820.       if (arg.sub[subi] == "")
  821.         continue;
  822.       string subargtype = arg.sub[subi];
  823.       blocks.AddBlocksOfType(subargtype, cmd.nameLike);
  824.  
  825.       if (blocks.Count() > 0)
  826.       {
  827.         for (int j = 0; j < blocks.Count(); j++)
  828.         {
  829.           IMyTerminalBlock block = blocks.Blocks[j];
  830.           IMyInventory inv = block.GetInventory(0);
  831.           if (inv == null)
  832.             continue;
  833.  
  834.           double amt = 0;
  835.           double maxAmt = 0;
  836.           double otherAmt = 0;
  837.           List<IMyInventoryItem> items = inv.GetItems();
  838.           string itemType = (items.Count > 0 ? items[0].Content.ToString() : "");
  839.           for (int idx = 0; idx < items.Count; idx++)
  840.           {
  841.             IMyInventoryItem item = items[idx];
  842.                
  843.             if (item.Content.ToString() != itemType)
  844.               otherAmt += (double)item.Amount;
  845.             else
  846.               amt += (double)item.Amount;
  847.           }
  848.           string amountStr = "EMPTY";
  849.           string blockName = block.CustomName;
  850.  
  851.           if (amt > 0 && (double)inv.CurrentVolume > 0)
  852.           {
  853.             double otherVol = otherAmt * (double)inv.CurrentVolume / (amt + otherAmt);
  854.             maxAmt = Math.Floor(amt * ((double)inv.MaxVolume - otherVol) / (double)inv.CurrentVolume - otherVol);
  855.  
  856.             amountStr = MM.FormatLargeNumber(amt) + " / " + (otherAmt > 0 ? "~" : "") + MM.FormatLargeNumber(maxAmt);
  857.           }
  858.  
  859.           blockName = MMStringFunc.GetStringTrimmed(blockName, LCD_LINE_WORK_STATE_POS - 60);
  860.           MMLCDMgr.Add(panel, blockName);
  861.           MMLCDMgr.AddRightAlignLn(panel, amountStr, LCD_LINE_WORK_STATE_POS);
  862.  
  863.           if (progressbars && maxAmt > 0)
  864.           {
  865.             double perc = 100 * amt / maxAmt;
  866.             MMLCDMgr.AddProgressBarLn(panel, perc, FULL_PROGRESS_CHARS);
  867.           }
  868.         }
  869.       }
  870.     }
  871.   }
  872. }
  873.  
  874. public void RunEcho(MMPanel panel, MMCommand cmd)
  875. {
  876.   bool center = (cmd.cmdstr == "center");
  877.   int idx = cmd.cmdLine.IndexOf(' ');
  878.   string msg = "";
  879.   if (idx >= 0)
  880.     msg = cmd.cmdLine.Substring(idx + 1);
  881.  
  882.   if (!center)
  883.     MMLCDMgr.AddLn(panel, msg);
  884.   else
  885.     MMLCDMgr.AddCenterLn(panel, msg, LCD_LINE_WIDTH / 2);
  886. }
  887.  
  888. public void RunDamage(MMPanel panel, MMCommand cmd)
  889. {
  890.   bool simple = cmd.cmdstr.StartsWith("damagex");
  891.   bool onlyDmg = cmd.cmdstr.EndsWith("noc"); // no construct
  892.  
  893.   MMBlockCollection blocks = new MMBlockCollection();
  894.   blocks.AddBlocksOfNameLike(cmd.nameLike);
  895.   bool found = false;
  896.  
  897.   for (int i = 0; i < blocks.Count(); i++)
  898.   {
  899.     IMyTerminalBlock block = blocks.Blocks[i];
  900.     IMySlimBlock slim = block.CubeGrid.GetCubeBlock(block.Position);
  901.     float hull = (onlyDmg? slim.MaxIntegrity : slim.BuildIntegrity) - slim.CurrentDamage;
  902.     float perc = 100 * (hull / slim.MaxIntegrity);
  903.  
  904.     if (perc >= 100)
  905.       continue;
  906.  
  907.     found = true;
  908.        
  909.     MMLCDMgr.Add(panel, MMStringFunc.GetStringTrimmed(slim.FatBlock.DisplayNameText,  
  910.       LCD_LINE_DMG_NUMBERS_POS - 70) + " ");
  911.     if (!simple)
  912.     {
  913.       MMLCDMgr.AddRightAlign(panel, MM.FormatLargeNumber(hull) + " / ",
  914.         LCD_LINE_DMG_NUMBERS_POS);
  915.       MMLCDMgr.Add(panel, MM.FormatLargeNumber(slim.MaxIntegrity));
  916.     }
  917.     MMLCDMgr.AddRightAlignLn(panel, ' ' + perc.ToString("0.0") + "%", LCD_LINE_WIDTH);
  918.     MMLCDMgr.AddProgressBarLn(panel, perc, FULL_PROGRESS_CHARS);
  919.   }
  920.  
  921.   if (!found)
  922.     MMLCDMgr.AddLn(panel, "No damaged blocks found.");
  923. }
  924.  
  925. public void RunTankStatus(MMPanel panel, MMCommand cmd)
  926. {
  927.   List<MMArgument> args = cmd.args;
  928.   string tankType;
  929.  
  930.   if (args.Count == 0 || args[0].sub.Count == 0)
  931.   {
  932.     MMLCDMgr.AddLn(panel, "Missing tank type. eg: 'Tanks * Hydrogen'");
  933.     return;
  934.   }
  935.  
  936.   tankType = args[0].sub[0];
  937.  
  938.   double percent;
  939.   MMBlockCollection blocks = new MMBlockCollection();
  940.  
  941.   blocks.AddBlocksOfType("oxytank", cmd.nameLike);
  942.  
  943.   double tankSum = 0;
  944.   int cnt = blocks.Count();
  945.   for (int i = 0; i < blocks.Count(); i++)
  946.   {
  947.     IMyOxygenTank tank = blocks.Blocks[i] as IMyOxygenTank;
  948.     if ((tankType == "oxygen" && tank.BlockDefinition.SubtypeId == "") ||
  949.       tank.BlockDefinition.SubtypeId.ToLower().Contains(tankType)) // only selected tank type
  950.       tankSum += tank.GetOxygenLevel() * 100;
  951.     else
  952.       cnt--;
  953.   }
  954.  
  955.   if (cnt == 0)
  956.   {
  957.     MMLCDMgr.AddLn(panel, "No " + tankType + " tanks found.");
  958.     return;
  959.   }
  960.  
  961.   percent = tankSum / cnt;
  962.  
  963.   tankType = char.ToUpper(tankType[0]) + tankType.Substring(1);
  964.  
  965.   MMLCDMgr.Add(panel, tankType + " Tanks");
  966.   MMLCDMgr.AddRightAlignLn(panel, percent.ToString("F2") + "%", LCD_LINE_WORK_STATE_POS);
  967.   MMLCDMgr.AddProgressBarLn(panel, percent, FULL_PROGRESS_CHARS);
  968. }
  969.  
  970. public void RunOxygenStatus(MMPanel panel, MMCommand cmd)
  971. {
  972.   double percent;
  973.   MMBlockCollection blocks = new MMBlockCollection();
  974.  
  975.   blocks.AddBlocksOfType("airvent", cmd.nameLike);
  976.   bool found = (blocks.Count() > 0);
  977.  
  978.   for (int i = 0; i < blocks.Count(); i++)
  979.   {
  980.     IMyAirVent vent = blocks.Blocks[i] as IMyAirVent;
  981.     percent = Math.Max(vent.GetOxygenLevel() * 100, 0f);
  982.  
  983.     MMLCDMgr.Add(panel, vent.CustomName);
  984.  
  985.     if (vent.CanPressurize)
  986.       MMLCDMgr.AddRightAlignLn(panel, percent.ToString("F1") + "%", LCD_LINE_WORK_STATE_POS);
  987.     else
  988.       MMLCDMgr.AddRightAlignLn(panel, "Leaking", LCD_LINE_WORK_STATE_POS);
  989.     MMLCDMgr.AddProgressBarLn(panel, percent, FULL_PROGRESS_CHARS);
  990.   }
  991.  
  992.   blocks.Clear();
  993.   blocks.AddBlocksOfType("oxyfarm", cmd.nameLike);
  994.   int cnt = blocks.Count();
  995.   if (cnt > 0)
  996.   {
  997.     double farmSum = 0;
  998.     for (int i = 0; i < cnt; i++)
  999.     {
  1000.       IMyOxygenFarm farm = blocks.Blocks[i] as IMyOxygenFarm;
  1001.       farmSum += farm.GetOutput() * 100;
  1002.     }
  1003.  
  1004.     percent = farmSum / cnt;
  1005.  
  1006.     if (found)
  1007.       MMLCDMgr.AddLn(panel, "");
  1008.  
  1009.     found |= (cnt > 0);
  1010.  
  1011.     MMLCDMgr.Add(panel, "Oxygen Farms");
  1012.     MMLCDMgr.AddRightAlignLn(panel, percent.ToString("F2") + "%", LCD_LINE_WORK_STATE_POS);
  1013.     MMLCDMgr.AddProgressBarLn(panel, percent, FULL_PROGRESS_CHARS);
  1014.   }
  1015.  
  1016.   blocks.Clear();
  1017.   blocks.AddBlocksOfType("oxytank", cmd.nameLike);
  1018.   cnt = blocks.Count();
  1019.  
  1020.   if (cnt == 0)
  1021.   {
  1022.     if (!found)
  1023.       MMLCDMgr.AddLn(panel, "No oxygen blocks found.");
  1024.     return;
  1025.   }
  1026.  
  1027.   double tankSum = 0;
  1028.   int tankCnt = cnt;
  1029.   for (int i = 0; i < cnt; i++)
  1030.   {
  1031.     IMyOxygenTank tank = blocks.Blocks[i] as IMyOxygenTank;
  1032.     if (tank.BlockDefinition.SubtypeId == "" ||
  1033.       tank.BlockDefinition.SubtypeId.Contains("Oxygen")) // only oxygen tanks
  1034.       tankSum += tank.GetOxygenLevel() * 100;
  1035.     else
  1036.       tankCnt--;
  1037.   }
  1038.  
  1039.   if (tankCnt == 0)
  1040.   {
  1041.     if (!found)
  1042.       MMLCDMgr.AddLn(panel, "No oxygen blocks found.");
  1043.     return;
  1044.   }
  1045.  
  1046.   percent = tankSum / tankCnt;
  1047.  
  1048.   if (found)
  1049.     MMLCDMgr.AddLn(panel, "");
  1050.   MMLCDMgr.Add(panel, "Oxygen Tanks");
  1051.   MMLCDMgr.AddRightAlignLn(panel, percent.ToString("F2") + "%", LCD_LINE_WORK_STATE_POS);
  1052.   MMLCDMgr.AddProgressBarLn(panel, percent, FULL_PROGRESS_CHARS);
  1053. }
  1054.  
  1055. public void RunMass(MMPanel panel, MMCommand cmd)
  1056. {
  1057.   MMBlockCollection blocks = new MMBlockCollection();
  1058.   bool simple = (cmd.cmdstr[cmd.cmdstr.Length - 1] == 'x');
  1059.   bool progress = (cmd.cmdstr[cmd.cmdstr.Length - 1] == 'p');
  1060.    
  1061.   blocks.AddBlocksOfNameLike(cmd.nameLike);
  1062.  
  1063.   double used = blocks.GetMassSummary();
  1064.   double total = 0;
  1065.  
  1066.   int argCnt = cmd.args.Count;
  1067.   if (argCnt > 0)
  1068.   {
  1069.     if (cmd.args[0].sub.Count > 0)
  1070.       double.TryParse(cmd.args[0].sub[0].Trim(), out total);
  1071.     if ((argCnt > 1) && (cmd.args[1].sub.Count > 0)) {
  1072.       string unit = cmd.args[1].sub[0].Trim().ToLower();
  1073.       if (unit != "")
  1074.         total *= Math.Pow(1000.0, "kmgtpezy".IndexOf(unit[0]));
  1075.     }
  1076.     total *= 1000.0;
  1077.   }
  1078.  
  1079.   MMLCDMgr.Add(panel, "Cargo Mass: ");
  1080.   if (total <= 0)
  1081.   {
  1082.     MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(used), LCD_LINE_WIDTH);
  1083.     return;
  1084.   }
  1085.  
  1086.   double perc = used / total * 100;
  1087.  
  1088.   if (!simple && !progress)
  1089.   {
  1090.     MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(used) + "g / " + MM.FormatLargeNumber(total) + "g", LCD_LINE_WIDTH);
  1091.     MMLCDMgr.AddProgressBar(panel, perc, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  1092.     MMLCDMgr.AddLn(panel, ' ' + perc.ToString("0.0") + "%");
  1093.   }
  1094.   else if (progress)
  1095.   {
  1096.     MMLCDMgr.AddRightAlignLn(panel, perc.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1097.     MMLCDMgr.AddProgressBarLn(panel, perc, FULL_PROGRESS_CHARS);
  1098.   }
  1099.   else
  1100.     MMLCDMgr.AddRightAlignLn(panel, perc.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1101. }
  1102.  
  1103. public void RunCargoStatus(MMPanel panel, MMCommand cmd)
  1104. {
  1105.   MMBlockCollection blocks = new MMBlockCollection();
  1106.   bool alltypes = cmd.cmdstr.Contains("all");
  1107.   bool simple = (cmd.cmdstr[cmd.cmdstr.Length - 1] == 'x');
  1108.   bool progress = (cmd.cmdstr[cmd.cmdstr.Length - 1] == 'p');
  1109.  
  1110.   if (alltypes)
  1111.     blocks.AddBlocksOfNameLike(cmd.nameLike);
  1112.   else
  1113.     blocks.AddBlocksOfType("cargocontainer",
  1114.       cmd.nameLike);
  1115.  
  1116.   double usedCargo;
  1117.   double totalCargo;
  1118.   double percentCargo = blocks.GetCargoSpaceSummary(
  1119.     out usedCargo, out totalCargo);
  1120.  
  1121.   MMLCDMgr.Add(panel, "Cargo Used: ");
  1122.   if (!simple && !progress)
  1123.   {
  1124.     MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(usedCargo) + "L / " + MM.FormatLargeNumber(totalCargo) + "L", LCD_LINE_WIDTH);
  1125.     MMLCDMgr.AddProgressBar(panel, percentCargo, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  1126.     MMLCDMgr.AddLn(panel, ' ' + percentCargo.ToString("0.0") + "%");
  1127.   }
  1128.   else if (progress)  
  1129.   {
  1130.     MMLCDMgr.AddRightAlignLn(panel, percentCargo.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1131.     MMLCDMgr.AddProgressBarLn(panel, percentCargo, FULL_PROGRESS_CHARS);
  1132.   }
  1133.   else
  1134.     MMLCDMgr.AddRightAlignLn(panel, percentCargo.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1135. }
  1136.  
  1137. // type: simple, progress, normal
  1138. public void ShowPowerOutput(MMPanel panel, MMBlockCollection generators, string title, string type = "normal")
  1139. {
  1140.   double usedPower, totalPower;
  1141.   double percentPower = generators.GetPowerOutput(out usedPower, out totalPower);
  1142.  
  1143.   MMLCDMgr.Add(panel, title + ": ");
  1144.   switch (type)
  1145.   {
  1146.     case "simple":
  1147.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentPower.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1148.       break;
  1149.     case "progress":
  1150.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentPower.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1151.       MMLCDMgr.AddProgressBarLn(panel, percentPower, FULL_PROGRESS_CHARS);
  1152.       break;
  1153.     default:
  1154.       MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(usedPower) + "W / " + MM.FormatLargeNumber(totalPower) + "W", LCD_LINE_WIDTH);
  1155.       MMLCDMgr.AddProgressBar(panel, percentPower, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  1156.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentPower.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1157.       break;
  1158.   }
  1159. }
  1160.  
  1161. public void ShowSolarOutput(MMPanel panel, MMBlockCollection generators, string title, string type = "normal")
  1162. {
  1163.   double usedPower, totalPower;
  1164.   generators.GetPowerOutput(out usedPower, out totalPower);
  1165.   double percentPower = (totalPower > 0 ? (usedPower / totalPower) * 100 : 100);
  1166.  
  1167.   MMLCDMgr.Add(panel, title + ": ");
  1168.   switch (type)
  1169.   {
  1170.     case "simple":
  1171.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentPower.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1172.       break;
  1173.     case "progress":
  1174.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentPower.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1175.       MMLCDMgr.AddProgressBarLn(panel, percentPower, FULL_PROGRESS_CHARS);
  1176.       break;
  1177.     default:
  1178.       MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(usedPower) + "W / " + MM.FormatLargeNumber(totalPower) + "W", LCD_LINE_WIDTH);
  1179.       MMLCDMgr.AddProgressBar(panel, percentPower, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  1180.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentPower.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1181.       break;
  1182.   }
  1183. }
  1184.  
  1185. public void ShowBatteriesInfo(MMPanel panel, MMBlockCollection batteries, string title, bool onlystored = false, string type = "normal")
  1186. {
  1187.   double output, maxOutput, input, maxInput;
  1188.   double stored, maxStored;
  1189.   double percentStored =
  1190.     batteries.GetBatteryStats(
  1191.       out output, out maxOutput,
  1192.       out input, out maxInput,
  1193.       out stored, out maxStored);
  1194.   double percentOutput =  (maxOutput > 0 ? (output / maxOutput) * 100 : 100);
  1195.   double percentInput = (maxInput > 0 ? (input / maxInput) * 100 : 100);
  1196.  
  1197.   if (!onlystored)
  1198.   {
  1199.     if (type != "progress")
  1200.     {
  1201.       MMLCDMgr.Add(panel, title + ": ");
  1202.       MMLCDMgr.AddRightAlignLn(panel, "(IN " + MM.FormatLargeNumber(input) + "W / OUT " + MM.FormatLargeNumber(output) + "W)", LCD_LINE_WIDTH);
  1203.     }
  1204.     else
  1205.       MMLCDMgr.AddLn(panel, title + ": ");
  1206.  
  1207.     MMLCDMgr.Add(panel, "  Stored: ");
  1208.   } else  
  1209.     MMLCDMgr.Add(panel, title + ": ");
  1210.  
  1211.   switch (type)
  1212.   {
  1213.     case "simple":
  1214.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentStored.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1215.       break;
  1216.     case "progress":
  1217.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentStored.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1218.       MMLCDMgr.AddProgressBarLn(panel, percentStored, FULL_PROGRESS_CHARS);
  1219.       break;
  1220.     default:
  1221.       MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(stored) + "Wh / " + MM.FormatLargeNumber(maxStored) + "Wh", LCD_LINE_WIDTH);
  1222.       MMLCDMgr.AddProgressBar(panel, percentStored, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  1223.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentStored.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1224.       break;
  1225.   }
  1226.  
  1227.   if (onlystored)
  1228.     return;
  1229.  
  1230.   MMLCDMgr.Add(panel, "  Output: ");
  1231.   switch (type)
  1232.   {
  1233.     case "simple":
  1234.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentOutput.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1235.       break;
  1236.     case "progress":
  1237.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentOutput.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1238.       MMLCDMgr.AddProgressBarLn(panel, percentOutput, FULL_PROGRESS_CHARS);
  1239.       break;
  1240.     default:
  1241.       MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(output) + "W / " + MM.FormatLargeNumber(maxOutput) + "W", LCD_LINE_WIDTH);
  1242.       MMLCDMgr.AddProgressBar(panel, percentOutput, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  1243.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentOutput.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1244.       break;
  1245.   }
  1246.  
  1247.   MMLCDMgr.Add(panel, "  Input: ");
  1248.   switch (type)
  1249.   {
  1250.     case "simple":
  1251.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentInput.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1252.       break;
  1253.     case "progress":
  1254.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentInput.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1255.       MMLCDMgr.AddProgressBarLn(panel, percentInput, FULL_PROGRESS_CHARS);
  1256.       break;
  1257.     default:
  1258.       MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(input) + "W / " + MM.FormatLargeNumber(maxInput) + "W", LCD_LINE_WIDTH);
  1259.       MMLCDMgr.AddProgressBar(panel, percentInput, FULL_PROGRESS_CHARS, PERCENT_TEXT_SIZE);
  1260.       MMLCDMgr.AddRightAlignLn(panel, ' ' + percentInput.ToString("0.0") + "%", LCD_LINE_WIDTH);
  1261.       break;
  1262.   }
  1263. }
  1264.  
  1265. public void RunPowerStatus(MMPanel panel, MMCommand cmd)
  1266. {
  1267.   MMBlockCollection reactors = new MMBlockCollection();
  1268.   MMBlockCollection solars = new MMBlockCollection();
  1269.   MMBlockCollection batteries = new MMBlockCollection();
  1270.   int got;
  1271.   string displayType = (cmd.cmdstr.EndsWith("x") ? "simple" : (cmd.cmdstr.EndsWith("p") ? "progress" : "normal"));
  1272.   bool issummary = (cmd.cmdstr.StartsWith("powersummary"));
  1273.   bool isstored = (cmd.cmdstr.StartsWith("powerstored"));
  1274.  
  1275.  
  1276.   if (!isstored)
  1277.   {
  1278.     reactors.AddBlocksOfType("reactor", cmd.nameLike);
  1279.     solars.AddBlocksOfType("solarpanel", cmd.nameLike);
  1280.   }
  1281.   batteries.AddBlocksOfType("battery", cmd.nameLike);
  1282.  
  1283.   got = 0;
  1284.   int reactCnt = reactors.Count();
  1285.   int solarCnt = solars.Count();
  1286.   int batteCnt = batteries.Count();
  1287.  
  1288.   if (reactCnt > 0) got++;
  1289.   if (solarCnt > 0) got++;
  1290.   if (batteCnt > 0) got++;
  1291.  
  1292.   if (got < 1)
  1293.   {
  1294.     MMLCDMgr.AddLn(panel, "No power source found!");
  1295.     return;
  1296.   }
  1297.  
  1298.   if (isstored)
  1299.   {
  1300.     ShowBatteriesInfo(panel, batteries, "Batteries", true, displayType);
  1301.     return;
  1302.   }
  1303.  
  1304.   string title = "Total Output";
  1305.  
  1306.   if (!issummary)
  1307.   {
  1308.     if (reactCnt > 0)
  1309.       ShowPowerOutput(panel, reactors, "Reactors", displayType);
  1310.     if (solarCnt > 0)
  1311.       ShowSolarOutput(panel, solars, "Solars", displayType);
  1312.     if (batteCnt > 0)
  1313.       ShowBatteriesInfo(panel, batteries, "Batteries", false, displayType);
  1314.   }
  1315.   else
  1316.   {
  1317.     title = "Power";
  1318.     got = 10; // hack ;)
  1319.   }
  1320.  
  1321.   if (got == 1)
  1322.     return;
  1323.  
  1324.   MMBlockCollection blocks = new MMBlockCollection();
  1325.   blocks.AddFromCollection(reactors);
  1326.   blocks.AddFromCollection(solars);
  1327.   blocks.AddFromCollection(batteries);
  1328.   ShowPowerOutput(panel, blocks, title, displayType);
  1329. }
  1330.  
  1331. public void RunCountdown(MMPanel panel, MMCommand cmd)
  1332. {
  1333.   bool center = cmd.cmdstr.EndsWith("c");
  1334.   bool right = cmd.cmdstr.EndsWith("r");
  1335.  
  1336.   string input = "";
  1337.   int firstSpace = cmd.cmdLine.IndexOf(' ');
  1338.   if (firstSpace >= 0)
  1339.     input = cmd.cmdLine.Substring(firstSpace + 1).Trim();
  1340.  
  1341.   DateTime now = DateTime.Now;
  1342.   DateTime inputt;
  1343.   // 19:02 3.9.2015
  1344.   if (!DateTime.TryParseExact(input, "H:mm d.M.yyyy", System.Globalization.CultureInfo.InvariantCulture,
  1345.     System.Globalization.DateTimeStyles.None, out inputt))
  1346.   {
  1347.     MMLCDMgr.AddLn(panel, "Invalid countdown format, use:");
  1348.     MMLCDMgr.AddLn(panel, "  Countdown 19:02 28.2.2015");
  1349.     return;
  1350.   }
  1351.  
  1352.   TimeSpan dt = inputt - now;
  1353.   string text = "";
  1354.  
  1355.   if (dt.Ticks <= 0)
  1356.     text = "EXPIRED";
  1357.   else
  1358.   {
  1359.     if ((int)dt.TotalDays > 0)
  1360.       text += (int)dt.TotalDays + " days ";
  1361.     if (dt.Hours > 0 || text != "")
  1362.       text += dt.Hours + "h ";
  1363.     if (dt.Minutes > 0 || text != "")
  1364.       text += dt.Minutes + "m ";
  1365.     text += dt.Seconds + "s";
  1366.   }
  1367.   if (center)
  1368.     MMLCDMgr.AddCenterLn(panel, text, LCD_LINE_WIDTH / 2);
  1369.   else if (right)
  1370.     MMLCDMgr.AddRightAlignLn(panel, text, LCD_LINE_WIDTH);
  1371.   else
  1372.     MMLCDMgr.AddLn(panel, text);
  1373. }
  1374.    
  1375. public void RunCurrentTime(MMPanel panel, MMCommand cmd)
  1376. {
  1377.   bool datetime = (cmd.cmdstr.StartsWith("datetime"));
  1378.   bool date = (cmd.cmdstr.StartsWith("date"));
  1379.   bool center = cmd.cmdstr.Contains("c");
  1380.   int offsetIdx = cmd.cmdstr.IndexOf('+');
  1381.   if (offsetIdx < 0)
  1382.     offsetIdx = cmd.cmdstr.IndexOf('-');
  1383.   float offset = 0;
  1384.  
  1385.   if (offsetIdx >= 0)
  1386.     float.TryParse(cmd.cmdstr.Substring(offsetIdx), out offset);
  1387.  
  1388.   DateTime dt = DateTime.Now.AddHours(offset);
  1389.  
  1390.   string text = "";
  1391.   int firstSpace = cmd.cmdLine.IndexOf(' ');
  1392.   if (firstSpace >= 0)
  1393.     text = cmd.cmdLine.Substring(firstSpace + 1);
  1394.   if (!datetime)
  1395.   {
  1396.     if (!date)
  1397.       text += dt.ToShortTimeString();
  1398.     else
  1399.       text += dt.ToShortDateString();
  1400.   }
  1401.   else
  1402.   {
  1403.     if (text == "")
  1404.       text = String.Format("{0:d} {0:t}", dt);
  1405.     else
  1406.     {
  1407.       // try to prevent exceptions
  1408.       text = text.Replace("/", "\\/");
  1409.       text = text.Replace(":", "\\:");
  1410.       text = text.Replace("\"", "\\\"");
  1411.       text = text.Replace("'", "\\'");
  1412.       text = dt.ToString(text + ' ');
  1413.       text = text.Substring(0, text.Length - 1);
  1414.     }
  1415.   }
  1416.  
  1417.   if (center)
  1418.     MMLCDMgr.AddCenterLn(panel, text, LCD_LINE_WIDTH / 2);
  1419.   else
  1420.     MMLCDMgr.AddLn(panel, text);
  1421. }
  1422.  
  1423. private void ShowInventoryLine(MMPanel panel, string msg, double num, int quota)
  1424. {
  1425.   if (quota > 0)
  1426.   {
  1427.     MMLCDMgr.AddProgressBar(panel, Math.Min(100, 100 * num / quota), INV_PROGRESS_CHARS);
  1428.     MMLCDMgr.Add(panel, ' ' + msg + ' ');
  1429.     MMLCDMgr.AddRightAlign(panel, MM.FormatLargeNumber(num), LCD_LINE_INV_NUMBERS_POS);
  1430.     MMLCDMgr.AddLn(panel, " / " + MM.FormatLargeNumber(quota));
  1431.   }
  1432.   else
  1433.   {
  1434.     MMLCDMgr.Add(panel, msg + ':');
  1435.     MMLCDMgr.AddRightAlignLn(panel, MM.FormatLargeNumber(num), LCD_LINE_NUMERS_POS);
  1436.   }
  1437. }
  1438.  
  1439. private void ShowInventoryIngotLine(MMPanel panel, string msg, double num, double numOres, int quota)
  1440. {
  1441.   if (quota > 0)
  1442.   {
  1443.     MMLCDMgr.Add(panel, msg + ' ');
  1444.     MMLCDMgr.AddRightAlign(panel, MM.FormatLargeNumber(num), LCD_LINE_INGOT_NUMBERS_POS);
  1445.     MMLCDMgr.Add(panel, " / " + MM.FormatLargeNumber(quota));
  1446.     MMLCDMgr.AddRightAlignLn(panel, "+" + MM.FormatLargeNumber(numOres) + " ore", LCD_LINE_WIDTH);
  1447.     MMLCDMgr.AddProgressBarLn(panel, Math.Min(100, 100 * num / quota), FULL_PROGRESS_CHARS);
  1448.   }
  1449.   else
  1450.   {
  1451.     MMLCDMgr.Add(panel, msg + ':');
  1452.     MMLCDMgr.AddRightAlign(panel, MM.FormatLargeNumber(num), LCD_LINE_INGOT_NUMBERS_POS);
  1453.     MMLCDMgr.AddRightAlignLn(panel, "+" + MM.FormatLargeNumber(numOres) + " ore", LCD_LINE_WIDTH);
  1454.   }
  1455. }
  1456.  
  1457. public void PrintItemsOfMain(MMPanel panel, MMItemAmounts amounts, bool missing, bool simple, string mainType, string displayType)
  1458. {
  1459.   List<MMAmountSpec> items = amounts.GetAmountsOfMain(mainType);
  1460.   if (items.Count > 0)
  1461.   {
  1462.     if (!simple)
  1463.     {
  1464.       if (MMLCDMgr.GetLCDText(panel).curLine > 0 && MMLCDMgr.GetLCDText(panel).lines[0] != "")
  1465.         MMLCDMgr.AddLn(panel, "");  // add empty line
  1466.       MMLCDMgr.AddCenterLn(panel, "<< " + displayType + " summary >>", LCD_LINE_WIDTH / 2);
  1467.     }
  1468.        
  1469.     for (int i = 0; i < items.Count; i++)
  1470.     {
  1471.       double num = items[i].current;
  1472.  
  1473.       if (missing && num >= items[i].min)
  1474.         continue;
  1475.  
  1476.       int quota = items[i].max;
  1477.       if (missing)
  1478.         quota = items[i].min;
  1479.  
  1480.       string msg = MM.TranslateToDisplay(items[i].subType, items[i].mainType);
  1481.  
  1482.       ShowInventoryLine(panel, msg, num, quota);
  1483.     }
  1484.   }
  1485. }
  1486.  
  1487. public void RunInvListing(MMPanel panel, MMCommand cmd)
  1488. {
  1489.   MMBlockCollection blocks = new MMBlockCollection();
  1490.   bool noexpand = false;
  1491.   bool simple = false;
  1492.   if (cmd.cmdstr[cmd.cmdstr.Length - 1] == 's')
  1493.   {
  1494.     cmd.cmdstr = cmd.cmdstr.Substring(0, cmd.cmdstr.Length - 1);
  1495.     simple = true;
  1496.   }
  1497.   if (cmd.cmdstr[cmd.cmdstr.Length - 1] == 'x')
  1498.   {
  1499.     cmd.cmdstr = cmd.cmdstr.Substring(0, cmd.cmdstr.Length - 1);
  1500.     noexpand = true;
  1501.   }
  1502.  
  1503.   bool missing = (cmd.cmdstr == "missing");
  1504.   bool nocats = (cmd.cmdstr == "invlist");
  1505.  
  1506.   blocks.AddBlocksOfNameLike(cmd.nameLike);
  1507.  
  1508.   MMItemAmounts amounts = new MMItemAmounts();
  1509.   List<MMArgument> args = cmd.args;
  1510.   if (args.Count == 0)
  1511.     args.Add(new MMArgument("all", false));
  1512.  
  1513.   for (int i = 0; i < args.Count; i++)
  1514.   {
  1515.     MMArgument arg = args[i];
  1516.     string mainType = arg.main.ToLower();
  1517.  
  1518.     for (int subi = 0; subi < arg.sub.Count; subi++)
  1519.     {
  1520.       string[] subs = arg.sub[subi].Split(':');
  1521.       double number;
  1522.       MM.Debug("Processing sub arg " + subs[0]);
  1523.  
  1524.       if (subs[0] == "all")
  1525.         subs[0] = "";
  1526.  
  1527.       int min = 1;
  1528.       int max = -1;
  1529.       if (subs.Length > 1)
  1530.       {
  1531.         if (Double.TryParse(subs[1], out number))
  1532.         {
  1533.           if (missing)
  1534.             min = (int)Math.Ceiling(number);
  1535.           else
  1536.             max = (int)Math.Ceiling(number);
  1537.         }
  1538.       }
  1539.  
  1540.       string subfulltype = subs[0];
  1541.       if (mainType != "")
  1542.         subfulltype += ' ' + mainType;
  1543.       amounts.AddSpec(subfulltype, (arg.op == "-"), min, max);
  1544.     }
  1545.   }
  1546.   MM.Debug("All args processed");
  1547.  
  1548.   if (!noexpand)
  1549.   {
  1550.     amounts.ExpandSpecs();
  1551.     MM.Debug("Expanded specs");
  1552.   }
  1553.   MM.Debug("Entering process function");
  1554.   amounts.ProcessItemsFromBlockCollection(blocks);
  1555.   MM.Debug("Processed items from blocks");
  1556.  
  1557.   PrintItemsOfMain(panel, amounts, missing, nocats, "Ore", "Ores");
  1558.   MM.Debug("Printed ores");
  1559.  
  1560.   if (simple)
  1561.     PrintItemsOfMain(panel, amounts, missing, nocats, "Ingot", "Ingots");
  1562.   else
  1563.   {
  1564.     List<MMAmountSpec> ingots = amounts.GetAmountsOfMain("Ingot");
  1565.     if (ingots.Count > 0)
  1566.     {
  1567.       if (!nocats)
  1568.       {
  1569.         if (MMLCDMgr.GetLCDText(panel).curLine > 0 && MMLCDMgr.GetLCDText(panel).lines[0] != "")
  1570.           MMLCDMgr.AddLn(panel, "");  // add empty line
  1571.         MMLCDMgr.AddCenterLn(panel, "<< Ingots summary >>", LCD_LINE_WIDTH / 2);
  1572.       }
  1573.  
  1574.       for (int i = 0; i < ingots.Count; i++)
  1575.       {
  1576.         double num = ingots[i].current;
  1577.  
  1578.         if (missing && num >= ingots[i].min)
  1579.           continue;
  1580.  
  1581.         int quota = ingots[i].max;
  1582.         if (missing)
  1583.           quota = ingots[i].min;
  1584.  
  1585.         string msg = MM.TranslateToDisplay(ingots[i].subType, ingots[i].mainType);
  1586.         if (ingots[i].subType != "Scrap")
  1587.         {
  1588.           double numOres = amounts.GetAmountSpec(ingots[i].subType + " Ore", ingots[i].subType, "Ore").current;
  1589.           ShowInventoryIngotLine(panel, msg, num, numOres, quota);
  1590.         }
  1591.         else
  1592.           ShowInventoryLine(panel, msg, num, quota);
  1593.       }
  1594.     }
  1595.   }
  1596.   MM.Debug("Printed ingots");
  1597.      
  1598.   PrintItemsOfMain(panel, amounts, missing, nocats, "Component", "Components");
  1599.   PrintItemsOfMain(panel, amounts, missing, nocats, "OxygenContainerObject", "Gas");
  1600.   PrintItemsOfMain(panel, amounts, missing, true, "GasContainerObject", "");
  1601.   PrintItemsOfMain(panel, amounts, missing, nocats, "AmmoMagazine", "Ammo");
  1602.   PrintItemsOfMain(panel, amounts, missing, nocats, "PhysicalGunObject", "Tools");
  1603. }
  1604. }
  1605.  
  1606. // MMAPI below (do not modify)  
  1607. public class MMCommand
  1608. {
  1609. public string cmdstr = "";
  1610. public string nameLike = "";
  1611. public string cmdLine;
  1612.  
  1613. public List<MMArgument> args = new List<MMArgument>();
  1614.  
  1615. public MMCommand(string _cmdLine)
  1616. {
  1617.   cmdLine = _cmdLine.TrimStart(' ');
  1618.   if (cmdLine == "")
  1619.     return;
  1620.  
  1621.   string[] targs = cmdLine.Split(' ');
  1622.   string fullArg = "";
  1623.   bool multiWord = false;
  1624.  
  1625.   cmdstr = targs[0].ToLower();
  1626.  
  1627.   for (int i = 1; i < targs.Length; i++)
  1628.   {
  1629.     string arg = targs[i];
  1630.     if (arg == "")
  1631.       continue;
  1632.  
  1633.     if (arg[0] == '{' && arg[arg.Length - 1] == '}')
  1634.     {
  1635.       arg = arg.Substring(1, arg.Length - 2);
  1636.       if (arg == "")
  1637.         continue;
  1638.       if (nameLike == "")
  1639.         nameLike = arg;
  1640.       else
  1641.         args.Add(new MMArgument(arg.ToLower(), false));
  1642.       continue;
  1643.     }
  1644.     if (arg[0] == '{')
  1645.     {
  1646.       multiWord = true;
  1647.       fullArg = arg.Substring(1);
  1648.       continue;
  1649.     }
  1650.     if (arg[arg.Length - 1] == '}')
  1651.     {
  1652.       multiWord = false;
  1653.       fullArg += ' ' + arg.Substring(0, arg.Length - 1);
  1654.       if (nameLike == "")
  1655.         nameLike = fullArg;
  1656.       else
  1657.         args.Add(new MMArgument(fullArg.ToLower(), false));
  1658.       continue;
  1659.     }
  1660.  
  1661.     if (multiWord)
  1662.     {
  1663.       if (fullArg.Length != 0)
  1664.         fullArg += ' ';
  1665.       fullArg += arg;
  1666.       continue;
  1667.     }
  1668.  
  1669.     if (nameLike == "")
  1670.       nameLike = arg;
  1671.     else
  1672.       args.Add(new MMArgument(arg.ToLower()));
  1673.   }
  1674. }
  1675. }
  1676.  
  1677. public class MMArgument
  1678. {
  1679. public string op = "";
  1680. public string main;
  1681. public List<string> sub = new List<string>();
  1682.  
  1683. public MMArgument(string arg, bool parse = true)
  1684. {
  1685.   if (!parse)
  1686.   {
  1687.     main = "";
  1688.     sub.Add(arg);
  1689.     return;
  1690.   }
  1691.  
  1692.   string cur = arg.Trim();
  1693.   if (cur[0] == '+' || cur[0] == '-')
  1694.   {
  1695.     op += cur[0];
  1696.     cur = arg.Substring(1);
  1697.   }
  1698.  
  1699.   string[] parts = cur.Split('/');
  1700.   string subargs = parts[0];
  1701.  
  1702.   if (parts.Length > 1)
  1703.   {
  1704.     main = parts[0];
  1705.     subargs = parts[1];
  1706.   }
  1707.   else
  1708.     main = "";
  1709.  
  1710.   if (subargs.Length > 0)
  1711.   {
  1712.     string[] subs = subargs.Split(',');
  1713.     for (int i = 0; i < subs.Length; i++)
  1714.       if (subs[i] != "")
  1715.         sub.Add(subs[i]);
  1716.   }
  1717. }
  1718. }
  1719.  
  1720. // IMyTerminal reactors collection with useful methods  
  1721. public class MMBlockCollection
  1722. {
  1723. public List<IMyTerminalBlock> Blocks = new List<IMyTerminalBlock>();
  1724.  
  1725. public double GetCargoSpaceSummary(out double usedAmount, out double totalAmount)
  1726. {
  1727.   usedAmount = 0;
  1728.   totalAmount = 0;
  1729.   for (int i = 0; i < Blocks.Count; i++)
  1730.   {
  1731.     IMyInventory inv = Blocks[i].GetInventory(0);
  1732.     if (inv == null)
  1733.       continue;
  1734.  
  1735.     usedAmount += (double)inv.CurrentVolume;
  1736.     totalAmount += (double)inv.MaxVolume;
  1737.   }
  1738.   usedAmount *= 1000;
  1739.   totalAmount *= 1000;
  1740.   return MM.GetPercent(usedAmount, totalAmount);
  1741. }
  1742.  
  1743. public double GetMassSummary()
  1744. {
  1745.   double used = 0;
  1746.   for (int i = 0; i < Blocks.Count; i++) {
  1747.     for (int invId = 0; invId < 2; invId++) {  
  1748.     IMyInventory inv = Blocks[i].GetInventory(invId);
  1749.     if (inv == null)
  1750.       continue;
  1751.  
  1752.     used += (double)inv.CurrentMass;
  1753.     }
  1754.   }
  1755.   return used * 1000;
  1756. }
  1757.  
  1758. public double GetPowerOutput(out double current, out double max)
  1759. {
  1760.   max = 0;
  1761.   current = 0;
  1762.  
  1763.   for (int i = 0; i < Blocks.Count; i++)
  1764.   {
  1765.     IMyBatteryBlock bat = (Blocks[i] as IMyBatteryBlock);
  1766.     List<double> vals = MMStatus.GetDetailedInfoValues(Blocks[i]);
  1767.     if ((bat != null && vals.Count < 6) ||
  1768.       (bat == null && vals.Count < 2))
  1769.       continue;
  1770.  
  1771.     max += vals[0];
  1772.  
  1773.     if (bat != null)
  1774.       current += vals[4];
  1775.     else
  1776.       current += vals[1];
  1777.   }
  1778.   return MM.GetPercent(current, max);
  1779. }
  1780.  
  1781.  
  1782. // returns percent stored
  1783. public double GetBatteryStats(out double output, out double max_output,
  1784.                 out double input, out double max_input,
  1785.                 out double stored, out double max_stored)
  1786. {
  1787.   max_output = 0;
  1788.   output = 0;
  1789.   max_input = 0;
  1790.   input = 0;
  1791.   max_stored = 0;
  1792.   stored = 0;
  1793.  
  1794.   for (int i = 0; i < Blocks.Count; i++)
  1795.   {
  1796.     List<double> vals = MMStatus.GetDetailedInfoValues(Blocks[i]);
  1797.     if (vals.Count < 6)
  1798.       continue;
  1799.  
  1800.     max_output += vals[0];
  1801.     max_input += vals[1];
  1802.     max_stored += vals[2];
  1803.     input += vals[3];
  1804.     output += vals[4];
  1805.     stored += vals[5];
  1806.   }
  1807.   return MM.GetPercent(stored, max_stored);
  1808. }
  1809.  
  1810. // add Blocks with name containing nameLike  
  1811. public void AddBlocksOfNameLike(string nameLike)
  1812. {
  1813.   if (nameLike == "" || nameLike == "*")
  1814.   {
  1815.     List<IMyTerminalBlock> lBlocks = new List<IMyTerminalBlock>();
  1816.     MM._GridTerminalSystem.GetBlocks(lBlocks);
  1817.     Blocks.AddList(lBlocks);
  1818.     return;
  1819.   }
  1820.  
  1821.   string group = (nameLike.StartsWith("G:") ? nameLike.Substring(2).Trim().ToLower() : "");
  1822.   if (group != "")
  1823.   {
  1824.     List<IMyBlockGroup> BlockGroups = new List<IMyBlockGroup>();
  1825.     MM._GridTerminalSystem.GetBlockGroups(BlockGroups);
  1826.     for (int i = 0; i < BlockGroups.Count; i++)
  1827.     {
  1828.       IMyBlockGroup g = BlockGroups[i];
  1829.       if (g.Name.ToLower() == group)
  1830.         Blocks.AddList(g.Blocks);
  1831.     }
  1832.     return;
  1833.   }
  1834.  
  1835.   MM._GridTerminalSystem.SearchBlocksOfName(nameLike, Blocks);
  1836. }
  1837.  
  1838. // add Blocks of type (optional: with name containing nameLike)  
  1839. public void AddBlocksOfType(string type, string nameLike = "")
  1840. {
  1841.   if (nameLike == "" || nameLike == "*")
  1842.   {
  1843.     List<IMyTerminalBlock> blocksOfType = new List<IMyTerminalBlock>();
  1844.     MMBlkMgr.GetBlocksOfType(ref blocksOfType, type);
  1845.     Blocks.AddList(blocksOfType);
  1846.   }
  1847.   else
  1848.   {
  1849.     string group = (nameLike.StartsWith("G:") ? nameLike.Substring(2).Trim().ToLower() : "");
  1850.     if (group != "")
  1851.     {
  1852.       List<IMyBlockGroup> BlockGroups = new List<IMyBlockGroup>();
  1853.       MM._GridTerminalSystem.GetBlockGroups(BlockGroups);
  1854.       for (int i = 0; i < BlockGroups.Count; i++)
  1855.       {
  1856.         IMyBlockGroup g = BlockGroups[i];
  1857.         if (g.Name.ToLower() == group)
  1858.         {
  1859.           for (int j = 0; j < g.Blocks.Count; j++)
  1860.             if (MMBlkMgr.IsBlockOfType(g.Blocks[j], type))
  1861.               Blocks.Add(g.Blocks[j]);
  1862.           return;
  1863.         }
  1864.       }
  1865.       return;
  1866.     }
  1867.     List<IMyTerminalBlock> blocksOfType = new List<IMyTerminalBlock>();
  1868.     MMBlkMgr.GetBlocksOfType(ref blocksOfType, type);
  1869.  
  1870.     for (int i = 0; i < blocksOfType.Count; i++)
  1871.       if (blocksOfType[i].CustomName.Contains(nameLike))
  1872.         Blocks.Add(blocksOfType[i]);
  1873.   }
  1874. }
  1875.  
  1876. // add all Blocks from collection col to this collection  
  1877. public void AddFromCollection(MMBlockCollection col)
  1878. {
  1879.   Blocks.AddList(col.Blocks);
  1880. }
  1881.  
  1882. // clear all reactors from this collection  
  1883. public void Clear()
  1884. {
  1885.   Blocks.Clear();
  1886. }
  1887.  
  1888. // number of reactors in collection  
  1889. public int Count()
  1890. {
  1891.   return Blocks.Count;
  1892. }
  1893. }
  1894.  
  1895. public class MMAmountSpec
  1896. {
  1897. public int min;
  1898. public int max;
  1899. public string subType = "";
  1900. public string mainType = "";
  1901. public bool ignore;
  1902. public double current;
  1903.  
  1904. public MMAmountSpec(bool _ignore = false, int _min = 1, int _max = -1)
  1905. {
  1906.   min = _min;
  1907.   ignore = _ignore;
  1908.   max = _max;
  1909. }
  1910. }
  1911.  
  1912. // Item amounts class
  1913. public class MMItemAmounts
  1914. {
  1915. public MMAmountSpecDict specBySubLower;
  1916. public MMAmountSpecDict specByMainLower;
  1917. public MMAmountSpecDict specByFullLower;
  1918. public bool specAll;
  1919.  
  1920. public MMAmountSpecDict amountByFullType;
  1921.  
  1922. public MMItemAmounts(int size = 20)
  1923. {
  1924.   specBySubLower = new MMAmountSpecDict();
  1925.   specByMainLower = new MMAmountSpecDict();
  1926.   specByFullLower = new MMAmountSpecDict();
  1927.   specAll = false;
  1928.   amountByFullType = new MMAmountSpecDict();
  1929. }
  1930.  
  1931. private bool IsMain(string subarg)
  1932. {
  1933.   return (subarg == "ingot" || subarg == "ore" ||
  1934.     subarg == "component" || subarg == "ammo" ||
  1935.     subarg == "tool" || subarg == "physicalgunobject" ||
  1936.     subarg == "ammomagazine" || subarg == "oxygencontainerobject" ||  
  1937.     subarg == "oxygen" || subarg == "gascontainerobject" || subarg == "gas");
  1938. }
  1939.  
  1940. public void AddSpec(string subfulltype, bool ignore = false, int min = 1, int max = -1)
  1941. {
  1942.   if (subfulltype == "")
  1943.   {
  1944.     specAll = true;
  1945.     return;
  1946.   }
  1947.  
  1948.   string[] parts = subfulltype.Split(' ');
  1949.  
  1950.   string mainType = "";
  1951.   MMAmountSpec spec = new MMAmountSpec(ignore, min, max);
  1952.  
  1953.   if (parts.Length == 2)
  1954.   {
  1955.     mainType = parts[1];
  1956.  
  1957.     if (mainType == "tool")
  1958.       mainType = "physicalgunobject";
  1959.     else
  1960.     if (mainType == "ammo")
  1961.       mainType = "ammomagazine";
  1962.     else
  1963.     if (mainType == "oxygen")
  1964.       mainType = "oxygencontainerobject";
  1965.     else
  1966.     if (mainType == "gas")
  1967.       mainType = "gascontainerobject";
  1968.   }
  1969.      
  1970.   string subType = parts[0].ToLower();
  1971.  
  1972.   if (IsMain(subType))
  1973.   {
  1974.     if (subType == "tool")
  1975.       subType = "physicalgunobject";
  1976.     else
  1977.     if (subType == "ammo")
  1978.       subType = "ammomagazine";
  1979.     else
  1980.     if (subType == "oxygen")
  1981.       subType = "oxygencontainerobject";
  1982.     else
  1983.     if (subType == "gas")
  1984.       subType = "gascontainerobject";
  1985.     spec.mainType = subType;
  1986.  
  1987.     specByMainLower.AddItem(spec.mainType, spec);
  1988.     return;
  1989.   }
  1990.  
  1991.   MM.TranslateToInternal(ref subType, ref mainType);
  1992.   if (mainType == "")
  1993.   {
  1994.     spec.subType = subType.ToLower();
  1995.     specBySubLower.AddItem(spec.subType, spec);
  1996.     return;
  1997.   }
  1998.      
  1999.   spec.subType = subType;
  2000.   spec.mainType = mainType;
  2001.   specByFullLower.AddItem(subType.ToLower() + ' ' + mainType.ToLower(), spec);
  2002. }
  2003.  
  2004. public MMAmountSpec GetSpec(string fullType, string subType, string mainType)
  2005. {
  2006.   MMAmountSpec spec;
  2007.      
  2008.   fullType = fullType.ToLower();
  2009.   spec = specByFullLower.GetItem(fullType);
  2010.   if (spec != null)
  2011.     return spec;
  2012.  
  2013.   subType = subType.ToLower();
  2014.   spec = specBySubLower.GetItem(subType);
  2015.   if (spec != null)
  2016.     return spec;
  2017.  
  2018.   mainType = mainType.ToLower();
  2019.   spec = specByMainLower.GetItem(mainType);
  2020.   if (spec != null)
  2021.     return spec;
  2022.  
  2023.   return null;
  2024. }
  2025.  
  2026. public bool IsIgnored(string fullType, string subType, string mainType)
  2027. {
  2028.   MMAmountSpec spec;
  2029.   bool found = false;
  2030.  
  2031.   spec = specByMainLower.GetItem(mainType.ToLower());
  2032.   if (spec != null)
  2033.   {
  2034.     if (spec.ignore)
  2035.       return true;
  2036.     found = true;
  2037.   }
  2038.   spec = specBySubLower.GetItem(subType.ToLower());
  2039.   if (spec != null)
  2040.   {
  2041.     if (spec.ignore)
  2042.       return true;
  2043.     found = true;
  2044.   }
  2045.   spec = specByFullLower.GetItem(fullType.ToLower());
  2046.   if (spec != null)
  2047.   {
  2048.     if (spec.ignore)
  2049.       return true;
  2050.     found = true;
  2051.   }
  2052.  
  2053.   return !(specAll || found);
  2054. }
  2055.  
  2056. public MMAmountSpec CreateAmountSpec(string fullType, string subType, string mainType)
  2057. {
  2058.   MMAmountSpec amount = new MMAmountSpec();
  2059.  
  2060.   fullType = fullType.ToLower();
  2061.   MMAmountSpec spec = GetSpec(fullType, subType.ToLower(), mainType.ToLower());
  2062.   if (spec != null)
  2063.   {
  2064.     amount.min = spec.min;
  2065.     amount.max = spec.max;
  2066.   }
  2067.   amount.subType = subType;
  2068.   amount.mainType = mainType;
  2069.  
  2070.   amountByFullType.AddItem(fullType, amount);
  2071.  
  2072.   return amount;
  2073. }
  2074.  
  2075. public MMAmountSpec GetAmountSpec(string fullType, string subType, string mainType)
  2076. {
  2077.   MMAmountSpec amount = amountByFullType.GetItem(fullType.ToLower());
  2078.   if (amount == null)
  2079.     amount = CreateAmountSpec(fullType, subType, mainType);
  2080.   return amount;
  2081. }
  2082.  
  2083. public List<MMAmountSpec> GetAmountsOfMain(string mainType)
  2084. {
  2085.   List<MMAmountSpec> result = new List<MMAmountSpec>();
  2086.  
  2087.   for (int i = 0; i < amountByFullType.CountAll(); i++)
  2088.   {
  2089.     MMAmountSpec spec = amountByFullType.GetItemAt(i);
  2090.     if (IsIgnored((spec.subType + ' ' + spec.mainType).ToLower(),  
  2091.         spec.subType, spec.mainType))
  2092.       continue;
  2093.     if (spec.mainType == mainType)
  2094.       result.Add(spec);
  2095.   }
  2096.  
  2097.   return result;
  2098. }
  2099.  
  2100. public void ExpandSpecs()
  2101. {
  2102.   for (int i = 0; i < MMItems.keys.Count; i++)
  2103.   {
  2104.     MMItem item = MMItems.items[MMItems.keys[i]];
  2105.     if (!item.used)
  2106.       continue;
  2107.     string fullType = item.subType + ' ' + item.mainType;
  2108.  
  2109.     if (IsIgnored(fullType, item.subType, item.mainType))
  2110.       continue;
  2111.  
  2112.     MMAmountSpec amount = GetAmountSpec(fullType, item.subType, item.mainType);
  2113.     if (amount.max == -1)
  2114.       amount.max = item.defaultQuota;
  2115.   }
  2116. }
  2117.  
  2118. public void ProcessItemsFromBlockCollection(MMBlockCollection col)
  2119. {
  2120.   for (int i = 0; i < col.Count(); i++)
  2121.   {
  2122.     for (int invId = 0; invId < col.Blocks[i].GetInventoryCount(); invId++)
  2123.     {
  2124.       IMyInventory inv = col.Blocks[i].GetInventory(invId);
  2125.  
  2126.       List<IMyInventoryItem> items = inv.GetItems();
  2127.       for (int j = 0; j < items.Count; j++)
  2128.       {
  2129.         IMyInventoryItem item = items[j];
  2130.         string fullType = MM.GetItemFullType(item);
  2131.         string fullTypeL = fullType.ToLower();
  2132.         string subType, mainType;
  2133.         MM.ParseFullType(fullTypeL, out subType, out mainType);
  2134.  
  2135.         if (mainType == "ore")
  2136.         {
  2137.           if (IsIgnored(subType.ToLower() + " ingot", subType, "Ingot") &&
  2138.             IsIgnored(fullType, subType, mainType))
  2139.             continue;
  2140.         }
  2141.         else
  2142.         {
  2143.           if (IsIgnored(fullType, subType, mainType))
  2144.             continue;
  2145.         }
  2146.  
  2147.         MM.ParseFullType(fullType, out subType, out mainType);
  2148.         MMAmountSpec amount = GetAmountSpec(fullTypeL, subType, mainType);
  2149.         amount.current += (double)item.Amount;
  2150.       }
  2151.     }
  2152.   }
  2153. }
  2154. }
  2155.  
  2156. // MMAPI Helper functions  
  2157. public static class MMBlkMgr
  2158. {
  2159. public static IMyGridTerminalSystem _GridTerminalSystem;
  2160.  
  2161. private static bool IsCryoChamber(IMyTerminalBlock block)
  2162. {
  2163. return block.BlockDefinition.ToString().Contains("Cryo");
  2164. }
  2165.  
  2166. public static void GetBlocksOfExactType(ref List<IMyTerminalBlock> blocks, string exact)
  2167. {
  2168. if (exact == "CargoContainer") _GridTerminalSystem.GetBlocksOfType<IMyCargoContainer>(blocks);
  2169. else if (exact == "TextPanel") _GridTerminalSystem.GetBlocksOfType<IMyTextPanel>(blocks);
  2170. else if (exact == "Assembler") _GridTerminalSystem.GetBlocksOfType<IMyAssembler>(blocks);
  2171. else if (exact == "Refinery") _GridTerminalSystem.GetBlocksOfType<IMyRefinery>(blocks);
  2172. else if (exact == "Reactor") _GridTerminalSystem.GetBlocksOfType<IMyReactor>(blocks);
  2173. else if (exact == "SolarPanel") _GridTerminalSystem.GetBlocksOfType<IMySolarPanel>(blocks);
  2174. else if (exact == "BatteryBlock") _GridTerminalSystem.GetBlocksOfType<IMyBatteryBlock>(blocks);
  2175. else if (exact == "Beacon") _GridTerminalSystem.GetBlocksOfType<IMyBeacon>(blocks);
  2176. else if (exact == "RadioAntenna") _GridTerminalSystem.GetBlocksOfType<IMyRadioAntenna>(blocks);
  2177. else if (exact == "AirVent") _GridTerminalSystem.GetBlocksOfType<IMyAirVent>(blocks);
  2178. else if (exact == "ConveyorSorter") _GridTerminalSystem.GetBlocksOfType<IMyConveyorSorter>(blocks);
  2179. else if (exact == "OxygenTank") _GridTerminalSystem.GetBlocksOfType<IMyOxygenTank>(blocks);
  2180. else if (exact == "OxygenGenerator") _GridTerminalSystem.GetBlocksOfType<IMyOxygenGenerator>(blocks);
  2181. else if (exact == "OxygenFarm") _GridTerminalSystem.GetBlocksOfType<IMyOxygenFarm>(blocks);
  2182. // FIXME!
  2183. else if (exact == "CryoChamber") _GridTerminalSystem.GetBlocksOfType<IMyTerminalBlock>(blocks, IsCryoChamber);
  2184. else if (exact == "LaserAntenna") _GridTerminalSystem.GetBlocksOfType<IMyLaserAntenna>(blocks);
  2185. else if (exact == "Thrust") _GridTerminalSystem.GetBlocksOfType<IMyThrust>(blocks);
  2186. else if (exact == "Gyro") _GridTerminalSystem.GetBlocksOfType<IMyGyro>(blocks);
  2187. else if (exact == "SensorBlock") _GridTerminalSystem.GetBlocksOfType<IMySensorBlock>(blocks);
  2188. else if (exact == "ShipConnector") _GridTerminalSystem.GetBlocksOfType<IMyShipConnector>(blocks);
  2189. else if (exact == "ReflectorLight") _GridTerminalSystem.GetBlocksOfType<IMyReflectorLight>(blocks);
  2190. else if (exact == "InteriorLight") _GridTerminalSystem.GetBlocksOfType<IMyInteriorLight>(blocks);
  2191. else if (exact == "LandingGear") _GridTerminalSystem.GetBlocksOfType<IMyLandingGear>(blocks);
  2192. else if (exact == "ProgrammableBlock") _GridTerminalSystem.GetBlocksOfType<IMyProgrammableBlock>(blocks);
  2193. else if (exact == "TimerBlock") _GridTerminalSystem.GetBlocksOfType<IMyTimerBlock>(blocks);
  2194. else if (exact == "MotorStator") _GridTerminalSystem.GetBlocksOfType<IMyMotorStator>(blocks);
  2195. else if (exact == "PistonBase") _GridTerminalSystem.GetBlocksOfType<IMyPistonBase>(blocks);
  2196. else if (exact == "Projector") _GridTerminalSystem.GetBlocksOfType<IMyProjector>(blocks);
  2197. else if (exact == "ShipMergeBlock") _GridTerminalSystem.GetBlocksOfType<IMyShipMergeBlock>(blocks);
  2198. else if (exact == "SoundBlock") _GridTerminalSystem.GetBlocksOfType<IMySoundBlock>(blocks);
  2199. else if (exact == "Collector") _GridTerminalSystem.GetBlocksOfType<IMyCollector>(blocks);
  2200. else if (exact == "JumpDrive") _GridTerminalSystem.GetBlocksOfType<IMyJumpDrive>(blocks);
  2201. else if (exact == "Door") _GridTerminalSystem.GetBlocksOfType<IMyDoor>(blocks);
  2202. else if (exact == "GravityGeneratorSphere") _GridTerminalSystem.GetBlocksOfType<IMyGravityGeneratorSphere>(blocks);
  2203. else if (exact == "GravityGenerator") _GridTerminalSystem.GetBlocksOfType<IMyGravityGenerator>(blocks);
  2204. else if (exact == "ShipDrill") _GridTerminalSystem.GetBlocksOfType<IMyShipDrill>(blocks);
  2205. else if (exact == "ShipGrinder") _GridTerminalSystem.GetBlocksOfType<IMyShipGrinder>(blocks);
  2206. else if (exact == "ShipWelder") _GridTerminalSystem.GetBlocksOfType<IMyShipWelder>(blocks);
  2207. else if (exact == "LargeGatlingTurret") _GridTerminalSystem.GetBlocksOfType<IMyLargeGatlingTurret>(blocks);
  2208. else if (exact == "LargeInteriorTurret") _GridTerminalSystem.GetBlocksOfType<IMyLargeInteriorTurret>(blocks);
  2209. else if (exact == "LargeMissileTurret") _GridTerminalSystem.GetBlocksOfType<IMyLargeMissileTurret>(blocks);
  2210. else if (exact == "SmallGatlingGun") _GridTerminalSystem.GetBlocksOfType<IMySmallGatlingGun>(blocks);
  2211. else if (exact == "SmallMissileLauncherReload") _GridTerminalSystem.GetBlocksOfType<IMySmallMissileLauncherReload>(blocks);
  2212. else if (exact == "SmallMissileLauncher") _GridTerminalSystem.GetBlocksOfType<IMySmallMissileLauncher>(blocks);
  2213. else if (exact == "VirtualMass") _GridTerminalSystem.GetBlocksOfType<IMyVirtualMass>(blocks);
  2214. else if (exact == "Warhead") _GridTerminalSystem.GetBlocksOfType<IMyWarhead>(blocks);
  2215. else if (exact == "FunctionalBlock") _GridTerminalSystem.GetBlocksOfType<IMyFunctionalBlock>(blocks);
  2216. else if (exact == "LightingBlock") _GridTerminalSystem.GetBlocksOfType<IMyLightingBlock>(blocks);
  2217. else if (exact == "ControlPanel") _GridTerminalSystem.GetBlocksOfType<IMyControlPanel>(blocks);
  2218. else if (exact == "Cockpit") _GridTerminalSystem.GetBlocksOfType<IMyCockpit>(blocks);
  2219. else if (exact == "MedicalRoom") _GridTerminalSystem.GetBlocksOfType<IMyMedicalRoom>(blocks);
  2220. else if (exact == "RemoteControl") _GridTerminalSystem.GetBlocksOfType<IMyRemoteControl>(blocks);
  2221. else if (exact == "ButtonPanel") _GridTerminalSystem.GetBlocksOfType<IMyButtonPanel>(blocks);
  2222. else if (exact == "CameraBlock") _GridTerminalSystem.GetBlocksOfType<IMyCameraBlock>(blocks);
  2223. else if (exact == "OreDetector") _GridTerminalSystem.GetBlocksOfType<IMyOreDetector>(blocks);
  2224. }
  2225.  
  2226. public static void GetBlocksOfType(ref List<IMyTerminalBlock> blocks, string typestr)
  2227. {
  2228. GetBlocksOfExactType(ref blocks, TranslateToExactBlockType(typestr.Trim()));
  2229. }
  2230.  
  2231. public static bool IsBlockOfType(IMyTerminalBlock block, string typestr)
  2232. {
  2233. return block.BlockDefinition.ToString().Contains(TranslateToExactBlockType(typestr));
  2234. }
  2235.  
  2236. public static string TranslateToExactBlockType(string typeInStr)
  2237. {
  2238. typeInStr = typeInStr.ToLower();
  2239.  
  2240. if (typeInStr.StartsWith("carg")  
  2241.   || typeInStr.StartsWith("conta")) return "CargoContainer";
  2242. if (typeInStr.StartsWith("text")  
  2243.   || typeInStr.StartsWith("lcd")) return "TextPanel";
  2244. if (typeInStr.StartsWith("ass"))  return "Assembler";
  2245. if (typeInStr.StartsWith("refi"))   return "Refinery";
  2246. if (typeInStr.StartsWith("reac"))   return "Reactor";
  2247. if (typeInStr.StartsWith("solar"))  return "SolarPanel";
  2248. if (typeInStr.StartsWith("bat"))  return "BatteryBlock";
  2249. if (typeInStr.StartsWith("bea"))  return "Beacon";
  2250. if (typeInStr.Contains("vent"))   return "AirVent";
  2251. if (typeInStr.Contains("sorter"))   return "ConveyorSorter";
  2252. if (typeInStr.Contains("tank"))   return "OxygenTank";
  2253. if (typeInStr.Contains("farm")
  2254.   && typeInStr.Contains("oxy"))   return "OxygenFarm";
  2255. if (typeInStr.Contains("gene")
  2256.   && typeInStr.Contains("oxy"))   return "OxygenGenerator";
  2257. if (typeInStr.Contains("cryo"))   return "CryoChamber";
  2258. if (typeInStr == "laserantenna")  return "LaserAntenna";
  2259. if (typeInStr.Contains("antenna"))  return "RadioAntenna";
  2260. if (typeInStr.StartsWith("thrust")) return "Thrust";
  2261. if (typeInStr.StartsWith("gyro"))   return "Gyro";
  2262. if (typeInStr.StartsWith("sensor")) return "SensorBlock";
  2263. if (typeInStr.Contains("connector")) return "ShipConnector";
  2264. if (typeInStr.StartsWith("reflector")) return "ReflectorLight";
  2265. if ((typeInStr.StartsWith("inter")
  2266.   && typeInStr.EndsWith("light"))) return "InteriorLight";
  2267. if (typeInStr.StartsWith("land"))  return "LandingGear";
  2268. if (typeInStr.StartsWith("program")) return "ProgrammableBlock";
  2269. if (typeInStr.StartsWith("timer"))   return "TimerBlock";
  2270. if (typeInStr.StartsWith("motor"))   return "MotorStator";
  2271. if (typeInStr.StartsWith("piston"))  return "PistonBase";
  2272. if (typeInStr.StartsWith("proj"))  return "Projector";
  2273. if (typeInStr.Contains("merge"))   return "ShipMergeBlock";
  2274. if (typeInStr.StartsWith("sound"))   return "SoundBlock";
  2275. if (typeInStr.StartsWith("col"))   return "Collector";
  2276. if (typeInStr.Contains("jump"))    return "JumpDrive";
  2277. if (typeInStr == "door")       return "Door";
  2278. if ((typeInStr.Contains("grav")
  2279.   && typeInStr.Contains("sphe")))  return "GravityGeneratorSphere";
  2280. if (typeInStr.Contains("grav"))    return "GravityGenerator";
  2281. if (typeInStr.EndsWith("drill"))   return "ShipDrill";
  2282. if (typeInStr.Contains("grind"))   return "ShipGrinder";
  2283. if (typeInStr.EndsWith("welder"))  return "ShipWelder";
  2284. if ((typeInStr.Contains("turret")
  2285.   && typeInStr.Contains("gatl")))  return "LargeGatlingTurret";
  2286. if ((typeInStr.Contains("turret")  
  2287.   && typeInStr.Contains("inter"))) return "LargeInteriorTurret";
  2288. if ((typeInStr.Contains("turret")  
  2289.   && typeInStr.Contains("miss")))  return "LargeMissileTurret";
  2290. if (typeInStr.Contains("gatl"))    return "SmallGatlingGun";
  2291. if ((typeInStr.Contains("launcher")
  2292.   && typeInStr.Contains("reload"))) return "SmallMissileLauncherReload";
  2293. if ((typeInStr.Contains("launcher"))) return "SmallMissileLauncher";
  2294. if (typeInStr.Contains("mass"))    return "VirtualMass";
  2295. if (typeInStr == "warhead")      return "Warhead";
  2296. if (typeInStr.StartsWith("func"))  return "FunctionalBlock";
  2297. if (typeInStr.StartsWith("light"))   return "LightingBlock";
  2298. if (typeInStr.StartsWith("contr"))   return "ControlPanel";
  2299. if (typeInStr.StartsWith("coc"))   return "Cockpit";
  2300. if (typeInStr.StartsWith("medi"))  return "MedicalRoom";
  2301. if (typeInStr.StartsWith("remote"))  return "RemoteControl";
  2302. if (typeInStr.StartsWith("but"))   return "ButtonPanel";
  2303. if (typeInStr.StartsWith("cam"))   return "CameraBlock";
  2304. if (typeInStr.Contains("detect"))  return "OreDetector";
  2305. return "Unknown";
  2306. }
  2307. }
  2308.  
  2309. public static class MMStatus
  2310. {
  2311. public static List<double> GetDetailedInfoValues(IMyTerminalBlock block, int lines = -1)
  2312. {
  2313.   List<double> result = new List<double>();
  2314.  
  2315.   string[] attrLines = block.DetailedInfo.Split('\n');
  2316.   int max = Math.Min(attrLines.Length, (lines > 0 ? lines : attrLines.Length));
  2317.  
  2318.   for (int i = 0; i < max; i++)
  2319.   {
  2320.     string[] parts = attrLines[i].Split(':');
  2321.     // broken line? (try German)
  2322.     if (parts.Length < 2)
  2323.     {
  2324.       parts = attrLines[i].Split('r');
  2325.       // still broken line? (try Portuguese)
  2326.       if (parts.Length < 2)
  2327.         parts = attrLines[i].Split('x');
  2328.     }
  2329.      
  2330.     string valStr = (parts.Length < 2 ? parts[0] : parts[1]);
  2331.     string[] valParts = valStr.Trim().Split(' ');
  2332.     string strVal = valParts[0];
  2333.     char strUnit = (valParts.Length > 1?valParts[1][0]:'.');
  2334.      
  2335.     double val;
  2336.     if (Double.TryParse(strVal, out val))
  2337.     {
  2338.       double finalVal = val * Math.Pow(1000.0, ".kMGTPEZY".IndexOf(strUnit));
  2339.       result.Add(finalVal);
  2340.     }
  2341.   }
  2342.   return result;
  2343. }
  2344.  
  2345. public static string GetLastDetailedValue(IMyTerminalBlock block)
  2346. {
  2347.   string[] infoLines = block.DetailedInfo.Split('\n');
  2348.   string[] stateParts = infoLines[infoLines.Length - 1].Split(':');
  2349.   string state = (stateParts.Length > 1?stateParts[1]:stateParts[0]);
  2350.   return state;
  2351. }
  2352.  
  2353. public static string GetBatteryWorkingString(IMyBatteryBlock battery)
  2354. {
  2355.   string prefix = "";
  2356.   if (battery.GetValueBool("Recharge"))
  2357.     prefix = "(+) ";
  2358.   else
  2359.     if (battery.GetValueBool("Discharge"))
  2360.       prefix = "(-) ";
  2361.     else
  2362.       prefix = "(±) ";
  2363.   return prefix + ((battery.CurrentStoredPower / battery.MaxStoredPower) * 100.0f).ToString("0.0") + "%";
  2364. }
  2365.  
  2366. // Get laser antenna status
  2367. public static string GetLaserAntennaStatus(IMyLaserAntenna gear)
  2368. {
  2369.   string[] infoLines = gear.DetailedInfo.Split('\n');
  2370.   return infoLines[infoLines.Length - 1].Split(' ')[0].ToUpper();
  2371. }
  2372.  
  2373. public static double GetJumpDriveChargeValues(IMyJumpDrive jd, out double cur, out double max)
  2374. {
  2375.   List<double> vals = GetDetailedInfoValues(jd, 5);
  2376.   if (vals.Count < 4) {
  2377.     max = 0;
  2378.     cur = 0;  
  2379.     return 0;
  2380.   }
  2381.  
  2382.   max = vals[1];
  2383.   cur = vals[3];
  2384.  
  2385.   return MM.GetPercent(cur, max);
  2386. }
  2387.  
  2388. public static double GetJumpDriveCharge(IMyJumpDrive jd)
  2389. {
  2390.   List<double> vals = GetDetailedInfoValues(jd, 5);
  2391.   double max = 0, cur = 0;
  2392.   if (vals.Count < 4)
  2393.     return 0;
  2394.  
  2395.   max = vals[1];
  2396.   cur = vals[3];
  2397.  
  2398.   return MM.GetPercent(cur, max);
  2399. }
  2400.  
  2401. // Get landing gear status
  2402. public static string GetLandingGearStatus(IMyLandingGear gear)
  2403. {
  2404.   string unlockchars = "udoesnp";
  2405.  
  2406.   string[] infoLines = gear.DetailedInfo.Split('\n');
  2407.   string attrLine = infoLines[infoLines.Length - 1];
  2408.  
  2409.   string[] attr = attrLine.Split(':');
  2410.  
  2411.   string state;
  2412.   if (attr.Length < 2)
  2413.     state = attr[0].Trim().ToLower();
  2414.   else
  2415.     state = attr[1].Trim().ToLower();
  2416.  
  2417.   if (state == "")
  2418.     return "UNLOCK";
  2419.  
  2420.   // hope it will be more words in other langs too
  2421.   if (state.Split(' ').Length > 1)
  2422.     return "READY";
  2423.  
  2424.   if ((unlockchars.IndexOf(state[0]) < 0) && !state.StartsWith("au"))
  2425.     return "LOCK";
  2426.  
  2427.   return "UNLOCK";
  2428. }
  2429. }
  2430.  
  2431. public static class MM
  2432. {
  2433. public static bool EnableDebug;
  2434. public static IMyGridTerminalSystem _GridTerminalSystem;
  2435. public static MMBlockCollection _DebugTextPanels;
  2436. public static IMyProgrammableBlock Me;
  2437. public static TimeSpan ElapsedTime;
  2438.  
  2439. public static void Init(IMyGridTerminalSystem gridSystem)
  2440. {
  2441.   _GridTerminalSystem = gridSystem;
  2442.   MMBlkMgr._GridTerminalSystem = gridSystem;
  2443.   _DebugTextPanels = new MMBlockCollection();
  2444.   MMStringFunc.InitCharSizes();
  2445.      
  2446.   // prepare debug panels
  2447.   // select all text panels with [DEBUG] in name  
  2448.   if (MM.EnableDebug)
  2449.   {
  2450.     _DebugTextPanels.AddBlocksOfType("textpanel", "[DEBUG]");
  2451.     Debug("DEBUG Panel started.", false, "DEBUG PANEL");
  2452.   }
  2453.  
  2454.   MMItems.Init();
  2455. }
  2456.  
  2457. public static double GetPercent(double current, double max)
  2458. {
  2459.   return (max > 0 ? (current / max) * 100 : 100);
  2460. }
  2461.  
  2462. // return full type of item  
  2463. public static string GetItemFullType(IMyInventoryItem item)
  2464. {
  2465.   string typeid = item.Content.TypeId.ToString();
  2466.  
  2467.   typeid = typeid.Substring(typeid.LastIndexOf('_') + 1);
  2468.  
  2469.   return item.Content.SubtypeName + " " + typeid;
  2470. }
  2471.  
  2472. // parse full type into subType and mainType  
  2473. public static void ParseFullType(string fullType, out string subType, out string mainType)
  2474. {
  2475.   string[] substr = fullType.Split(' ');
  2476.  
  2477.   if (substr.Length == 2)
  2478.   {
  2479.     subType = substr[0];
  2480.     mainType = substr[1];
  2481.     return;
  2482.   }
  2483.  
  2484.   subType = fullType;
  2485.   mainType = "";
  2486. }
  2487.  
  2488. public static string TranslateToDisplay(string fullType)
  2489. {
  2490.   string subType;
  2491.   string mainType;
  2492.   ParseFullType(fullType, out subType, out mainType);
  2493.  
  2494.   return TranslateToDisplay(subType, mainType);
  2495. }
  2496.  
  2497. public static string TranslateToDisplay(string subType, string mainType)
  2498. {
  2499.   MMItem item = MMItems.GetItemOfType(subType, mainType);
  2500.   if (item != null) {
  2501.     if (item.displayName != "")
  2502.       return item.displayName;
  2503.  
  2504.     return item.subType;
  2505.   }
  2506.  
  2507.   return System.Text.RegularExpressions.Regex.Replace(
  2508.     subType, "([a-z])([A-Z])", "$1 $2");
  2509. }
  2510.  
  2511. public static void TranslateToInternal(ref string subType, ref string mainType)
  2512. {
  2513.   string shortName = subType.ToLower();
  2514.   MMItem item;
  2515.  
  2516.   if (MMItems.itemsByShort.TryGetValue(shortName, out item)) {
  2517.     subType = item.subType;
  2518.     mainType = item.mainType;
  2519.     return;
  2520.   }
  2521.  
  2522.   item = MMItems.GetItemOfType(subType, mainType);
  2523.   if (item != null)
  2524.   {
  2525.     subType = item.subType;
  2526.     if (mainType == "Ore" || mainType == "Ingot")
  2527.       return;
  2528.     mainType = item.mainType;
  2529.   }
  2530. }
  2531.  
  2532. public static string FormatLargeNumber(double number, bool compress = true)
  2533. {
  2534.   if (!compress)
  2535.     return number.ToString(
  2536.       "#,###,###,###,###,###,###,###,###,###");
  2537.  
  2538.   string ordinals = " kMGTPEZY";
  2539.   double compressed = number;
  2540.  
  2541.   var ordinal = 0;
  2542.  
  2543.   while (compressed >= 1000)
  2544.   {
  2545.     compressed /= 1000;
  2546.     ordinal++;
  2547.   }
  2548.  
  2549.   string res = Math.Round(compressed, 1, MidpointRounding.AwayFromZero).ToString();
  2550.  
  2551.   if (ordinal > 0)
  2552.     res += " " + ordinals[ordinal];
  2553.  
  2554.   return res;
  2555. }
  2556.  
  2557. public static void WriteLine(IMyTextPanel textpanel, string message, bool append = true, string title = "")
  2558. {
  2559.   textpanel.WritePublicText(message + "\n", append);
  2560.   if (title != "")
  2561.     textpanel.WritePublicTitle(title);
  2562.   textpanel.ShowTextureOnScreen();
  2563.   textpanel.ShowPublicTextOnScreen();
  2564. }
  2565.  
  2566. public static void Debug(string message, bool append = true, string title = "")
  2567. {
  2568.   if (EnableDebug && _DebugTextPanels != null && _DebugTextPanels.Count() != 0)
  2569.     DebugTextPanel(message, append, title);
  2570. }
  2571.  
  2572. public static void DebugTextPanel(string message, bool append = true, string title = "")
  2573. {
  2574.   for (int i = 0; i < _DebugTextPanels.Count(); i++)
  2575.   {
  2576.     IMyTextPanel debugpanel = _DebugTextPanels.Blocks[i] as IMyTextPanel;
  2577.     debugpanel.SetCustomName("[DEBUG] Prog: " + message);
  2578.     WriteLine(debugpanel, message, append, title);
  2579.   }
  2580. }
  2581. }
  2582.  
  2583. public class MMPanel
  2584. {
  2585. // approximate width of LCD panel line
  2586. public const float LCD_LINE_WIDTH = 730;
  2587. public int SCROLL_LINES = 5;
  2588.  
  2589. public MMTextPanelDict panels = new MMTextPanelDict();
  2590. public MMLCDMgr.MMLCDText text;
  2591. public IMyTextPanel first;
  2592.  
  2593. public void SetFontSize(float size)
  2594. {
  2595.   for (int i = 0; i < panels.CountAll(); i++)
  2596.     panels.GetItemAt(i).SetValueFloat("FontSize", size);
  2597. }
  2598.  
  2599. public void SortPanels()
  2600. {
  2601.   panels.SortAll();
  2602.   first = panels.GetItemAt(0);
  2603. }
  2604.  
  2605. public bool IsWide()
  2606. {
  2607.   return (first.BlockDefinition.SubtypeId.Contains("Wide")
  2608.     || first.DefinitionDisplayNameText == "Computer Monitor");
  2609. }
  2610.  
  2611. public void Update()
  2612. {
  2613.   if (text == null)
  2614.     return;
  2615.  
  2616.   int cnt = panels.CountAll();
  2617.  
  2618.   if (cnt > 1)
  2619.     SetFontSize(first.GetValueFloat("FontSize"));
  2620.  
  2621.   for (int i = 0; i < panels.CountAll(); i++)
  2622.   {
  2623.     IMyTextPanel panel = panels.GetItemAt(i);
  2624.     panel.WritePublicText(text.GetDisplayString(i));
  2625.     if (MMLCDMgr.forceRedraw)
  2626.     {
  2627.       panel.ShowTextureOnScreen();
  2628.       panel.ShowPublicTextOnScreen();
  2629.     }
  2630.   }
  2631. }
  2632. }
  2633.  
  2634. public static class MMLCDMgr
  2635. {
  2636. private static Dictionary<IMyTextPanel, MMLCDText> texts = new Dictionary<IMyTextPanel, MMLCDText>();
  2637. public static bool forceRedraw = true;
  2638.  
  2639. public static void SetupLCDText(MMPanel p)
  2640. {
  2641.   MMLCDText lcdText = GetLCDText(p);
  2642.   lcdText.SetFontSize(p.first.GetValueFloat("FontSize"));
  2643.   lcdText.SetNrScreens(p.panels.CountAll());
  2644.   lcdText.widthMod = (p.IsWide() ? 2.0f : 1.0f) * (0.8f / lcdText.fontSize);
  2645.   lcdText.SCROLL_LINES = p.SCROLL_LINES;
  2646. }
  2647.  
  2648. public static MMLCDText GetLCDText(MMPanel p)
  2649. {
  2650.   MMLCDText lcdText;
  2651.   IMyTextPanel panel = p.first;
  2652.  
  2653.   if (!texts.TryGetValue(panel, out lcdText))
  2654.   {
  2655.     lcdText = new MMLCDText();
  2656.     p.text = lcdText;
  2657.     texts.Add(panel, lcdText);
  2658.   }
  2659.  
  2660.   p.text = lcdText;
  2661.   return lcdText;
  2662. }
  2663.  
  2664. public static void AddLn(MMPanel panel, string line)
  2665. {
  2666.   MMLCDText lcd = GetLCDText(panel);
  2667.   lcd.AddLine(line);
  2668. }
  2669.  
  2670. public static void AddMultiLn(MMPanel panel, string multiline)
  2671. {
  2672.   MMLCDText lcd = GetLCDText(panel);
  2673.   lcd.AddMultiLine(multiline);
  2674. }
  2675.  
  2676. public static void Add(MMPanel panel, string text)
  2677. {
  2678.   MMLCDText lcd = GetLCDText(panel);
  2679.   lcd.AddFast(text);
  2680.   lcd.curWidth += MMStringFunc.GetStringSize(text);
  2681. }
  2682.  
  2683. public static void AddRightAlignLn(MMPanel panel, string text, float endScreenX)
  2684. {
  2685.   AddRightAlign(panel, text, endScreenX);
  2686.   AddLn(panel,"");
  2687. }
  2688.  
  2689. public static void AddRightAlign(MMPanel panel, string text, float endScreenX)
  2690. {
  2691.   MMLCDText lcd = GetLCDText(panel);
  2692.  
  2693.   float textWidth = MMStringFunc.GetStringSize(text);
  2694.   endScreenX *= lcd.widthMod;
  2695.   endScreenX -= lcd.curWidth;
  2696.  
  2697.   if (endScreenX < textWidth)
  2698.   {
  2699.     lcd.AddFast(text);
  2700.     lcd.curWidth += textWidth;
  2701.     return;
  2702.   }
  2703.  
  2704.   endScreenX -= textWidth;
  2705.   int fillchars = (int)Math.Round(endScreenX / MMStringFunc.WHITESPACE_WIDTH, MidpointRounding.AwayFromZero);
  2706.   float fillWidth = fillchars * MMStringFunc.WHITESPACE_WIDTH;
  2707.  
  2708.   string filler = new String(' ', fillchars);
  2709.   lcd.AddFast(filler + text);
  2710.   lcd.curWidth += fillWidth + textWidth;
  2711. }
  2712.  
  2713. public static void AddCenterLn(MMPanel panel, string text, float screenX)
  2714. {
  2715.   AddCenter(panel, text, screenX);
  2716.   AddLn(panel, "");
  2717. }
  2718.    
  2719. public static void AddCenter(MMPanel panel, string text, float screenX)
  2720. {
  2721.   MMLCDText lcd = GetLCDText(panel);
  2722.   float textWidth = MMStringFunc.GetStringSize(text);
  2723.   screenX *= lcd.widthMod;
  2724.   screenX -= lcd.curWidth;
  2725.  
  2726.   if (screenX < textWidth / 2)
  2727.   {
  2728.     lcd.AddFast(text);
  2729.     lcd.curWidth += textWidth;
  2730.     return;
  2731.   }
  2732.  
  2733.   screenX -= textWidth / 2;
  2734.   int fillchars = (int)Math.Round(screenX / MMStringFunc.WHITESPACE_WIDTH, MidpointRounding.AwayFromZero);
  2735.   float fillWidth = fillchars * MMStringFunc.WHITESPACE_WIDTH;
  2736.  
  2737.   string filler = new String(' ', fillchars);
  2738.   lcd.AddFast(filler + text);
  2739.   lcd.curWidth += fillWidth + textWidth;
  2740. }
  2741.  
  2742. public static void AddProgressBarLn(MMPanel panel, double percent, int width = 22, float leaveSpaceX = 0f)
  2743. {
  2744.   AddProgressBar(panel, percent, width, leaveSpaceX);
  2745.   AddLn(panel, "");
  2746. }
  2747.  
  2748. public static void AddProgressBar(MMPanel panel, double percent, int width = 22, float leaveSpaceX = 0f)
  2749. {
  2750.   MMLCDText lcd = GetLCDText(panel);
  2751.   int totalBars = (int)(width * lcd.widthMod) - 2 - (int)(leaveSpaceX / MMStringFunc.PROGRESSCHAR_WIDTH);
  2752.   int fill = (int)(percent * totalBars) / 100;
  2753.   if (fill > totalBars)
  2754.     fill = totalBars;
  2755.   string progress = "[" + new String('|', fill) + new String('\'', totalBars - fill) + "]";
  2756.  
  2757.   lcd.AddFast(progress);
  2758.   lcd.curWidth += MMStringFunc.PROGRESSCHAR_WIDTH * totalBars + 18f;
  2759. }
  2760.  
  2761. public static void ClearText(MMPanel panel)
  2762. {
  2763.   GetLCDText(panel).ClearText();
  2764. }
  2765.  
  2766. public static void UpdatePanel(MMPanel panel)
  2767. {
  2768.   panel.Update();
  2769.   GetLCDText(panel).Scroll();
  2770. }
  2771.  
  2772. public class MMLCDText
  2773. {
  2774. public int SCROLL_LINES = 5;
  2775. public float fontSize = 0.8f;
  2776. public float widthMod = 1.0f;
  2777. public int scrollPos;
  2778. public int scrollDir = 1;
  2779. public int DisplayLines = 22; // 22 for font size 0.8
  2780. public int screens = 1;
  2781.  
  2782. public List<string> lines = new List<string>();
  2783. public int curLine;
  2784. public float curWidth;
  2785.  
  2786. public MMLCDText(float fontSize = 0.8f)
  2787. {
  2788.   SetFontSize(fontSize);
  2789.   lines.Add("");
  2790. }
  2791.  
  2792. public void SetFontSize(float size)
  2793. {
  2794.   fontSize = size;
  2795.   DisplayLines = (int)Math.Round(22 * (0.8 / fontSize) * screens);
  2796. }
  2797.  
  2798. public void SetNrScreens(int cnt)
  2799. {
  2800.   screens = cnt;
  2801.   DisplayLines = (int)Math.Round(22 * (0.8 / fontSize) * screens);
  2802. }
  2803.  
  2804. public void AddFast(string text)
  2805. {
  2806.   lines[curLine] += text;
  2807. }
  2808.  
  2809. public void AddMultiLine(string multiline)
  2810. {
  2811.   string[] lines = multiline.Split('\n');
  2812.  
  2813.   for (int i = 0; i < lines.Length; i++)
  2814.     AddLine(lines[i]);
  2815. }
  2816.  
  2817. public void AddLine(string line)
  2818. {
  2819.   lines[curLine] += line;
  2820.   lines.Add("");
  2821.   curLine++;
  2822.   curWidth = 0;
  2823. }
  2824.  
  2825. public void ClearText()
  2826. {
  2827.   lines.Clear();
  2828.   lines.Add("");
  2829.   curWidth = 0;
  2830.   curLine = 0;
  2831. }
  2832.  
  2833. public string GetFullString()
  2834. {
  2835.   return String.Join("\n", lines);
  2836. }
  2837.  
  2838. // Display only X lines from scrollPos
  2839. public string GetDisplayString(int screenidx = 0)
  2840. {
  2841.   if (lines.Count < DisplayLines / screens)
  2842.   {
  2843.     if (screenidx != 0) return "";
  2844.     scrollPos = 0;
  2845.     scrollDir = 1;
  2846.     return GetFullString();
  2847.   }
  2848.  
  2849.   int pos = scrollPos + screenidx * (DisplayLines / screens);
  2850.   if (pos > lines.Count)
  2851.     pos = lines.Count;
  2852.  
  2853.   List<string> display =
  2854.     lines.GetRange(pos,
  2855.       Math.Min(lines.Count - pos, DisplayLines / screens));
  2856.  
  2857.   return String.Join("\n", display);
  2858. }
  2859.  
  2860. public void Scroll()
  2861. {
  2862.   int linesCnt = lines.Count - 1;
  2863.   if (linesCnt <= DisplayLines)
  2864.   {
  2865.     scrollPos = 0;
  2866.     scrollDir = 1;
  2867.     return;
  2868.   }
  2869.  
  2870.   if (scrollDir > 0)
  2871.   {
  2872.     if (scrollPos + SCROLL_LINES + DisplayLines > linesCnt)
  2873.     {
  2874.       scrollDir = -1;
  2875.       scrollPos = Math.Max(linesCnt - DisplayLines, 0);
  2876.       return;
  2877.     }
  2878.  
  2879.     scrollPos += SCROLL_LINES;
  2880.   }
  2881.   else
  2882.   {
  2883.     if (scrollPos - SCROLL_LINES < 0)
  2884.     {
  2885.       scrollPos = 0;
  2886.       scrollDir = 1;
  2887.       return;
  2888.     }
  2889.  
  2890.     scrollPos -= SCROLL_LINES;
  2891.   }
  2892. }
  2893. }
  2894. }
  2895.  
  2896. public static class MMStringFunc
  2897. {
  2898. private static Dictionary<char, float> charSize = new Dictionary<char, float>();
  2899.  
  2900. public const float WHITESPACE_WIDTH = 8f;
  2901. public const float PROGRESSCHAR_WIDTH = 6.4f;
  2902.  
  2903. public static void InitCharSizes()
  2904. {
  2905.   if (charSize.Count > 0)
  2906.     return;
  2907.  
  2908.   AddCharsSize("3FKTabdeghknopqsuy£µÝàáâãäåèéêëðñòóôõöøùúûüýþÿāăąďđēĕėęěĝğġģĥħĶķńņňʼnōŏőśŝşšŢŤŦũūŭůűųŶŷŸșȚЎЗКЛбдекруцяёђћўџ", 17f);
  2909.   AddCharsSize("#0245689CXZ¤¥ÇßĆĈĊČŹŻŽƒЁЌАБВДИЙПРСТУХЬ€", 19f);
  2910.   AddCharsSize("$&GHPUVY§ÙÚÛÜÞĀĜĞĠĢĤĦŨŪŬŮŰŲОФЦЪЯжы†‡", 20f);
  2911.   AddCharsSize("ABDNOQRSÀÁÂÃÄÅÐÑÒÓÔÕÖØĂĄĎĐŃŅŇŌŎŐŔŖŘŚŜŞŠȘЅЊЖф□", 21f);
  2912.   AddCharsSize("(),.1:;[]ft{}·ţťŧț", 9f);
  2913.   AddCharsSize("+<=>E^~¬±¶ÈÉÊË×÷ĒĔĖĘĚЄЏЕНЭ−", 18f);
  2914.   AddCharsSize(" !I`ijl ¡¨¯´¸ÌÍÎÏìíîïĨĩĪīĮįİıĵĺļľłˆˇ˘˙˚˛˜˝ІЇії‹›∙", 8f);
  2915.   AddCharsSize("7?Jcz¢¿çćĉċčĴźżžЃЈЧавийнопсъьѓѕќ", 16f);
  2916.   AddCharsSize("L_vx«»ĹĻĽĿŁГгзлхчҐ–•", 15f);
  2917.   AddCharsSize("\"-rª­ºŀŕŗř", 10f);
  2918.   AddCharsSize("mw¼ŵЮщ", 27f);
  2919.   AddCharsSize("MМШ", 26f);
  2920.   AddCharsSize("WÆŒŴ—…‰", 31f);
  2921.   AddCharsSize("'|¦ˉ‘’‚", 6f);
  2922.   AddCharsSize("*²³¹", 11f);
  2923.   AddCharsSize("\\°“”„", 12f);
  2924.   AddCharsSize("/ijтэє", 14f);
  2925.   AddCharsSize("%IJЫ", 24f);
  2926.   AddCharsSize("@©®мшњ", 25f);
  2927.   AddCharsSize("\n", 0f);
  2928.   AddCharsSize("¾æœЉ", 28f);
  2929.   AddCharsSize("½Щ", 29f);
  2930.   AddCharsSize("ј", 7f);
  2931.   AddCharsSize("љ", 22f);
  2932.   AddCharsSize("ґ", 13f);
  2933.   AddCharsSize("ю", 23f);
  2934.   AddCharsSize("™", 30f);
  2935.   AddCharsSize("", 34f);
  2936.   AddCharsSize("", 32f);
  2937.   AddCharsSize("", 41f);
  2938. }
  2939.  
  2940. private static void AddCharsSize(string chars, float size)
  2941. {
  2942.   for (int i = 0; i < chars.Length; i++)
  2943.     charSize.Add(chars[i], size);
  2944. }
  2945.  
  2946. public static float GetCharSize(char c)
  2947. {
  2948.   float width = 40;
  2949.   charSize.TryGetValue(c, out width);
  2950.  
  2951.   return width;
  2952. }
  2953.  
  2954. public static float GetStringSize(string str)
  2955. {
  2956.   float sum = 0;
  2957.   for (int i = 0; i < str.Length; i++)
  2958.     sum += GetCharSize(str[i]);
  2959.  
  2960.   return sum;
  2961. }
  2962.  
  2963. public static string GetStringTrimmed(string text, float pixelWidth)
  2964. {
  2965.   int trimlen = Math.Min((int)pixelWidth / 14, text.Length - 2);
  2966.   float stringSize = GetStringSize(text);
  2967.   if (stringSize <= pixelWidth)
  2968.     return text;
  2969.  
  2970.   while (stringSize > pixelWidth - 20)
  2971.   {
  2972.     text = text.Substring(0, trimlen);
  2973.     stringSize = GetStringSize(text);
  2974.     trimlen -= 2;
  2975.   }
  2976.   return text + "..";
  2977. }
  2978. }
  2979.  
  2980.  
  2981. public class MMItem
  2982. {
  2983. public string subType;
  2984. public string mainType;
  2985.  
  2986. public int defaultQuota;
  2987. public string displayName;
  2988. public string shortName;
  2989.  
  2990. public bool used;
  2991.  
  2992. public MMItem(string _subType, string _mainType, int _defaultQuota = 0, string _displayName = "", string _shortName = "", bool _used = true)
  2993. {
  2994.   subType = _subType;
  2995.   mainType = _mainType;
  2996.   defaultQuota = _defaultQuota;
  2997.   displayName = _displayName;
  2998.   shortName = _shortName;
  2999.   used = _used;
  3000. }
  3001. }
  3002. public class MMPanelDict
  3003. {
  3004.   public Dictionary<string, MMPanel> dict = new Dictionary<string, MMPanel>();
  3005.   public List<string> keys = new List<string>();
  3006.  
  3007.   public void AddItem(string key, MMPanel item) { if (!dict.ContainsKey(key)) { keys.Add(key); dict.Add(key, item); } }
  3008.   public int CountAll() { return dict.Count; }
  3009.   public MMPanel GetItem(string key) { if (dict.ContainsKey(key)) return dict[key]; return null; }
  3010.   public MMPanel GetItemAt(int index) { return dict[keys[index]]; }
  3011.   public void ClearAll() { keys.Clear(); dict.Clear(); }
  3012.   public void SortAll() { keys.Sort(); }
  3013. }
  3014. public class MMTextPanelDict
  3015. {
  3016.   public Dictionary<string, IMyTextPanel> dict = new Dictionary<string, IMyTextPanel>();
  3017.   public List<string> keys = new List<string>();
  3018.  
  3019.   public void AddItem(string key, IMyTextPanel item) { if (!dict.ContainsKey(key)) { keys.Add(key); dict.Add(key, item); } }
  3020.   public int CountAll() { return dict.Count; }
  3021.   public IMyTextPanel GetItem(string key) { if (dict.ContainsKey(key)) return dict[key]; return null; }
  3022.   public IMyTextPanel GetItemAt(int index) { return dict[keys[index]]; }
  3023.   public void ClearAll() { keys.Clear(); dict.Clear(); }
  3024.   public void SortAll() { keys.Sort(); }
  3025. }
  3026. public class MMAmountSpecDict
  3027. {
  3028.   public Dictionary<string, MMAmountSpec> dict = new Dictionary<string, MMAmountSpec>();
  3029.   public List<string> keys = new List<string>();
  3030.  
  3031.   public void AddItem(string key, MMAmountSpec item) { if (!dict.ContainsKey(key)) { keys.Add(key); dict.Add(key, item); } }
  3032.   public int CountAll() { return dict.Count; }
  3033.   public MMAmountSpec GetItem(string key) { if (dict.ContainsKey(key)) return dict[key]; return null; }
  3034.   public MMAmountSpec GetItemAt(int index) { return dict[keys[index]]; }
  3035.   public void ClearAll() { keys.Clear(); dict.Clear(); }
  3036.   public void SortAll() { keys.Sort(); }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement