diff --git a/SmartStorage.lua b/SmartStorage.lua index 67fde62..cb84f3a 100644 --- a/SmartStorage.lua +++ b/SmartStorage.lua @@ -9,7 +9,7 @@ local serialization=require('serialization') require('libevent') -local version_tag="Smart Storage v0.5.9" +local version_tag="Smart Storage v0.6.1-dbg" print(version_tag) print("Checking hardware...") @@ -181,7 +181,7 @@ local function display(tb_data,tb_display,tb_craft,begin_at,filter) gpu.set(1,1,version_tag) gpu.fill(1,2,w,1,'-') gpu.fill(1,h-2,w,1,'-') - gpu.set(1,h-1," ") + gpu.set(1,h-1," ") local count_shown=0 for i=begin_at,#tb_display,1 do @@ -214,14 +214,58 @@ local function display(tb_data,tb_display,tb_craft,begin_at,filter) gpu.set(4,h-2," Space used: " .. math.floor(tb_data.slot_used/tb_data.slot_total*1000)/10 .. "% (" .. tb_data.slot_used .. "/" .. tb_data.slot_total ..") ") end +local function SystemGetItem(tb_data,request_key,request_amount) + local fetched=0 + local this_table=tb_data[request_key] + for idx,this_info in ipairs(this_table.position) do + local this_trans=component.proxy(this_info.addr) + local need=0 + if(this_info.size>request_amount-fetched) then + need=request_amount-fetched + else + need=this_info.size + end + local done=this_trans.transferItem(this_info.side,sides.down,need,this_info.slot) + fetched=fetched+done + this_info.size=this_info.size-done + this_table.total=this_table.total-done + if(fetched>=request_amount) then break end + status("[Working] " .. fetched .. " of " .. request_amount .. " items transferred.") + end + + -- Update storage info + local idx=1 + while(idx<=#this_table.position) do + if(this_table.position[idx].size<=0) then + table.remove(this_table.position,idx) + result.slot_used=result.slot_used-1 + else + idx=idx+1 + end + end + if(this_table.total<1) then + result[tb_display[begin_at+e.y-3]]=nil -- Remove this type + table.remove(tb_display,begin_at+e.y-3) + + if(begin_at>1) then + begin_at=begin_at-1 + end + end + + status("[Done] " .. fetched .. " of " .. request_amount .. " items transferred") -- Sometimes (ex: output box is full) not all items can be transferred. + + return fetched +end + term.clear() print("Smart Storage System Starting...") status("Scanning...") -local craft_table={} -local result=full_scan() -local tb_display=GetDisplayTable(result) -local begin_at=1 -local item_filter='' +-- These variable should be local. Here is just for debug purpose. +craft_table={} +result=full_scan() +tb_display=GetDisplayTable(result) +begin_at=1 +item_filter='' local need_refresh=true @@ -329,7 +373,7 @@ while true do from={}, to={} } - + local io_trans=component.proxy(io_trans_addr) local temp=io_trans.getStackInSlot(io_trans_buffer_side,14) if(temp==nil or temp.size==nil) then @@ -343,18 +387,37 @@ while true do temp=io_trans.getStackInSlot(io_trans_buffer_side,from_slot) if(temp~=nil or temp.size~=nil) then newRecipe.from[idx]={ - id=getItemXID(temp.name,temp.label) + id=getItemXID(temp.name,temp.label), size=temp.size } end end - end - if(not craft_table[newRecipe.to.id]) then - craft_table[newRecipe.to.id]={} + if(not craft_table[newRecipe.to.id]) then + craft_table[newRecipe.to.id]={} + end + table.insert(craft_table[newRecipe.to.id],{size=newRecipe.to.size,from=newRecipe.from}) + status("New recipe added") + + need_refresh=true + end + elseif(e.x<=string.len(" ")) then + term.setCursor(1,h-1) + term.clearLine() + io.write("Lua: ") + local str=io.read() + if(str) then + local f,err=load(str,"UserChunk","t",_ENV) + if(f==nil) then + status("Invalid Debug: " .. err) + else + local ok,err=pcall(f) + if(not ok) then + status("Debug Failed: " .. err) + end + end + need_refresh=true end - table.insert(craft_table[newRecipe.to.id],{size=newRecipe.to.size,from=newRecipe.from}) - status("New recipe added") end elseif(e.y>=3 and e.y<=h-3) then if(begin_at+e.y-3<=#tb_display) then @@ -370,46 +433,134 @@ while true do status("Invalid input.") else status("Transfer begins.") - local fetched=0 - for idx,this_info in ipairs(this_table.position) do - local this_trans=component.proxy(this_info.addr) - local need=0 - if(this_info.size>n-fetched) then - need=n-fetched - else - need=this_info.size - end - local done=this_trans.transferItem(this_info.side,sides.down,need,this_info.slot) - fetched=fetched+done - this_info.size=this_info.size-done - this_table.total=this_table.total-done - if(fetched>=n) then break end - status("[Working] " .. fetched .. " of " .. n .. " items transferred.") - end - -- Update storage info - local idx=1 - while(idx<=#this_table.position) do - if(this_table.position[idx].size<=0) then - table.remove(this_table.position,idx) - result.slot_used=result.slot_used-1 - else - idx=idx+1 - end - end - if(this_table.total<1) then - result[tb_display[begin_at+e.y-3]]=nil -- Remove this type - table.remove(tb_display,begin_at+e.y-3) - - if(begin_at>1) then - begin_at=begin_at-1 - end - end - - status("[Done] " .. fetched .. " of " .. n .. " items transferred") -- Sometimes (ex: output box is full) not all items can be transferred. + SystemGetItem(result,tb_display[begin_at+e.y-3],n) end elseif(e.button==1) then -- Right click + if(craft_table[tb_display[begin_at+e.y-3]]==nil) then + status("This item can't be crafted.") + else + need_refresh=true + local this_table=result[tb_display[begin_at+e.y-3]] + local this_recipe_list=craft_table[tb_display[begin_at+e.y-3]] + local resolved_recipe_id=nil + status("Calculating crafting need...") + for idx,this_recipe in ipairs(this_recipe_list) do + status("[Working] Checking recipe " .. idx .. "...") + local temp_sum={} + for idx,this_from in pairs(this_recipe.from) do + if(not temp_sum[this_from.id]) then + temp_sum[this_from.id]=0 + end + temp_sum[this_from.id]=temp_sum[this_from.id]+this_from.size + end + local available=true + for this_id,this_amount in pairs(temp_sum) do + status("[Checking] ID=" .. this_id) + if(result[this_id].total0 do end + status("[Working] Moving resource to buffer chest...") + for i=1,9,1 do + if(follow_recipe.from[i]) then + status("[Working] Gathering item for slot " .. i .. "...") + local which_slot=0 + while which_slot<1 do + for j=1,io_trans.getInventorySize(io_trans_output_side),1 do + local this_info=io_trans.getStackInSlot(io_trans_output_side,j) + if(this_info~=nil and this_info.size~=nil and + (getItemXID(this_info.name,this_info.label)==follow_recipe.from[i].id) and + (this_info.size>=follow_recipe.from[i].size) + ) then + which_slot=j + break + end + end + + status("[Working] Waiting item for slot " .. i .. "...") + end + io_trans.transferItem(io_trans_output_side,io_trans_buffer_side,follow_recipe.from[i].size,which_slot,target_slot[i]) + end + end + + status("[Pending] Waiting for robot response...") + modem.send(robotAddr,1000,"do_craft") + local robot_ok=true + while true do + local e=WaitEvent(5,"modem_message") + if(e==nil) then + status("Unable to craft. Robot no response.") + robot_ok=false + break + elseif(e.event=="modem_message" and e.port==1001 and e.data[1]=="craft_started") then + break + end + end + + if(robot_ok) then + status("[Pending] Robot is crafting... (Ctrl+C to stop)") + local craft_done=false + local craft_ok=false + while true do + local e=WaitMultipleEvent("modem_message","interrupted") + if(e.event=="interrupted") then + status("Craft process is cancelled by user.") + break + elseif(e.event=="modem_message" and e.port==1001 and e.data[1]=="craft_done") then + status("[Working] Robot crafting finished.") + craft_ok=e.data[2] + + craft_done=true + break + end + end + + if(craft_done) then + status("[Working] Moving items to output chest...") + while io_trans.transferItem(io_trans_buffer_side,io_trans_output_side)>0 do end + if(craft_ok) then + status("[Done] Item crafted successfully.") + else + status("[Done] Item failed to craft.") + end + end + end + end + end + end end end end diff --git a/SmartStorageRobot.lua b/SmartStorageRobot.lua new file mode 100644 index 0000000..0377a29 --- /dev/null +++ b/SmartStorageRobot.lua @@ -0,0 +1,76 @@ +-- Smart Storage Robot +-- Author: Kiritow + +local component=require('component') +local sides=require('sides') +local serialization=require('serialization') +local robot=require('robot') + +require('libevent') + +local version_tag="Smart Storage Robot v0.1" + +print(version_tag) +print("Checking hardware...") +local modem=component.modem +local crafting=component.crafting +local controller=component.inventory_controller +if(not modem or not crafting or not controller or robot.inventorySize()<16) then + print("This program requires Modem, Crafting upgrade, Inventory Controller upgrade and at least a 16-slot inventory to run.") + return +end +print("Reading config...") + +print("Waiting for Smart Storage System... (Ctrl+C to stop)") +local sysAddr='' +modem.open(1000) +while true do + local e=WaitMultipleEvent("modem_message","interrupted") + if(e.event=="interrupted") then + print("Cancelled by user.") + modem.close(1000) + return + elseif(e.event=="modem_message" and e.port==1000 and e.data[1]=="find_crafting_robot") then + print("System request received.") + sysAddr=e.senderAddress + modem.send(sysAddr,1001,"crafting_robot_response") + print("Response sent.") + break + end +end +print("Smart Storage System set to " .. sysAddr) +while true do + print("Waiting for requests... (Ctrl+C to stop)") + local e=WaitMultipleEvent("modem_message","interrupted") + if(e.event=="interrupted") then + print("Receive stop signal") + break + elseif(e.event=="modem_message" and e.port==1000) then + if(e.data[1]=="do_craft") then + print("[Pending] Sending response...") + modem.send(sysAddr,1001,"craft_started") + print("[Working] Start craft task...") + local from_slot={1,2,3,10,11,12,19,20,21} + local to_slot={1,2,3,5,6,7,9,10,11} + print("[Working] Moving resource...") + for i=1,9,1 do + robot.select(to_slot[i]) + controller.suckFromSlot(sides.front,from_slot[i]) + end + print("[Working] Crafting...") + robot.select(4) + local result=crafting.craft() + print("[Working] Craft result: ",result) + print("[Working] Cleaning inventory...") + for i=1,16,1 do + robot.select(i) + robot.drop() + end + modem.send(sysAddr,1001,"craft_done",result) + print("[Done] Task craft finished.") + end + end +end + +print("Closing ports...") +modem.close(1000) \ No newline at end of file