cc-tweaked / CC-Tweaked

Just another ComputerCraft fork
https://tweaked.cc
942 stars 211 forks source link

Clone and simulate moving items and fluids to a peripheral #1839

Open Burkino opened 6 months ago

Burkino commented 6 months ago

Currently there is no good way of moving a set of items to a peripheral while being confident all items will be moved. For this I would need a way to test what will happen before doing it for real. This is especially necessary for when you can't take items and fluids back out of input slots. I believe the easiest way for the user would be to have a peripheral.virtual(name) function that clones the peripheral (including its inventory and tanks), then have some way of pushing fake items and fluids into it.

local TARGET = "minecraft:chest_0"

local fake = peripheral.virtual(TARGET)

--- @class Input
--- @field name string
--- @field amount number
--- @field type "item"|"fluid"

local to_test = { --- @type table<Input>
  {name="minecraft:cobblestone", amount=32, type="item"},
  {name="minecraft:water", amount=1000, type="fluid"}
}

--- @param inputs table<Input>
--- @return boolean
local function test(inputs)
  for _,v in pairs(inputs) do
    if v.type == "item" then
      local moved = fake.simulate_push_items(v)
      if moved ~= v.amount then
        return false
      end
    elseif v.type == "fluid" then
      local moved = fake.simulate_push_fluids(v)
      if moved ~= v.amount then
        return false
      end
    end
  end

  return true
end

if test(to_test) then
  -- Move items and fluids for real
else
  print("You can't move fluids into a chest")
end
Wojbie commented 6 months ago

Could you expand on in which situations you could be not 100% sure it will be moved or not? If you know exactly what state target and source inventories/tanks are you should be able to predict if that move call will succeed fully, partially or not at all.

Lupus590 commented 6 months ago

How does this virtual peripheral know how the real one would behave to thus simulate that behaviour? I think that a better way would be to calculate the free space remaining in the real peripheral before the push/pull.

Or maybe, if this is possible on the Java side, the push/pull methods should have a flag to abort the transfer of fluids/items if the transfer would be partially complete.

Wojbie commented 6 months ago

Or maybe, if this is possible on the Java side, the push/pull methods should have a flag to abort the transfer of fluids/items if the transfer would be partially complete.

Or argument to indicate minimal amount to transfer to counterpoint with limit argument.

Burkino commented 6 months ago

Could you expand on in which situations you could be not 100% sure it will be moved or not? If you know exactly what state target and source inventories/tanks are you should be able to predict if that move call will succeed fully, partially or not at all.

This is mostly for use in GregTech machines. There are dozens of machines with different amounts of input slots so it would be a huge pain to say what the input slots are. You would have to consider partially full slots and items rolling over to the next slot. Being able to simulate what would happen would greatly simplify the problem. It's not entirely impossible, but it's a lot of extra work that would undoubtedly have some issue.

Or argument to indicate minimal amount to transfer to counterpoint with limit argument.

This wouldn't be a great solution, if you need to move 5 types of items and the 3rd one fails, you would need to backtrack, take the first 2 out, then try another machine.

Lupus590 commented 6 months ago

Why not just take the free space in the slot and use that as the limit for the transfer?

fatboychummy commented 6 months ago

Do gregtech machines not show up as different peripheral types to CC? It makes no sense to me that you're trying to essentially brute-force find what machine a recipe should be for (at least, from the little explanation you've given, this is what it sounds like you're trying to do). You know the recipe, you know the machine, only push the recipe ingredients to the right machine?

This is how systems like AE2's ME does it, you cannot just push a recipe to any machine without care, you must designate a machine for every recipe.

Burkino commented 6 months ago

Do gregtech machines not show up as different peripheral types to CC? It makes no sense to me that you're trying to essentially brute-force find what machine a recipe should be for (at least, from the little explanation you've given, this is what it sounds like you're trying to do). You know the recipe, you know the machine, only push the recipe ingredients to the right machine?

This is how systems like AE2's ME does it, you cannot just push a recipe to any machine without care, you must designate a machine for every recipe.

I have already encoded recipes and the type of machine it uses, I just need some way of checking that all the ingredients for the recipe will be pushed into the machine.

Wojbie commented 6 months ago

So can't you look in machine input and detect if they will fit or not? I am sorry if we seem repetitive but solution just seem to be to look at machine inputs state and calculate if they will fit, and i wonder if there is something about gregtech that stops you from doing that?

Burkino commented 6 months ago

So can't you look in machine input and detect if they will fit or not? I am sorry if we seem repetitive but solution just seem to be to look at machine inputs state and calculate if they will fit, and i wonder if there is something about gregtech that stops you from doing that?

Like I said, I could probably do that, but just being able to simulate what would happen would greatly simplify the problem