mirror of
https://github.com/Kiritow/OpenComputerScripts.git
synced 2024-03-22 13:10:46 +08:00
Smart Storage v0.6
Now support robot crafting.
This commit is contained in:
parent
15ee96e87e
commit
4b684885d4
251
SmartStorage.lua
251
SmartStorage.lua
|
@ -9,7 +9,7 @@ local serialization=require('serialization')
|
||||||
|
|
||||||
require('libevent')
|
require('libevent')
|
||||||
|
|
||||||
local version_tag="Smart Storage v0.5.9"
|
local version_tag="Smart Storage v0.6.1-dbg"
|
||||||
|
|
||||||
print(version_tag)
|
print(version_tag)
|
||||||
print("Checking hardware...")
|
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.set(1,1,version_tag)
|
||||||
gpu.fill(1,2,w,1,'-')
|
gpu.fill(1,2,w,1,'-')
|
||||||
gpu.fill(1,h-2,w,1,'-')
|
gpu.fill(1,h-2,w,1,'-')
|
||||||
gpu.set(1,h-1,"<Refresh> <Reform> <Set Filter> <Clear Filter> <Read recipe>")
|
gpu.set(1,h-1,"<Refresh> <Reform> <Set Filter> <Clear Filter> <Read recipe> <Debug>")
|
||||||
|
|
||||||
local count_shown=0
|
local count_shown=0
|
||||||
for i=begin_at,#tb_display,1 do
|
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 ..") ")
|
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
|
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()
|
term.clear()
|
||||||
print("Smart Storage System Starting...")
|
print("Smart Storage System Starting...")
|
||||||
status("Scanning...")
|
status("Scanning...")
|
||||||
local craft_table={}
|
-- These variable should be local. Here is just for debug purpose.
|
||||||
local result=full_scan()
|
craft_table={}
|
||||||
local tb_display=GetDisplayTable(result)
|
result=full_scan()
|
||||||
local begin_at=1
|
tb_display=GetDisplayTable(result)
|
||||||
local item_filter=''
|
begin_at=1
|
||||||
|
item_filter=''
|
||||||
|
|
||||||
local need_refresh=true
|
local need_refresh=true
|
||||||
|
|
||||||
|
@ -329,7 +373,7 @@ while true do
|
||||||
from={},
|
from={},
|
||||||
to={}
|
to={}
|
||||||
}
|
}
|
||||||
|
|
||||||
local io_trans=component.proxy(io_trans_addr)
|
local io_trans=component.proxy(io_trans_addr)
|
||||||
local temp=io_trans.getStackInSlot(io_trans_buffer_side,14)
|
local temp=io_trans.getStackInSlot(io_trans_buffer_side,14)
|
||||||
if(temp==nil or temp.size==nil) then
|
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)
|
temp=io_trans.getStackInSlot(io_trans_buffer_side,from_slot)
|
||||||
if(temp~=nil or temp.size~=nil) then
|
if(temp~=nil or temp.size~=nil) then
|
||||||
newRecipe.from[idx]={
|
newRecipe.from[idx]={
|
||||||
id=getItemXID(temp.name,temp.label)
|
id=getItemXID(temp.name,temp.label),
|
||||||
size=temp.size
|
size=temp.size
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if(not craft_table[newRecipe.to.id]) then
|
if(not craft_table[newRecipe.to.id]) then
|
||||||
craft_table[newRecipe.to.id]={}
|
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("<Refresh> <Reform> <Set Filter> <Clear Filter> <Read recipe> <Debug>")) 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
|
end
|
||||||
table.insert(craft_table[newRecipe.to.id],{size=newRecipe.to.size,from=newRecipe.from})
|
|
||||||
status("New recipe added")
|
|
||||||
end
|
end
|
||||||
elseif(e.y>=3 and e.y<=h-3) then
|
elseif(e.y>=3 and e.y<=h-3) then
|
||||||
if(begin_at+e.y-3<=#tb_display) then
|
if(begin_at+e.y-3<=#tb_display) then
|
||||||
|
@ -370,46 +433,134 @@ while true do
|
||||||
status("Invalid input.")
|
status("Invalid input.")
|
||||||
else
|
else
|
||||||
status("Transfer begins.")
|
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
|
SystemGetItem(result,tb_display[begin_at+e.y-3],n)
|
||||||
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.
|
|
||||||
end
|
end
|
||||||
elseif(e.button==1) then -- Right click
|
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].total<this_amount) then
|
||||||
|
available=false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if(available) then
|
||||||
|
resolved_recipe_id=idx
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if(not resolved_recipe_id) then
|
||||||
|
status("Unable to craft. Not enough ingredients.")
|
||||||
|
else
|
||||||
|
status("[Checked] Following recipe " .. resolved_recipe_id)
|
||||||
|
local follow_recipe=this_recipe_list[resolved_recipe_id]
|
||||||
|
|
||||||
|
local target_slot={1,2,3,10,11,12,19,20,21}
|
||||||
|
local flag_done=true
|
||||||
|
|
||||||
|
local io_trans=component.proxy(io_trans_addr)
|
||||||
|
|
||||||
|
for idx,this_slot in pairs(follow_recipe.from) do
|
||||||
|
local ans=SystemGetItem(result,this_slot.id,this_slot.size)
|
||||||
|
if(ans~=this_slot.size) then
|
||||||
|
flag_done=false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if(not flag_done) then
|
||||||
|
status("Unable to craft. Failed to fetch enough item.")
|
||||||
|
else
|
||||||
|
status("[Working] Clearing buffer chest...")
|
||||||
|
while io_trans.transferItem(io_trans_buffer_side,io_trans_output_side)>0 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
|
end
|
||||||
end
|
end
|
||||||
|
|
76
SmartStorageRobot.lua
Normal file
76
SmartStorageRobot.lua
Normal file
|
@ -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)
|
Loading…
Reference in New Issue
Block a user