local S = logistica.TRANSLATOR local META_CURRENT_BUCKET_INDEX = "filcur" local INV_MAIN = "main" local INV_INPUT = "input" local buckets_to_names = nil local function get_all_buckets_to_names_list() if not buckets_to_names then buckets_to_names = logistica.table_to_list_indexed( logistica.reservoir_get_all_filled_buckets_to_names_map(), function (bucketName, liquidName) return { bucketName = bucketName, liquidName = liquidName } end ) end return buckets_to_names end -- Returns a a table of {bucketName = "bucket:name", liquidName = "Name of liquid"} function logistica.filler_get_current_selected_bucket(pos) local meta = minetest.get_meta(pos) local index = meta:get_int(META_CURRENT_BUCKET_INDEX) local allBuckets = get_all_buckets_to_names_list() local currBucket = allBuckets[index] if not currBucket then currBucket = allBuckets[0] or {} end return { bucketName = currBucket.bucketName or "", liquidName = currBucket.liquidName or "", } end function logistica.filler_change_selected_bucket(pos, change) local allBucketsToNames = get_all_buckets_to_names_list() local maxSize = #allBucketsToNames local meta = minetest.get_meta(pos) local index = meta:get_int(META_CURRENT_BUCKET_INDEX) index = index + change if index < 1 then index = maxSize elseif index > maxSize then index = 1 end meta:set_int(META_CURRENT_BUCKET_INDEX, index) -- set the main inventory's list local inv = meta:get_inventory() local mainList = {} if allBucketsToNames[index] then mainList[1] = ItemStack(allBucketsToNames[index].bucketName) end inv:set_list(INV_MAIN, mainList) logistica.update_cache_at_pos(pos, LOG_CACHE_SUPPLIER) -- notify we got new item (well probably) end -- return a table of {remaining = int, error = ""}, indicating how many items remain to be fulfilled, and an optional error msg if any function logistica.take_item_from_bucket_filler(pos, stackToTake, network, collectorFunc, isAutomatedRequest, dryRun, depth) if stackToTake:get_count() <= 0 then return { remaining = 0, error = S("Can't take a stack of size 0") } end if not network then return { remaining = stackToTake:get_count(), error = S("No network") } end -- filling happens from network reservoirs, so need a network if not depth then depth = 1 end local originalRequestedBuckets = stackToTake:get_count() local stackToTakeName = stackToTake:get_name() local liquidName = logistica.reservoir_get_liquid_name_for_filled_bucket(stackToTakeName) if not liquidName then return { remaining = stackToTake:get_count(), error = S("Unknown liquid: ")..liquidName } end local liquidInfo = logistica.get_liquid_info_in_network(pos, liquidName) local remainingRequest = math.min(liquidInfo.curr, originalRequestedBuckets) local unfillableBuckets = originalRequestedBuckets - remainingRequest local filledBuckets = logistica.reservoir_get_full_buckets_for_liquid(liquidName) if not filledBuckets[stackToTakeName] then return { remaining = stackToTake:get_count(), error = S("Unknown filled bucket requested: ")..stackToTakeName } end local filledBucketName = stackToTakeName local emptyBucketName = logistica.reservoir_get_empty_bucket_for_full_bucket(stackToTakeName) if not emptyBucketName then return { remaining = stackToTake:get_count(), error = S("Unknown full bucket: ")..stackToTakeName } end -- first try to get the empty bucket from our internal inventory local inv = minetest.get_meta(pos):get_inventory() local collectedInternal = remainingRequest local tookFromInternal = false while collectedInternal > 0 and not tookFromInternal do -- try to take max, then 1 less, etc, until we take it, or we hit 0 local needed = ItemStack(emptyBucketName); needed:set_count(collectedInternal) if inv:contains_item(INV_INPUT, needed) then tookFromInternal = true else collectedInternal = collectedInternal - 1 end end -- remaining decreased by how many we actually managed to take from internal inv remainingRequest = remainingRequest - collectedInternal -- then if necessary, try to take remaining empty buckets from network local collectedFromNetwork = 0 if remainingRequest > 0 then local collectEmpty = function(stackToInsert) collectedFromNetwork = stackToInsert:get_count() ; return 0 end local stackToTakeFromNetwork = ItemStack(emptyBucketName) ; stackToTakeFromNetwork:set_count(remainingRequest) logistica.take_stack_from_network(stackToTakeFromNetwork, network, collectEmpty, isAutomatedRequest, false, true, depth + 1) remainingRequest = remainingRequest - collectedFromNetwork end local numEmptyBucketsAvailable = collectedInternal + collectedFromNetwork local emptyBucketStack = ItemStack(emptyBucketName) for _ = 1, numEmptyBucketsAvailable, 1 do logistica.fill_bucket_from_network(network, emptyBucketStack, liquidName, dryRun) end local toGive = ItemStack(filledBucketName) ; toGive:set_count(numEmptyBucketsAvailable) local leftover = collectorFunc(toGive) if not dryRun then -- actually remove empty buckets from storages local numAccepted = numEmptyBucketsAvailable - leftover local actuallyTakeFromInternal = math.min(collectedInternal, numAccepted) if actuallyTakeFromInternal > 0 then local stackRemInternal = ItemStack(emptyBucketName) ; stackRemInternal:set_count(actuallyTakeFromInternal) inv:remove_item(INV_INPUT, stackRemInternal) end local actuallyTakeFromNetwork = math.min(collectedFromNetwork, numAccepted - actuallyTakeFromInternal) local stackToTakeFromNetwork = ItemStack(emptyBucketName) ; stackToTakeFromNetwork:set_count(actuallyTakeFromNetwork) logistica.take_stack_from_network(stackToTakeFromNetwork, network, function(_) return 0 end, isAutomatedRequest, false, false, depth + 1) end local error = nil if numEmptyBucketsAvailable < originalRequestedBuckets - unfillableBuckets then error = S("Not enough empty buckets available") elseif unfillableBuckets > 0 then error = S("Not enough liquid available in network") end return { remaining = unfillableBuckets + remainingRequest, error = error } end