Welcome to Keen Software House Forums! Log in or Sign up to interact with the KSH community.
  1. You are currently browsing our forum as a guest. Create your own forum account to access all forum functionality.

IMyInventory.GetItems() Returning MyInventoryItem instead of IMyInventoryItem

Discussion in 'Programming (In-game)' started by Java_SE_Binary, Mar 1, 2019.

Thread Status:
This last post in this thread was made more than 31 days old.
  1. Java_SE_Binary Trainee Engineer

    Messages:
    1
    I've got a few sections of code in a couple automatic drill miners, all of the code was written by a user called Pennywise, that use the GetItems method to perform different tasks. One section I've managed to convert over to the new MyInventoryItem way, but the second section, specifically where the Content method is called. According to the compilation log, the Content method is non-existent for the type MyInventoryItem, and I cannot cast an IMyInventoryItem to a MyInventoryItem.

    Is there some sort of work-around that has already been implemented that I don't know about?

    I don't have too much experience with Space Engineers coding, but I am attempting to fix this up.
     
  2. mojomann71 Senior Engineer

    Messages:
    2,005
    Maybe give the original author a day or so to fix their script? :)
     
  3. Adraesh Trainee Engineer

    Messages:
    3
    Hello!

    I have the exact same issue, GetItems returns an MyIventoryItem and therefore does not have any Content method. I just want to get the Name and the Amount of each items.

    Thank you in advance.

    EDIT: The ToString() method returns everything, so probably have to parse it? Is this the right way?
     
    Last edited: Mar 1, 2019
  4. Pembroke Trainee Engineer

    Messages:
    7
    Noticed the same. The IMyInventory.GetItems() interface has changed. It looks like GetItems() now expects to get a list as an argument it then, presumably, fills. That's ok, I can use an explicit list and use that to access the items. However, the second change is more problematic. GetItems() gives you MyInventoryItem objects instead of IMyInventoryItem objects. Is this a mistake or deliberate? Because that breaks stuff. The two classes have different methods.

    Are we supposed to use MyInventoryItems now instead of IMyInventoryItems? Or is it a mistake in their definitions and it really ought to give you IMyInventoryItems, instead?

    I'd very much like to know. Wouldn't want to change everything just to have to change them all back after the next bug fix...
     
  5. 2nd Engr. 3Dog Trainee Engineer

    Messages:
    16
  6. Old Garyman Trainee Engineer

    Messages:
    10

    Hi Adraesh,
    use .Type instead of .Content
     
  7. Pie Apprentice Engineer

    Messages:
    116
    IMyInventoryItem had a GetDefinitionId method. MyInventoryItem does not. I was relying on this to identify in-game items. Anyone know of an equivalent (ideally) or similar way of getting a unique string for an item?

    I used to just use GetItems on an inventory to get a list of IMyInventoryItem then use item.GetDefinitionId.ToString to identify it.

    EDIT - By Unique - I don't mean that particular item in that container - just "MyObjectBuilder_PhysicalGunObject/AngleGrinderItem" is always a basic grinder.
     
    Last edited: Mar 3, 2019
  8. Malware Master Engineer

    Messages:
    9,861
    It is very much deliberate, and the breaking was deliberate, because the old system was horrible, lead people to writing bad code that performs badly and allocates a lot of memory. This is just something we have to live with, and adapt our code to fit. It will not be changed back.
    --- Automerge ---
    The MyItemType, which you can get via a MyInventoryItem.Type property, is implicitly convertible directly to a MyDefinitionId.

    Code:
    MyInventoryItem item = // get item;
    MyDefinitionId id = item.Type;
    
     
    • Informative Informative x 1
  9. 2nd Engr. 3Dog Trainee Engineer

    Messages:
    16
    This is how I changed my code to resolve this:

    Old code: if (blockItems.Content.SubtypeId.ToString() == "Iron") { FeAmount += (int)blockItems.Amount; }
    New code: if (blockItems.Type.ToString().EndsWith("Iron")) { FeAmount += (int)blockItems.Amount; }

    @Malware should I be using the MyDefinitionId instead? I'm certain there is a better way to do this, but I'm new to the namespace and trying to struggle through it.
     
  10. Sinus32 Trainee Engineer

    Messages:
    22
    The solution is much simpler:
    if (blockItems.Type.SubtypeId == "Iron") { FeAmount += blockItems.Amount; }

    Just use Visual Studio and check what is now available.
    BTW: It's better to use MyFixedPoint instead of int.
     
    • Like Like x 1
  11. Pie Apprentice Engineer

    Messages:
    116
    --- Automerge ---
    Thanks - worked a charm. I notice GetItems changed as well and you now have to give it a list to put the items in to. It seems to add to that list rather than return a new one so I need to clear it every time. I can see ways of avoiding loads of List.Clear however I guess it was happening under the covers in the old system anyway so shouldn't impact existing script tooooooo much.... :)
     
  12. 2nd Engr. 3Dog Trainee Engineer

    Messages:
    16
    Thanks for the feedback @Sinus32

    I'd really like to convert to using MyfixedPoint. As I reference I found this link https://github.com/KeenSoftwareHous.../Sources/VRage.Library/Memory/MyFixedPoint.cs

    That led me to VRage.MyFixedPoint FeAmount = 0; // There's more on this line, but for brevity

    If there is another reference I should use, or a better way to do this let me know?

    I do appreciate the direction and feedback.
     
    Last edited: Mar 3, 2019
  13. Malware Master Engineer

    Messages:
    9,861
    @2nd Engr. 3Dog Sinus32 is right. For that particular use, their suggestion is far superior.

    That github is completely and utterly outdated. It was abandoned long ago.
     
  14. Pembroke Trainee Engineer

    Messages:
    7
    Right, MyInventoryItem it is, then. Thank you!
    A question, though, what's the best way to distinguish between ores and ingots when using MyInventoryItems? Before I relied on checking whether the IMyInventory.Content description had "_Ore" in the string.
     
  15. Sinus32 Trainee Engineer

    Messages:
    22
    Just check
    if (item.Type.TypeId == "MyObjectBuilder_Ore")
     
  16. 2nd Engr. 3Dog Trainee Engineer

    Messages:
    16
    It's fine. I figured it out eventually. It would be really cool if we had known good code samples to help us learn the right way rather than just whatever works.
     
  17. Malware Master Engineer

    Messages:
    9,861
    Normally I'd agree, but... we're lucky we even have a programmable block at this point, let alone updated code ;)
     
  18. 2nd Engr. 3Dog Trainee Engineer

    Messages:
    16
    Touché
     
  19. ASmilingNinja Trainee Engineer

    Messages:
    4
    This seems to have been intentional. You can now get the item name with MyInventoryItem.Type. This will then work with .ToString() and I then used .Split('/')[1] to get just the name of inventory item. To get the amount of that item you simply use MyInventoryItem.Amount.
     
  20. Old Garyman Trainee Engineer

    Messages:
    10
    There are two getters for .Type:
    MyInventoryItem.Type.TypeId
    and
    MyInventoryItem.Type.SubtypeId

    No need to cast or split something they are allready strings.
     
    • Agree Agree x 1
    • Informative Informative x 1
  21. Graboid Trainee Engineer

    Messages:
    2
    Hi.If someone understand,please help.What should be changed in this function to work:
    public int AddAmount(int Recult, string NamesRuda)
    {
    for (int i = 0; i < cargoList.Count; i++)
    {
    IMyTerminalBlock block = cargoList as IMyTerminalBlock;
    var items = block.GetInventory().GetItems();
    for (int j = 0; j < items.Count; j++)
    {
    IMyInventoryItem item = items[j] as IMyInventoryItem;
    if (item.Content.SubtypeId.ToString() == NamesRuda)
    Recult += (int)items[j].Amount;
    }
    }
    return Recult;
    }
     
  22. Old Garyman Trainee Engineer

    Messages:
    10
    First read this from Sinus32: https://forum.keenswh.com/threads/i...st-1287104570"]IMyInventory GetItems working?

    Check this:
    public int AddAmount(int Recult, string NamesRuda)
    {
    for (int i = 0; i < cargoList.Count; i++)
    {
    IMyTerminalBlock block = cargoList as IMyTerminalBlock;

    var items = new List<MyInventoryItem>(); //You see: MyInventoryItem not IMyInventoryItem
    block.GetInventory(0).GetItems(items, null);

    for (int j = 0; j < items.Count; j++)
    {
    var item = items[j];
    if (item.Type.SubtypeId == NamesRuda) // .Type not .Content .ToString not needed
    Recult += (int)items[j].Amount;
    }
    }
    return Recult;
    }


    I didn't test it.
     
    Last edited: Mar 6, 2019
  23. Graboid Trainee Engineer

    Messages:
    2
    Thanks.I read this.And my code(new)is almost the same as You wrote.But Amount is not clear believes.So the problem remained.
     
  24. Old Garyman Trainee Engineer

    Messages:
    10
    What does the compiler says.

    Maybe use VRage.MyFixedPoint instead int.
    VRage.MyFixedPoint is a Fixed point number with 6 decimal places.
     
    Last edited: Mar 6, 2019
  25. 2nd Engr. 3Dog Trainee Engineer

    Messages:
    16
    I am doing nearly the same function, but I avoid using counters like "i" and int wherever possible:

    Here are some caveats:
    I only have one container in "DockingCargo" so I do not iterate through the list (note ToContainer = ToContainers[0] )



    Code:
    		private void TransferCargo()
    		{
    			List<IMyCargoContainer> FromContainers = new List<IMyCargoContainer>();
    			List<IMyCargoContainer> ToContainers = new List<IMyCargoContainer>();
    			IMyCargoContainer ToContainer;
    			GridTerminalSystem.GetBlocksOfType<IMyCargoContainer>(ToContainers, block => block.CustomName.EndsWith("[DockingCargo]"));
    			ToContainer = ToContainers[0];
    			IMyInventory invReceiver = ToContainer.GetInventory(0);
    
    			GridTerminalSystem.GetBlocksOfType<IMyCargoContainer>(FromContainers, block => block.CustomName.EndsWith("[am5]"));
    			Echo("Starting Cargo Transfer");
    			foreach (IMyCargoContainer am5Container in FromContainers)
    			{
    				IMyInventory invSender = am5Container.GetInventory(0);
    				if (invSender.CanTransferItemTo(invReceiver, null))
    				{
    					invSender.TransferItemTo(invReceiver, 0, null, true, null); //(receiverContainer, SourceItemIndex, DestItemIndex, StackIfPossible, Amount)
    				}
    				
    			}
    }
    
     
  26. Malware Master Engineer

    Messages:
    9,861
    It is really disappointing to me that he didn't ditch the MyFixedPoint nonsense.
     
  27. Old Garyman Trainee Engineer

    Messages:
    10
    What's your problem?
    And what do you mean with the MyFixedPoint nonsense?
    Please express yourself better.

    Thanks
     
    Last edited: Mar 7, 2019
  28. Malware Master Engineer

    Messages:
    9,861
    MyFixedPoint is an overcomplicated solution that isn't required and just makes it harder for beginners to use the system. Inflex (the author of the new system) already knows my view on this very well :) It's disappointing to me that he didn't replace that when he remade the new API.
     
    • Agree Agree x 1
  29. Old Garyman Trainee Engineer

    Messages:
    10
    Okay, thanks for your explanation.
    Yes, I don't understand the meaning of MyFixedPoint either. But at the moment we seem to have to live with it.

    ;)
     
  30. Malware Master Engineer

    Messages:
    9,861
    The meaning is, theoretically, to reduce decimal point inaccuracy problems. However, it's my opinion that it doesn't really do that job very well, and that it really isn't needed. I maintain that we don't need that level of accuracy. Conclusion being, it's extra complexity for little gain.
     
Thread Status:
This last post in this thread was made more than 31 days old.