Advertisement
klassekatze

Store Script

Aug 10th, 2023
1,920
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.02 KB | None | 0 0
  1. /*
  2.  * R e a d m e
  3.  * -----------
  4.  *
  5.  * In this file you can include any instructions or other comments you want to have injected onto the
  6.  * top of your final script. You can safely delete this file if you do not want any such comments.
  7.  */
  8.  
  9. // This file contains your actual script.
  10. //
  11. // You can either keep all your code here, or you can create separate
  12. // code files to make your program easier to navigate while coding.
  13. //
  14. // In order to add a new utility class, right-click on your project,
  15. // select 'New' then 'Add Item...'. Now find the 'Space Engineers'
  16. // category under 'Visual C# Items' on the left hand side, and select
  17. // 'Utility Class' in the main area. Name it in the box below, and
  18. // press OK. This utility class will be merged in with your code when
  19. // deploying your final script.
  20. //
  21. // You can also simply create a new utility class manually, you don't
  22. // have to use the template if you don't want to. Just do so the first
  23. // time to see what a utility class looks like.
  24. //
  25. // Go to:
  26. // https://github.com/malware-dev/MDK-SE/wiki/Quick-Introduction-to-Space-Engineers-Ingame-Scripts
  27. //
  28. // to learn more about ingame scripts.
  29.  
  30. public Program()
  31. {
  32.     set();
  33.     Runtime.UpdateFrequency = UpdateFrequency.Update100;
  34. }
  35. public bool isThisShips(IMyTerminalBlock b)
  36. {
  37.     return b.OwnerId == Me.OwnerId && b.IsFunctional && b.CubeGrid == Me.CubeGrid && b.IsSameConstructAs(Me);
  38. }
  39.  
  40.  
  41. public class Order
  42. {
  43.     public static int QUANTITY_ALL = 10000000;
  44.     public string name = "";
  45.     public int price=0;
  46.     public int quantity=0;
  47.     public Order(string name, int price, int quantity)
  48.     {
  49.         this.name = name;
  50.         this.price = price;
  51.         this.quantity = quantity;
  52.     }
  53.     public Order(string line)
  54.     {
  55.         string[] lr = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  56.         if (lr.Length >= 4)
  57.         {
  58.             int p = 0;
  59.             int.TryParse(lr[3], out p);
  60.             if (lr[0] == "BUY") p = -p;
  61.             string item = lr[1];
  62.             name = item;
  63.             price = p;
  64.             string quant = lr[2];
  65.             if (quant == "ALL") quantity = QUANTITY_ALL;
  66.             else
  67.             {
  68.                 int.TryParse(quant, out quantity);
  69.             }
  70.         }
  71.     }
  72. }
  73.  
  74. //Dictionary<string, int> prices = new Dictionary<string, int>();
  75. List<Order> orders = new List<Order>();
  76.  
  77. Order getOrderByName(string n)
  78. {
  79.     foreach (Order o in orders)
  80.     {
  81.         if (o.name == n) return o;
  82.     }
  83.     return null;
  84. }
  85. int getStock(string n, AggregateInventoryInterface inv)
  86. {
  87.     foreach (var kvp in inv.items)
  88.     {
  89.         string iname = isyname(kvp.Key);
  90.         if (iname == n) return kvp.Value;
  91.     }
  92.     return 0;
  93. }
  94.  
  95. void readprices()
  96. {
  97.     orders.Clear();
  98.     string[] lines = Me.CustomData.Split('\n');
  99.     foreach (string line in lines)
  100.     {
  101.         if (line.StartsWith("#")) continue;
  102.         Order o = new Order(line);
  103.         if (o.name != "") orders.Add(o);
  104.         /*string[] lr = line.Split(new char[] { ' ' },StringSplitOptions.RemoveEmptyEntries);
  105.                 if (lr.Length >= 4)
  106.                 {
  107.                     int price = 0;
  108.                     int.TryParse(lr[4],out price);
  109.                     if (lr[0] == "BUY") price = -price;
  110.                     string key = lr[1];
  111.                     prices[key] = price;
  112.                 }*/
  113.     }
  114. }
  115. string isyname(MyItemType t)
  116. {
  117.     return t.TypeId + "/" + t.SubtypeId;
  118. }
  119. void writeprices()
  120. {
  121.     string str = "#BUY/SELL ITEMID QUANTITY PRICE\n#\n";
  122.     foreach (Order o in orders)
  123.     {
  124.         if (o.name.Trim() != "")
  125.         {
  126.             int price = o.price;
  127.             if (price == 0) str += "UNSET ";
  128.             else if (price < 0)
  129.             {
  130.                 price = -price;
  131.                 str += "BUY  ";
  132.             }
  133.             else str += "SELL ";
  134.             str += o.name + " ";
  135.             if (o.quantity >= Order.QUANTITY_ALL) str += "ALL";
  136.             else str += o.quantity.ToString();
  137.             str += " ";
  138.             str += price + "\n";
  139.         }
  140.     }
  141.     Me.CustomData = str;
  142. }
  143. /*MyTuple<MyItemType, int> getkvp(string n, AggregateInventoryInterface inv)
  144.         {
  145.             foreach(var kvp in inv.items)
  146.             {
  147.                 string iname = isyname(kvp.Key);
  148.                 if (iname == n) return new MyTuple<MyItemType, int>(kvp.Key,kvp.Value);
  149.             }
  150.             return new MyTuple<MyItemType, int>(null,0);
  151.         }*/
  152.  
  153. public void set()
  154. {
  155.     IMyTextSurface log = Me.GetSurface(0);
  156.     log.ContentType = ContentType.TEXT_AND_IMAGE;
  157.     log.WriteText("");
  158.     List<IMyCargoContainer> cargo = new List<IMyCargoContainer>();
  159.     GridTerminalSystem.GetBlocksOfType<IMyCargoContainer>(cargo, delegate (IMyCargoContainer b) { return isThisShips(b); });
  160.     AggregateInventoryInterface inv = new AggregateInventoryInterface();
  161.     inv.setContainers(cargo);
  162.     inv.update(true);
  163.  
  164.     readprices();
  165.     foreach (var k in inv.items)
  166.     {
  167.         string n = isyname(k.Key);
  168.         Order o = getOrderByName(n);
  169.         if (o == null) orders.Add(new Order(n, 0, Order.QUANTITY_ALL));
  170.     }
  171.     writeprices();
  172.     List<IMyStoreBlock> s = new List<IMyStoreBlock>();
  173.     GridTerminalSystem.GetBlocksOfType<IMyStoreBlock>(s, delegate (IMyStoreBlock b) { return isThisShips(b); });
  174.     if (s.Count > 0)
  175.     {
  176.         var store = s[0];
  177.         List<MyStoreQueryItem> cur = new List<MyStoreQueryItem>();
  178.         store.GetPlayerStoreItems(cur);
  179.         foreach (var i in cur)
  180.         {
  181.             store.CancelStoreItem(i.Id);
  182.         }
  183.         foreach (Order o in orders)
  184.         {
  185.             if (o.price != 0)
  186.             {
  187.                 //var i = k.Key;
  188.                 MyDefinitionId definitionId;
  189.                 if (MyDefinitionId.TryParse(o.name, out definitionId))
  190.                 {
  191.                     long nid = -1;
  192.  
  193.                     if (o.price > 0)
  194.                     {
  195.                         int quantity = o.quantity;
  196.                         int stock = getStock(o.name, inv);
  197.                         if (stock < quantity) quantity = stock;
  198.                         var si = new MyStoreItemDataSimple(definitionId, quantity, o.price);
  199.                         store.InsertOffer(si, out nid);
  200.                     }
  201.                     else if (o.price < 0)
  202.                     {
  203.                         var si = new MyStoreItemDataSimple(definitionId, o.quantity, -o.price);
  204.                         store.InsertOrder(si, out nid);
  205.                     }
  206.                     if (nid != -1) log.WriteText("added " + o.name + "\n", true);
  207.                     else log.WriteText("fail added " + o.name + "\n", true);
  208.                 }
  209.             }
  210.             else
  211.             {
  212.                 log.WriteText("no price set for " + o.name+"\n", true);
  213.             }
  214.             //getStock(string n, AggregateInventoryInterface inv)
  215.         }
  216.     }
  217. }
  218. int lastUpdateTick = 0;
  219. int tick = 0;
  220.  
  221. DateTime lastUpd = DateTime.MinValue;
  222. public void Main(string argument, UpdateType updateSource)
  223. {
  224.     tick += 100;
  225.     if (argument == "set")
  226.     {
  227.         set();
  228.     }
  229.     if((DateTime.Now - lastUpd).TotalMinutes > 5)
  230.     {
  231.         lastUpd = DateTime.Now;
  232.         lastUpdateTick = tick;
  233.         set();
  234.     }
  235. }
  236.  
  237.  
  238. //can generate an inventory from a bunch of inventories, and can simplify programmatically sending stuff between such groupings.
  239. //the most immediate use here is automatically unstuffing grinders, stuffing torpedo launchers and other weapons, and sending excess garbage to connectors for ejection from the ship.
  240. //this interface doesn't recognize partial items, only whole units / integers.
  241. class AggregateInventoryInterface
  242. {
  243.     int tickOffset = 0;
  244.     static int offseti = 0;
  245.     public AggregateInventoryInterface()
  246.     {
  247.         tickOffset = offseti;
  248.         offseti += 10;
  249.     }
  250.     /*public void setContainers(List<IMyTerminalBlock> c)
  251.             {
  252.                 containers = c;
  253.             }*/
  254.     public void setContainers<T>(List<T> c) where T : IMyTerminalBlock
  255.     {
  256.         containers.Clear();
  257.         foreach (T i in c)
  258.         {
  259.             containers.Add(i);
  260.         }
  261.     }
  262.     List<IMyTerminalBlock> containers = new List<IMyTerminalBlock>();
  263.     public Dictionary<MyItemType, int> items = new Dictionary<MyItemType, int>();
  264.  
  265.     int updateInterval = 60 * 3;
  266.     int lastUpdateTick = 0;
  267.     int tick = 0;
  268.     //if called every tick will update the inventory manifest every 3 seconds.
  269.     //may not be necessary - a force update is best before doing anything important.
  270.     public void update(bool force = false, int ticks = 1)
  271.     {
  272.         tick += ticks;
  273.         if (tick + tickOffset - lastUpdateTick > updateInterval || force)
  274.         {
  275.             lastUpdateTick = tick;
  276.             items.Clear();
  277.             foreach (IMyTerminalBlock t in containers)
  278.             {
  279.                 for (int i = 0; i < t.InventoryCount; i++)
  280.                 {
  281.                     var inv = t.GetInventory(i);
  282.                     List<MyInventoryItem> t_items = new List<MyInventoryItem>();
  283.                     inv.GetItems(t_items);
  284.                     foreach (MyInventoryItem item in t_items)
  285.                     {
  286.                         if (!items.ContainsKey(item.Type)) items[item.Type] = (int)Math.Floor((double)item.Amount);
  287.                         else items[item.Type] += (int)Math.Floor((double)item.Amount);
  288.                     }
  289.                 }
  290.             }
  291.         }
  292.     }
  293.     //these return the amount of items that could not be sent (unavailable, no room, whatever). Ergo, 0 means all were transferred.
  294.     public int TransferItemTo(MyItemType type, int amount_to_transfer, IMyInventory destination)
  295.     {
  296.         float unit_volume = type.GetItemInfo().Volume;
  297.         foreach (IMyTerminalBlock t in containers)
  298.         {
  299.             for (int i = 0; i < t.InventoryCount; i++)
  300.             {
  301.                 var inv = t.GetInventory(i);
  302.                 List<MyInventoryItem> t_items = new List<MyInventoryItem>();
  303.                 inv.GetItems(t_items);
  304.                 foreach (MyInventoryItem item in t_items)
  305.                 {
  306.                     if (item.Type == type)
  307.                     {
  308.                         int transfer_amt = (int)Math.Floor((double)item.Amount);
  309.  
  310.                         int max_room_for = (int)Math.Floor((double)(destination.MaxVolume - destination.CurrentVolume + (MyFixedPoint)0.001) / unit_volume);
  311.  
  312.                         if (max_room_for < transfer_amt) transfer_amt = max_room_for;
  313.  
  314.                         if (transfer_amt > amount_to_transfer) transfer_amt = amount_to_transfer;
  315.                         //log(">sending " + transfer_amt + " of " + item.Type.SubtypeId);
  316.  
  317.  
  318.                         if (inv.TransferItemTo(destination, item, transfer_amt)) amount_to_transfer -= transfer_amt;
  319.                         if (amount_to_transfer <= 0) return 0;
  320.                     }
  321.                 }
  322.             }
  323.         }
  324.         return amount_to_transfer;
  325.     }
  326.     //these return the amount of items that could not be sent (unavailable, no room, whatever). Ergo, 0 means all were transferred.
  327.     public int TransferItemTo(MyItemType type, int amount, AggregateInventoryInterface destination)
  328.     {
  329.         foreach (IMyTerminalBlock t in destination.containers)
  330.         {
  331.             for (int i = 0; i < t.InventoryCount; i++)
  332.             {
  333.  
  334.                 var inv = t.GetInventory(i);
  335.                 //log("sending " + amount + " of " + type.SubtypeId + " to " + t.DefinitionDisplayNameText);
  336.                 amount = TransferItemTo(type, amount, inv);
  337.                 if (amount <= 0) return amount;
  338.             }
  339.         }
  340.         return amount;
  341.     }
  342.     static string[] common_ammo_identifiers = new string[]
  343.             {
  344.                 "missile",
  345.                 "ammo",
  346.                 "magazine",
  347.                 "torpedo",
  348.                 "slug",
  349.                 "box"
  350.             };
  351.     static Dictionary<string, string> bulkreplace = new Dictionary<string, string>();
  352.     static void initbulk()
  353.     {
  354.         var r = bulkreplace;
  355.         if (r.Count != 0) return;
  356.         r["AngleGrinder"] = "Grinder";
  357.         r["CrateTomato"] = "Crate of Tomatoes";
  358.         r["HeavyArms"] = "Heavy Armaments";
  359.         r["GravityGenerator"] = "Gravity Comp.";
  360.         r["RadioCommunication"] = "Radio-comm Comp.";
  361.         r["Detector"] = "Detector Comp.";
  362.         r["LargeTube"] = "Large Steel Tube";
  363.         r["Construction"] = "Construction Comp.";
  364.     }
  365.     static public string prettyItemName(MyItemType item)
  366.     {
  367.         initbulk();
  368.         string name = item.SubtypeId.Replace("MyObjectBuilder_", "").Replace("_", " ");
  369.         var nfo = item.GetItemInfo();
  370.         foreach (KeyValuePair<string, string> kvp in bulkreplace)
  371.         {
  372.             if (name == kvp.Key)
  373.             {
  374.                 name = kvp.Value;
  375.                 break;
  376.             }
  377.             else if (name.StartsWith(kvp.Key))
  378.             {
  379.                 name = name.Replace(kvp.Key, kvp.Value);
  380.                 break;
  381.             }
  382.         }
  383.         if (nfo.IsAmmo)
  384.         {
  385.             var l = name.ToLower();
  386.             if (name.Length > 20) name = name.Replace("Magazine", "");
  387.             else
  388.             {
  389.  
  390.                 if (name.StartsWith("Missile"))
  391.                 {
  392.                     name = name.Substring("Missile".Length) + " Missile";
  393.                 }
  394.  
  395.                 if (l.IndexOf("magazine") == -1)// && l.IndexOf(' ') == -1)
  396.                 {
  397.  
  398.                 }
  399.             }
  400.             l = name.ToLower();
  401.             bool id = false;
  402.             foreach (var i in common_ammo_identifiers)
  403.             {
  404.                 if (l.IndexOf(i) != -1)
  405.                 {
  406.                     id = true;
  407.                     break;
  408.                 }
  409.             }
  410.             if (!id)
  411.             {
  412.                 name += "Ammo";
  413.             }
  414.         }
  415.         if (nfo.IsTool && name.Length > 5)
  416.         {
  417.  
  418.             string nsub = name.Substring(0, name.Length - 5);
  419.             if (name.EndsWith("1Item")) name = nsub;
  420.             else if (name.EndsWith("2Item")) name = nsub + " (Enhanced)";
  421.             else if (name.EndsWith("3Item")) name = nsub + " (Proficient)";
  422.             else if (name.EndsWith("4Item")) name = nsub + " (Elite)";
  423.         }
  424.         int capcount = 0;
  425.         foreach (char c in name) if (char.IsUpper(c)) capcount += 1;
  426.         if (capcount <= 1)
  427.         {
  428.             if (nfo.IsOre && name != "Stone") return name + " Ore";
  429.             if (nfo.IsIngot)
  430.             {
  431.                 if (name == "Stone") return "Gravel";
  432.                 return name + " Ingot";
  433.             }
  434.             //if (name == "Stone Ingot") name = "Gravel";
  435.         }
  436.         else
  437.         {
  438.             string rename = "";
  439.             // bool didLast = false;
  440.             for (int i = 0; i < name.Length; i++)
  441.             {
  442.                 if (i > 0 && i < name.Length - 1)
  443.                 {
  444.                     bool notlast = true;
  445.                     if (rename.Length > 0) notlast = rename[rename.Length - 1] != ' ';
  446.                     if (name[i - 1] != ' ' && name[i] != ' ' && name[i + 1] != ' ' && notlast)
  447.                     {
  448.                         bool prev = char.IsUpper(name[i - 1]);
  449.                         bool cur = char.IsUpper(name[i]);
  450.                         bool next = char.IsUpper(name[i + 1]);
  451.                         bool nextLetter = char.IsLetter(name[i + 1]);
  452.                         if ((cur && !next && nextLetter && name[i - 1] != '(' && name[i] != ' ') || (!prev && name[i - 1] != '(' && cur && name[i] != ' '))// && !prev)
  453.                         {
  454.                             rename += " ";
  455.                         }
  456.                         if (prev && !char.IsLetter(name[i]) && name[i] != ' ') rename += " ";
  457.                     }
  458.                 }
  459.                 rename += name[i]; ;
  460.             }
  461.             name = rename;
  462.         }
  463.         name = name.Replace(" Adv ", " Advanced ");
  464.         if (nfo.IsAmmo && name.Length > 4)
  465.         {
  466.             if (name.EndsWith("MCRN")) name = name.Substring(0, name.Length - 4) + "(MCRN)";
  467.             if (name.EndsWith("UNN")) name = name.Substring(0, name.Length - 3) + "(UNN)";
  468.         }
  469.  
  470.         return name;
  471.     }
  472.  
  473.     public string listInv(Func<MyItemType,bool> filter = null)
  474.     {
  475.         string r = "";
  476.  
  477.         int nlen = 0;
  478.         Dictionary<string, int> entries = new Dictionary<string, int>();
  479.         foreach (KeyValuePair<MyItemType, int> kvp in items)
  480.         {
  481.             if (filter != null) if (!filter(kvp.Key)) continue;
  482.             entries[prettyItemName(kvp.Key)] = kvp.Value;
  483.         }
  484.         foreach (KeyValuePair<string, int> kvp in entries)if (kvp.Key.Length > nlen) nlen = kvp.Key.Length;
  485.         foreach (KeyValuePair<string, int> kvp in entries)
  486.         {
  487.             string d = kvp.Key;
  488.             if (d.Length < nlen) d += new string('_', nlen - d.Length);
  489.             r += d + ": " + kvp.Value + "\n";
  490.         }
  491.         return r;
  492.     }
  493. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement