38 Commits

Author SHA1 Message Date
kepler155c
d4cf76b8e8 cleanup 2018-01-06 22:31:54 -05:00
kepler155c
44932ac515 peripheral overhaul + 1.7 fixes 2018-01-06 22:26:21 -05:00
kepler155c
f2b9efc80f peripheral overhaul 2018-01-06 06:08:39 -05:00
kepler155c
c48243eae5 item db naming fix for items with diff names-nbt combinations 2018-01-04 03:33:09 -05:00
kepler155c
45bbc72fc3 autocrafting improvements 2018-01-03 02:41:56 -05:00
kepler155c
aa50b55ab1 storage manager improvements 2017-12-27 23:56:14 -05:00
kepler155c
85c5f542a8 Autocrafting improvements 2017-12-23 01:48:36 -05:00
kepler155c
863b7ff600 Autocrafting improvements 2017-12-16 00:09:28 -05:00
kepler155c
0ce537d4ce autocrafting improvements 2017-12-13 01:38:59 -05:00
kepler155c
73dc16703a crafting improvements 2017-12-11 11:30:56 -05:00
kepler155c
f6fb6a4433 api cleanup 2017-11-15 00:09:29 -05:00
kepler155c
2526308eb6 turtle api 2017-10-31 02:01:14 -04:00
kepler155c
d97a9d7468 refactor + cleanup 2017-10-27 20:25:16 -04:00
kepler155c
9939c75fc3 proxy apis over wireless 2017-10-24 23:01:59 -04:00
kepler155c
77107e1d57 refactor builder 2017-10-23 21:36:47 -04:00
kepler155c
a2f452dc90 builder starting point 2017-10-22 19:11:06 -04:00
kepler155c
e0cac06c2a builder starting point 2017-10-22 01:29:42 -04:00
kepler155c
5e80591160 input redo 2017-10-20 13:56:35 -04:00
kepler155c
c057f98830 fix Script bug + crafter 2017-10-20 04:23:54 -04:00
kepler155c
11a005969c crafter 2017-10-19 03:23:05 -04:00
kepler155c
6a1f72f957 crafter 2017-10-19 02:57:17 -04:00
kepler155c
3622518b20 crafter 2017-10-18 19:54:28 -04:00
kepler155c
1eb47cf3c8 crafter 2017-10-17 22:51:13 -04:00
kepler155c
7892c0dbb7 crafter 2017-10-17 22:30:50 -04:00
kepler155c
fe79e582cd crafter 2017-10-17 12:53:55 -04:00
kepler155c
a5c7fde530 crafter 2017-10-16 16:55:37 -04:00
kepler155c
c04ec356e5 redo input translation -round 2 2017-10-16 00:04:16 -04:00
kepler155c
194e6f0a91 redo input translation + shift-paste 2017-10-15 19:55:43 -04:00
kepler155c
d0c8d2dc4f better detection for adapters 2017-10-15 02:35:40 -04:00
kepler155c
728cda2215 non-global clipboard 2017-10-14 13:40:16 -04:00
kepler155c
1f31f7ef40 non-global clipboard, ad hoc crafting 2017-10-14 03:39:47 -04:00
kepler155c
3734afed92 compatibility improvements 2017-10-12 17:56:14 -04:00
kepler155c
5232b5a115 wrong box 2017-10-11 16:27:51 -04:00
kepler155c
f5dede540e cleanup 2017-10-11 15:07:32 -04:00
kepler155c
980c635037 simplify ui 2017-10-11 11:36:56 -04:00
kepler155c
ed2d6eeef1 lint 2017-10-08 17:45:37 -04:00
kepler155c
bba7841c43 UI improvements 2017-10-07 23:02:38 -04:00
kepler155c
8ef97df223 inactive elements 2017-10-07 00:28:18 -04:00
62 changed files with 8330 additions and 5317 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/etc/fstab
/etc/recipes2.db

View File

@@ -6,42 +6,10 @@ local JSON = require('json')
-- see https://github.com/Khroki/MCEdit-Unified/blob/master/pymclevel/minecraft.yaml
-- see https://github.com/Khroki/MCEdit-Unified/blob/master/Items/minecraft/blocks.json
--[[-- nameDB --]]--
local nameDB = TableDB({
fileName = 'blocknames.db'
})
function nameDB:load(dir, blockDB)
self.fileName = fs.combine(dir, self.fileName)
if fs.exists(self.fileName) then
TableDB.load(self)
end
self.blockDB = blockDB
end
function nameDB:getName(id, dmg)
return self:lookupName(id, dmg) or id .. ':' .. dmg
end
function nameDB:lookupName(id, dmg)
-- is it in the name db ?
local name = self:get({ id, dmg })
if name then
return name
end
-- is it in the block db ?
for _,v in pairs(self.blockDB.data) do
if v.strId == id and v.dmg == dmg then
return v.name
end
end
end
--[[-- blockDB --]]--
local blockDB = TableDB()
function blockDB:load()
local blocks = JSON.decodeFromFile('usr/etc/blocks.json')
if not blocks then
@@ -64,7 +32,7 @@ function blockDB:lookup(id, dmg)
if not id then
return
end
return self.data[id .. ':' .. dmg]
end
@@ -85,19 +53,6 @@ end
local placementDB = TableDB()
function placementDB:load(sbDB, btDB)
for k,blockType in pairs(sbDB.data) do
local bt = btDB.data[blockType]
if not bt then
error('missing block type: ' .. blockType)
end
local id, dmg = string.match(k, '(%d+):*(%d+)')
self:addSubsForBlockType(tonumber(id), tonumber(dmg), bt)
end
end
function placementDB:load2(sbDB, btDB)
for k,v in pairs(sbDB.data) do
if v.place then
local bt = btDB.data[v.place]
@@ -113,7 +68,6 @@ function placementDB:load2(sbDB, btDB)
self:addSubsForBlockType(155, 2, btDB.data['quartz-pillar'])
end
function placementDB:addSubsForBlockType(id, dmg, bt)
for _,sub in pairs(bt) do
local odmg = sub.odmg
@@ -136,12 +90,12 @@ function placementDB:addSubsForBlockType(id, dmg, bt)
sub.extra)
end
end
function placementDB:add(id, dmg, sid, sdmg, direction, extra)
if direction and #direction == 0 then
direction = nil
end
local entry = {
oid = id, -- numeric ID
odmg = dmg, -- dmg with placement info
@@ -176,9 +130,8 @@ function blockTypeDB:addTemp(blockType, subs)
end
self.dirty = true
end
function blockTypeDB:load()
blockTypeDB:addTemp('stairs', {
{ 0, nil, 0, 'east-up' },
{ 1, nil, 0, 'west-up' },
@@ -564,20 +517,17 @@ end
local Blocks = class()
function Blocks:init(args)
Util.merge(self, args)
self.blockDB = blockDB
self.nameDB = nameDB
blockDB:load()
blockTypeDB:load()
nameDB:load(self.dir, blockDB)
placementDB:load2(blockDB, blockTypeDB)
placementDB:load(blockDB, blockTypeDB)
end
-- for an ID / dmg (with placement info) - return the correct block (without the placment info embedded in the dmg)
-- for an ID / dmg (with placement info)
-- return the correct block (without the placment info embedded in the dmg)
function Blocks:getPlaceableBlock(id, dmg)
local p = placementDB:get({id, dmg})
if p then
return Util.shallowCopy(p)

101
apis/builder/builder.lua Normal file
View File

@@ -0,0 +1,101 @@
local Blocks = require('builder.blocks')
local class = require('class')
local Message = require('message')
local Util = require('util')
local device = _G.device
local fs = _G.fs
local turtle = _G.turtle
local Builder = class()
Util.merge(Builder, {
isCommandComputer = not turtle,
loc = { },
index = 1,
mode = 'build',
})
local BUILDER_DIR = 'usr/builder'
local blockInfo = Blocks()
function Builder:getBlockCounts()
local blocks = { }
for k = self.index, #self.schematic.blocks do
local b = self.schematic.blocks[k]
local key = tostring(b.id) .. ':' .. b.dmg
local block = blocks[key]
if not block then
block = Util.shallowCopy(b)
block.qty = 0
block.need = 0
blocks[key] = block
end
block.need = block.need + 1
end
return blocks
end
function Builder:substituteBlocks(throttle)
for _,b in pairs(self.schematic.blocks) do
-- replace schematic block type with substitution
local pb = blockInfo:getPlaceableBlock(b.id, b.dmg)
Util.merge(b, pb)
b.odmg = pb.odmg or pb.dmg
local sub = self.subDB:get({ b.id, b.dmg })
if sub then
b.id, b.dmg = self.subDB:extract(sub)
end
throttle()
end
end
function Builder:reloadSchematic(throttle)
self.schematic:reload(throttle)
self:substituteBlocks(throttle)
end
function Builder:log(...)
Util.print(...)
end
function Builder:dumpInventory()
end
function Builder:logBlock(index, b)
local bdir = b.direction or ''
local logText = string.format('%d %s:%d (x:%d,z:%d:y:%d) %s',
index, b.id, b.dmg, b.x, b.z, b.y, bdir)
self:log(logText)
-- self:log(b.index) -- unique identifier of block
if device.wireless_modem then
Message.broadcast('builder', { x = b.x, y = b.y, z = b.z, heading = b.heading })
end
end
function Builder:saveProgress(index)
Util.writeTable(
fs.combine(BUILDER_DIR, self.schematic.filename .. '.progress'),
{ index = index, loc = self.loc }
)
end
function Builder:loadProgress(filename)
local progress = Util.readTable(fs.combine(BUILDER_DIR, filename))
if progress then
self.index = progress.index
if self.index > #self.schematic.blocks then
self.index = 1
end
self.loc = progress.loc or { }
end
end
return Builder

84
apis/builder/commands.lua Normal file
View File

@@ -0,0 +1,84 @@
local Builder = require('builder.builder')
local Event = require('event')
local Util = require('util')
local commands = _G.commands
local fs = _G.fs
local os = _G.os
local read = _G.read
function Builder:begin()
local direction = 1
local last = #self.schematic.blocks
local throttle = Util.throttle()
local cx, cy, cz = commands.getBlockPosition()
if self.loc.x then
cx, cy, cz = self.loc.rx, self.loc.ry, self.loc.rz
end
if self.mode == 'destroy' then
direction = -1
last = 1
end
for i = self.index, last, direction do
self.index = i
local b = self.schematic:getComputedBlock(i)
if b.id ~= 'minecraft:air' then
self:logBlock(self.index, b)
local id = b.id
if self.mode == 'destroy' then
id = 'minecraft:air'
end
local function placeBlock(bid, dmg, x, y, z)
local command = table.concat({
"setblock",
cx + x + 1,
cy + y,
cz + z + 1,
bid,
dmg,
}, ' ')
commands.execAsync(command)
local result = { os.pullEvent("task_complete") }
if not result[4] then
Util.print(result[5])
if self.mode ~= 'destroy' then
read()
end
end
end
placeBlock(id, b.odmg, b.x, b.y, b.z)
if b.twoHigh then
local _, topBlock = self.schematic:findIndexAt(b.x, b.z, b.y + 1, true)
if topBlock then
placeBlock(id, topBlock.odmg, b.x, b.y + 1, b.z)
end
end
if self.mode == 'destroy' then
self:saveProgress(math.max(self.index, 1))
else
self:saveProgress(self.index + 1)
end
else
throttle() -- sleep in case there are a large # of skipped blocks
end
end
fs.delete(self.schematic.filename .. '.progress')
print('Finished')
Event.exitPullEvents()
end
return Builder

View File

@@ -1,9 +1,17 @@
local class = require('class')
local Util = require('util')
local DEFLATE = require('deflatelua')
local UI = require('ui')
local Point = require('point')
local bit = _G.bit
local fs = _G.fs
local os = _G.os
local term = _G.term
local function getHeadingInfo(heading)
return Point.headings[heading]
end
--[[
Loading and manipulating a schematic
--]]
@@ -11,8 +19,54 @@ local Point = require('point')
local schematicMagic = 0x0a00
local gzipMagic = 0x1f8b
--[[-- Spinner --]]--
local Spinner = class()
function Spinner:init(args)
local defaults = {
timeout = .095,
c = os.clock(),
spinIndex = 0,
spinSymbols = { '-', '/', '|', '\\' }
}
defaults.x, defaults.y = term.getCursorPos()
defaults.startX = defaults.x
defaults.startY = defaults.y
Util.merge(self, defaults)
Util.merge(self, args)
end
function Spinner:spin(text)
local cc = os.clock()
if text then
self.text = text
end
if cc > self.c + self.timeout then
term.setCursorPos(self.x, self.y)
local str = self.spinSymbols[self.spinIndex % #self.spinSymbols + 1]
if self.text then
str = str .. ' ' .. self.text
self.text = nil
end
term.write(str)
self.spinIndex = self.spinIndex + 1
os.sleep(0)
self.c = os.clock()
end
end
function Spinner:stop(text)
term.setCursorPos(self.x, self.y)
local str = string.rep(' ', #self.spinSymbols)
if text then
str = str .. ' ' .. text
end
term.write(str)
term.setCursorPos(self.startX, self.startY)
end
local Schematic = class()
function Schematic:init(args)
function Schematic:init()
self.blocks = { }
self.damages = { }
self.originalBlocks = { }
@@ -24,7 +78,7 @@ end
--[[
Credit to Orwell for the schematic file reader code
http://www.computercraft.info/forums2/index.php?/topic/1949-turtle-schematic-file-builder/
Some parts of the file reader code was modified from the original
--]]
@@ -48,11 +102,11 @@ function Schematic:readname(h)
local n = n1*256 + n2
local str = ""
for i=1,n do
for _=1,n do
local c = h:readbyte(h)
if c == nil then
return
end
end
str = str .. string.char(c)
end
return str
@@ -218,11 +272,11 @@ function DiskFile:close()
end
local MemoryFile = class()
function MemoryFile:init(args)
function MemoryFile:init()
self.s = { }
self.i = 1
end
function MemoryFile:open(filename)
function MemoryFile:open()
self.i = 1
end
function MemoryFile:close() end
@@ -247,7 +301,7 @@ function Schematic:decompress(ifname, spinner)
local mh = MemoryFile()
DEFLATE.gunzip({
input=function(...) spinner:spin() return ifh.read() end,
input=function() spinner:spin() return ifh.read() end,
output=function(b) mh:write(b) end,
disable_crc=true
})
@@ -276,7 +330,7 @@ function Schematic:loadpass(fh, spinner)
fh:close()
print('Assigning coords ')
spinner.text = 'Assigning coords '
local index = 1
for _, b in ipairs(self.blocks) do
while index < b.index do
@@ -309,11 +363,10 @@ function Schematic:loadpass(fh, spinner)
end
function Schematic:load(filename)
local cursorX, cursorY = term.getCursorPos()
local spinner = UI.Spinner({
x = UI.term.width,
y = cursorY - 1
local _, cy = term.getCursorPos()
local spinner = Spinner({
x = 1,
y = cy,
})
local f
@@ -322,7 +375,7 @@ function Schematic:load(filename)
filename = originalFile .. '.uncompressed'
if not fs.exists(filename) then
print('Decompressing')
spinner.text = 'Decompressing'
f = self:decompress(originalFile, spinner)
end
end
@@ -335,7 +388,7 @@ function Schematic:load(filename)
self:checkFileType(f)
print('Loading blocks ')
spinner.text = 'Loading blocks '
self:loadpass(f, spinner)
self.rowIndex = { }
@@ -352,7 +405,7 @@ function Schematic:load(filename)
end
function Schematic:assignDamages(spinner)
print('Assigning damages')
spinner.text = 'Assigning damages'
for _,b in pairs(self.blocks) do
b.dmg = self.damages[b.index] or 0
@@ -382,7 +435,7 @@ function Schematic:findIndexAt(x, z, y, allBlocks)
end
function Schematic:findBlockAtSide(b, side)
local hi = turtle.getHeadingInfo(side)
local hi = getHeadingInfo(side)
local index = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y + hi.yd)
if index then
return self.blocks[index] -- could be better
@@ -416,10 +469,10 @@ function Schematic:bestSide(b, chains, ...)
local blocks = { }
for k,d in pairs(directions) do
local hi = turtle.getHeadingInfo(d)
local hi = getHeadingInfo(d)
local sb = self:findIndexAt(b.x - hi.xd, b.z - hi.zd, b.y)
if not sb then
b.heading = turtle.getHeadingInfo(d).heading
b.heading = getHeadingInfo(d).heading
b.direction = d .. '-block'
return
end
@@ -476,7 +529,7 @@ function Schematic:bestFlipSide(b, chains)
}
local d = directions[b.direction]
local hi = turtle.getHeadingInfo(d)
local hi = getHeadingInfo(d)
local _, fb = self:findIndexAt(b.x + hi.xd, b.z + hi.zd, b.y)
if fb then
@@ -492,7 +545,7 @@ function Schematic:bestFlipSide(b, chains)
{ x = b.x - hi.xd, z = b.z - hi.zd, y = b.y }, -- room for the turtle
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
})
b.direction = turtle.getHeadingInfo((hi.heading + 2) % 4).direction .. '-block'
b.direction = getHeadingInfo((hi.heading + 2) % 4).direction .. '-block'
end
end
@@ -532,7 +585,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
table.insert(pc, { x = b.x, z = b.z, y = b.y })
b.direction = side1 .. '-block'
b.heading = turtle.getHeadingInfo(side1).heading
b.heading = getHeadingInfo(side1).heading
if b == lb then
break
@@ -550,7 +603,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
local ub = self:findBlockAtSide(fb, 'down')
if not ub then
fb.direction = side1 .. '-block'
fb.heading = turtle.getHeadingInfo(side1).heading
fb.heading = getHeadingInfo(side1).heading
else
fb.direction = od
end
@@ -564,7 +617,7 @@ function Schematic:bestOfTwoSides(b, chains, side1, side2) -- could be better
local ub = self:findBlockAtSide(lb, 'down')
if not ub then
lb.direction = side1 .. '-block'
lb.heading = turtle.getHeadingInfo(side1).heading
lb.heading = getHeadingInfo(side1).heading
else
fb.direction = od
end
@@ -581,7 +634,7 @@ function Schematic:determineBlockPlacement(y)
print('Processing level ' .. y)
local spinner = UI.Spinner({
local spinner = Spinner({
x = 1,
spinSymbols = { 'o.....', '.o....', '..o...', '...o..', '....o.', '.....o' }
})
@@ -709,12 +762,12 @@ function Schematic:determineBlockPlacement(y)
spinner:spin(#dirtyBlocks + #dirtyBlocks2 .. ' blocks remaining ')
if directions[d] then
b.heading = turtle.getHeadingInfo(directions[d]).heading
b.heading = getHeadingInfo(directions[d]).heading
end
if doorDirections[d] then
local hi = turtle.getHeadingInfo(doorDirections[d])
local hi = getHeadingInfo(doorDirections[d])
b.heading = hi.heading
self:addPlacementChain(chains, {
@@ -726,9 +779,9 @@ function Schematic:determineBlockPlacement(y)
if stairDownDirections[d] then
if not self:findIndexAt(b.x, b.z, b.y-1) then
b.direction = stairDownDirections[b.direction]
b.heading = turtle.getHeadingInfo(b.direction).heading
b.heading = getHeadingInfo(b.direction).heading
else
b.heading = turtle.getHeadingInfo(stairDownDirections[b.direction]).heading
b.heading = getHeadingInfo(stairDownDirections[b.direction]).heading
end
end
@@ -757,7 +810,7 @@ function Schematic:determineBlockPlacement(y)
-- otherwise, the turtle must place the block from the same plane
-- against another block
-- if no block to place against (from side) then the turtle must place from
-- the other side
-- the other side
--
-- Stair bug in 1.7 - placing a stair southward doesn't respect the turtle's direction
-- all other directions are fine
@@ -767,7 +820,7 @@ function Schematic:determineBlockPlacement(y)
if self:findIndexAt(b.x, b.z, b.y-1) then
-- there's a block below
b.direction = sd[1]
b.heading = turtle.getHeadingInfo(b.direction).heading
b.heading = getHeadingInfo(b.direction).heading
else
local _,pb = self:findIndexAt(b.x + sd[3], b.z + sd[4], b.y)
if pb and pb.direction ~= sd[5] then
@@ -775,7 +828,7 @@ function Schematic:determineBlockPlacement(y)
d = sd[2] -- fall through to the blockDirections code below
b.direction = sd[2]
else
b.heading = (turtle.getHeadingInfo(sd[1]).heading + 2) % 4
b.heading = (getHeadingInfo(sd[1]).heading + 2) % 4
end
end
elseif flipDirections[d] then
@@ -784,7 +837,7 @@ function Schematic:determineBlockPlacement(y)
if blockDirections[d] then
-- placing a block from the side
local hi = turtle.getHeadingInfo(blockDirections[d])
local hi = getHeadingInfo(blockDirections[d])
b.heading = hi.heading
self:addPlacementChain(chains, {
{ x = b.x + hi.xd, z = b.z + hi.zd, y = b.y }, -- block we are placing against
@@ -843,8 +896,6 @@ end
-- set the order for block dependencies
function Schematic:setPlacementOrder(spinner, placementChains)
local cursorX, cursorY = term.getCursorPos()
-- optimize for overlapping check
for _,chain in pairs(placementChains) do
for index,_ in pairs(chain.keys) do
@@ -917,9 +968,9 @@ function Schematic:setPlacementOrder(spinner, placementChains)
]]--
local masterChain = table.remove(chains)
--[[ it's something like this:
A chain B chain result
1 1
2 -------- 2 2
@@ -1040,12 +1091,10 @@ v.info = 'Unplaceable'
end
term.clearLine()
return t
end
function Schematic:optimizeRoute(spinner, y)
local function getNearestNeighbor(p, pt, maxDistance)
local key, block, heading
local moves = maxDistance
@@ -1115,8 +1164,8 @@ function Schematic:optimizeRoute(spinner, y)
return block
end
local pt = Util.shallowCopy(self.cache[y - 1] or turtle.point)
local t = {}
local pt = Util.shallowCopy(self.cache[y - 1] or { x = -1, y = 0, z = -1, heading = 0 })
local t = { }
local ri = self.rowIndex[y]
local blockCount = ri.e - ri.s + 1
@@ -1146,7 +1195,6 @@ function Schematic:optimizeRoute(spinner, y)
local maxDistance = self.width*self.length
local plane, doors = extractPlane(y)
spinner:spin(percent)
pt.index = 0
for i = 1, #plane do
local b = getNearestNeighbor(plane, pt, maxDistance)

1248
apis/builder/turtle.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@ local convertNames = {
displayName = 'display_name',
maxDamage = 'max_dmg',
}
local keys = {
local keys = {
'damage',
'displayName',
'maxCount',
@@ -31,7 +31,7 @@ local function safeString(text)
local newText = {}
for i = 4, #text do
local val = text:byte(i)
val = text:byte(i)
newText[i - 3] = (val > 31 and val < 127) and val or 63
end
return string.char(unpack(newText))
@@ -65,11 +65,11 @@ function ChestAdapter:init(args)
Util.merge(self, chest)
end
end
function ChestAdapter:isValid()
return not not self.getAllStacks
end
function ChestAdapter:refresh(throttle)
return self:listItems(throttle)
end
@@ -86,13 +86,12 @@ function ChestAdapter:listItems(throttle)
if not entry then
self.cache[key] = v
local ikey = { v.name, v.damage, v.nbtHash }
if not itemDB:get(ikey) then
if not itemDB:get(v) then
local t = { }
for _,k in pairs(keys) do
t[k] = v[k]
end
itemDB:add(ikey, t)
itemDB:add(t)
end
else
entry.count = entry.count + v.count
@@ -109,12 +108,11 @@ function ChestAdapter:getItemInfo(item)
local key = table.concat({ item.name, item.damage, item.nbtHash }, ':')
return self.cache[key]
end
function ChestAdapter:craft(id, dmg, qty)
return false
function ChestAdapter:craft()
end
function ChestAdapter:craftItems(items)
function ChestAdapter:craftItems()
end
function ChestAdapter:provide(item, qty, slot, direction)
@@ -144,7 +142,7 @@ end
function ChestAdapter:insert(slot, qty)
local s, m = pcall(function() self.pullItem(self.direction, slot, qty) end)
if not s and m then
sleep(1)
os.sleep(1)
pcall(function() self.pullItem(self.direction, slot, qty) end)
end
end

View File

@@ -5,28 +5,23 @@ local Peripheral = require('peripheral')
local ChestAdapter = class()
local keys = Util.transpose({
'damage',
'displayName',
'maxCount',
'maxDamage',
'name',
'nbtHash',
})
function ChestAdapter:init(args)
local defaults = {
name = 'chest',
direction = 'up',
wrapSide = 'bottom',
name = 'chest',
}
Util.merge(self, defaults)
Util.merge(self, args)
local chest = Peripheral.getBySide(self.wrapSide)
if not chest then
local chest
if not self.side then
chest = Peripheral.getByMethod('list')
else
chest = Peripheral.getBySide(self.side)
if chest and not chest.list then
chest = nil
end
end
if chest then
Util.merge(self, chest)
end
@@ -37,30 +32,19 @@ function ChestAdapter:isValid()
end
function ChestAdapter:getCachedItemDetails(item, k)
local key = { item.name, item.damage, item.nbtHash }
local detail = itemDB:get(key)
if not detail then
pcall(function() detail = self.getItemMeta(k) end)
if not detail then
return
end
-- NOT SUFFICIENT
if detail.name ~= item.name then
return
end
for _,k in ipairs(Util.keys(detail)) do
if not keys[k] then
detail[k] = nil
end
end
itemDB:add(key, detail)
local cached = itemDB:get(item)
if cached then
return cached
end
if detail then
return Util.shallowCopy(detail)
local s, detail = pcall(self.getItemMeta, k)
if not s or not detail or detail.name ~= item.name then
-- debug({ s, detail })
-- error('Inventory has changed')
return
end
return itemDB:add(detail)
end
function ChestAdapter:refresh(throttle)
@@ -69,33 +53,38 @@ end
-- provide a consolidated list of items
function ChestAdapter:listItems(throttle)
self.cache = { }
local cache = { }
local items = { }
throttle = throttle or Util.throttle()
for k,v in pairs(self.list()) do
local key = table.concat({ v.name, v.damage, v.nbtHash }, ':')
if v.count > 0 then
local key = table.concat({ v.name, v.damage, v.nbtHash }, ':')
local entry = self.cache[key]
if not entry then
entry = self:getCachedItemDetails(v, k)
if entry then
local entry = cache[key]
if not entry then
entry = self:getCachedItemDetails(v, k)
if not entry then
return -- Inventory has changed
end
entry = Util.shallowCopy(entry)
entry.count = 0
self.cache[key] = entry
cache[key] = entry
table.insert(items, entry)
end
end
if entry then
entry.count = entry.count + v.count
if entry then
entry.count = entry.count + v.count
end
throttle()
end
throttle()
end
itemDB:flush()
return items
if not Util.empty(items) then
self.cache = cache
return items
end
end
function ChestAdapter:getItemInfo(item)
@@ -106,34 +95,68 @@ function ChestAdapter:getItemInfo(item)
return self.cache[key]
end
function ChestAdapter:craft(name, damage, qty)
function ChestAdapter:craft()
end
function ChestAdapter:craftItems(items)
function ChestAdapter:craftItems()
end
function ChestAdapter:getPercentUsed()
if self.cache and self.getDrawerCount then
return math.floor(Util.size(self.cache) / self.getDrawerCount() * 100)
end
return 0
end
function ChestAdapter:provide(item, qty, slot, direction)
local stacks = self.list()
for key,stack in pairs(stacks) do
if stack.name == item.name and stack.damage == item.damage then
local amount = math.min(qty, stack.count)
if amount > 0 then
self.pushItems(direction or self.direction, key, amount, slot)
end
qty = qty - amount
if qty <= 0 then
break
local s, m = pcall(function()
local stacks = self.list()
for key,stack in Util.rpairs(stacks) do
if stack.name == item.name and
(not item.damage or stack.damage == item.damage) and
(not item.nbtHash or stack.nbtHash == item.nbtHash) then
local amount = math.min(qty, stack.count)
if amount > 0 then
self.pushItems(direction or self.direction, key, amount, slot)
end
qty = qty - amount
if qty <= 0 then
break
end
end
end
end
end)
return s, m
end
function ChestAdapter:eject(item, qty, direction)
local s, m = pcall(function()
local stacks = self.list()
local maxStack = itemDB:getMaxCount(item)
for key,stack in Util.rpairs(stacks) do
if stack.name == item.name and
(not item.damage or stack.damage == item.damage) and
(not item.nbtHash or stack.nbtHash == item.nbtHash) then
local amount = math.min(maxStack, math.min(qty, stack.count))
if amount > 0 then
self.drop(key, amount, direction)
end
qty = qty - amount
if qty <= 0 then
break
end
end
end
end)
return s, m
end
function ChestAdapter:extract(slot, qty, toSlot)
self.pushItems(self.direction, slot, qty, toSlot)
end
function ChestAdapter:insert(slot, qty)
self.pullItems(self.direction, slot, qty)
function ChestAdapter:insert(slot, qty, toSlot)
self.pullItems(self.direction, slot, qty, toSlot)
end
return ChestAdapter

View File

@@ -0,0 +1,18 @@
local Adapter = { }
function Adapter.wrap(args)
local adapters = {
'refinedAdapter',
'meAdapter',
}
for _,adapterType in ipairs(adapters) do
local adapter = require(adapterType)(args)
if adapter:isValid() then
return adapter
end
end
end
return Adapter

52
apis/inventoryAdapter.lua Normal file
View File

@@ -0,0 +1,52 @@
local Util = require('util')
local Adapter = { }
function Adapter.wrap(args)
local adapters = {
--'refinedAdapter',
'chestAdapter18',
'meAdapter',
'chestAdapter',
}
if args and args.side and args.facing and not args.direction then
args = Util.shallowCopy(args)
local horz = { top = 'down', bottom = 'up' }
args.direction = horz[args.side]
if not args.direction then
local sides = {
front = 0,
back = 2,
right = 1,
left = 3,
}
-- pretty sure computer/turtle have sides reversed
local cards = {
east = 0,
south = 1,
west = 2,
north = 3,
}
local icards = {
[ 0 ] = 'west',
[ 1 ] = 'north',
[ 2 ] = 'east',
[ 3 ] = 'south',
}
args.direction = icards[(cards[args.facing] + sides[args.side]) % 4]
end
end
for _,adapterType in ipairs(adapters) do
local adapter = require(adapterType)(args)
if adapter:isValid() then
return adapter
end
end
end
return Adapter

View File

@@ -4,73 +4,165 @@ local Util = require('util')
local itemDB = TableDB({ fileName = 'usr/config/items.db' })
local function splitKey(key, item)
local function safeString(text)
local val = text:byte(1)
if val < 32 or val > 128 then
local newText = { }
local skip = 0
for i = 1, #text do
val = text:byte(i)
if val == 167 then
skip = 2
end
if skip > 0 then
skip = skip - 1
else
if val >= 32 and val <= 128 then
newText[#newText + 1] = val
end
end
end
return string.char(unpack(newText))
end
return text
end
local function makeKey(item)
return table.concat({ item.name, item.damage or '*', item.nbtHash }, ':')
end
function itemDB:splitKey(key, item)
item = item or { }
local t = Util.split(key, '(.-):')
if #t[#t] > 8 then
item.nbtHash = table.remove(t)
end
item.damage = tonumber(table.remove(t))
local damage = table.remove(t)
if damage ~= '*' then
item.damage = tonumber(damage)
end
item.name = table.concat(t, ':')
return item
end
function itemDB:get(key)
if type(key) == 'string' then
key = self:splitKey(key)
end
local item = TableDB.get(self, key)
local item = TableDB.get(self, makeKey(key))
if item then
return item
end
if key[2] ~= 0 then
item = TableDB.get(self, { key[1], 0, key[3] })
if item and item.maxDamage > 0 then
-- try finding an item that has damage values
if type(key.damage) == 'number' then
item = TableDB.get(self, makeKey({ name = key.name, nbtHash = key.nbtHash }))
if item and item.maxDamage then
item = Util.shallowCopy(item)
item.damage = key[2]
item.displayName = string.format('%s (damage: %d)', item.displayName, item.damage)
item.damage = key.damage
if item.maxDamage > 0 and type(item.damage) == 'number' and item.damage > 0 then
item.displayName = string.format('%s (damage: %s)', item.displayName, item.damage)
end
return item
end
end
if key.nbtHash then
item = self:get({ name = key.name, damage = key.damage })
if item and item.ignoreNBT then
item = Util.shallowCopy(item)
item.nbtHash = key.nbtHash
item.damage = key.damage
return item
end
end
end
function itemDB:add(key, item)
--[[
If the base item contains an NBT hash, then the NBT hash uniquely
identifies this item.
]]--
function itemDB:add(baseItem)
local nItem = {
name = baseItem.name,
damage = baseItem.damage,
nbtHash = baseItem.nbtHash,
}
-- if detail.maxDamage > 0 then
-- nItem.damage = '*'
-- end
if item.maxDamage > 0 then
key = { key[1], 0, key[3] }
nItem.displayName = safeString(baseItem.displayName)
nItem.maxCount = baseItem.maxCount
nItem.maxDamage = baseItem.maxDamage
for k,item in pairs(self.data) do
if nItem.name == item.name and
nItem.displayName == item.displayName then
if nItem.nbtHash ~= item.nbtHash and nItem.damage ~= item.damage then
nItem.damage = '*'
nItem.nbtHash = nil
nItem.ignoreNBT = true
self.data[k] = nil
break
elseif nItem.damage ~= item.damage then
nItem.damage = '*'
self.data[k] = nil
break
elseif nItem.nbtHash ~= item.nbtHash then
nItem.nbtHash = nil
nItem.ignoreNBT = true
self.data[k] = nil
break
end
end
end
TableDB.add(self, key, item)
end
function itemDB:makeKey(item)
return { item.name, item.damage, item.nbtHash }
TableDB.add(self, makeKey(nItem), nItem)
nItem = Util.shallowCopy(nItem)
nItem.damage = baseItem.damage
nItem.nbtHash = baseItem.nbtHash
return nItem
end
-- Accepts: "minecraft:stick:0" or { name = 'minecraft:stick', damage = 0 }
function itemDB:getName(item)
if type(item) == 'string' then
item = splitKey(item)
item = self:splitKey(item)
end
local detail = self:get(self:makeKey(item))
local detail = self:get(item)
if detail then
return detail.displayName
end
-- fallback to nameDB
return nameDB:getName(item.name .. ':' .. item.damage)
return nameDB:getName(item.name .. ':' .. (item.damage or '*'))
end
function itemDB:getMaxCount(item)
local detail = self:get(item)
if detail then
return detail.maxCount
end
return 64
end
function itemDB:load()
TableDB.load(self)
for key,item in pairs(self.data) do
splitKey(key, item)
self:splitKey(key, item)
item.maxDamage = item.maxDamage or 0
item.maxCount = item.maxCount or 64
end
@@ -85,6 +177,7 @@ function itemDB:flush()
v.name = nil
v.damage = nil
v.nbtHash = nil
v.count = nil -- wipe out previously saved counts - temporary
if v.maxDamage == 0 then
v.maxDamage = nil
end

View File

@@ -3,7 +3,8 @@ local itemDB = require('itemDB')
local Peripheral = require('peripheral')
local Util = require('util')
local MEAdapter = class()
local os = _G.os
local peripheral = _G.peripheral
local convertNames = {
name = 'id',
@@ -13,7 +14,7 @@ local convertNames = {
displayName = 'display_name',
maxDamage = 'max_dmg',
}
local keys = {
local keys = {
'damage',
'displayName',
'maxCount',
@@ -31,7 +32,7 @@ local function safeString(text)
local newText = {}
for i = 4, #text do
local val = text:byte(i)
val = text:byte(i)
newText[i - 3] = (val > 31 and val < 127) and val or 63
end
return string.char(unpack(newText))
@@ -48,31 +49,33 @@ local function convertItem(item)
item.displayName = safeString(item.displayName)
end
local MEAdapter = class()
function MEAdapter:init(args)
local defaults = {
items = { },
name = 'ME',
jobList = { },
direction = 'up',
wrapSide = 'bottom',
auto = false,
}
Util.merge(self, defaults)
Util.merge(self, args)
if self.auto then
local mep = Peripheral.getByMethod('getAvailableItems')
if mep then
Util.merge(self, mep)
end
local chest
if not self.side then
chest = Peripheral.getByMethod('getAvailableItems')
else
local mep = peripheral.wrap(self.wrapSide)
if mep then
Util.merge(self, mep)
chest = Peripheral.getBySide(self.side)
if chest and not chest.getAvailableItems then
chest = nil
end
end
if chest then
Util.merge(self, chest)
end
end
function MEAdapter:isValid()
return self.getAvailableItems and self.getAvailableItems()
end
@@ -84,13 +87,8 @@ function MEAdapter:refresh()
Util.merge(v, v.item)
convertItem(v)
local key = { v.name, v.damage, v.nbtHash }
if not itemDB:get(key) then
local t = { }
for _,k in pairs(keys) do
t[k] = v[k]
end
itemDB:add(key, t)
if not itemDB:get(v) then
itemDB:add(v, v)
end
end
itemDB:flush()
@@ -102,9 +100,9 @@ function MEAdapter:listItems()
self:refresh()
return self.items
end
function MEAdapter:getItemInfo(item)
for key,i in pairs(self.items) do
for _,i in pairs(self.items) do
if item.name == i.name and item.damage == i.damage and item.nbtHash == i.nbtHash then
return i
end
@@ -123,7 +121,7 @@ function MEAdapter:isCPUAvailable()
end
end
return available
end
end
function MEAdapter:craft(item, count)
@@ -133,7 +131,7 @@ function MEAdapter:craft(item, count)
self:refresh()
local item = self:getItemInfo(item)
item = self:getItemInfo(item)
if item and item.is_craftable then
local cpus = self.getCraftingCPUs() or { }
@@ -186,8 +184,8 @@ end
function MEAdapter:isCrafting(item)
for _,v in pairs(self:getJobList()) do
if v.name == item.name and
v.damage == item.damage and
if v.name == item.name and
v.damage == item.damage and
v.nbtHash == item.nbtHash then
return true
end
@@ -220,7 +218,7 @@ function MEAdapter:provide(item, count, slot, direction)
return pcall(function()
while count > 0 do
local qty = math.min(count, 64)
local s, m = self.exportItem({
local s = self.exportItem({
id = item.name,
dmg = item.damage
}, direction or self.direction, qty, slot)
@@ -232,18 +230,14 @@ function MEAdapter:provide(item, count, slot, direction)
end
end)
end
function MEAdapter:insert(slot, count)
local s, m = pcall(function() self.pullItem(self.direction, slot, count) end)
if not s and m then
print('MEAdapter:pullItem')
print(m)
sleep(1)
os.sleep(1)
s, m = pcall(function() self.pullItem(self.direction, slot, count) end)
if not s and m then
print('MEAdapter:pullItem')
print(m)
read()
error(m)
end
end
end

View File

@@ -12,7 +12,7 @@ function nameDB:load()
end
for strId, block in pairs(blocks) do
local strId = 'minecraft:' .. strId
strId = 'minecraft:' .. strId
if type(block.name) == 'string' then
self.data[strId .. ':0'] = block.name
else

View File

@@ -5,7 +5,7 @@ local itemDB = require('itemDB')
local RefinedAdapter = class()
local keys = {
local keys = {
'damage',
'displayName',
'maxCount',
@@ -18,11 +18,22 @@ function RefinedAdapter:init(args)
local defaults = {
items = { },
name = 'refinedStorage',
direction = 'up',
wrapSide = 'bottom',
}
Util.merge(self, defaults)
Util.merge(self, args)
local controller = Peripheral.getByType('refinedstorage:controller')
local controller
if self.autoDetect then
controller = Peripheral.getByType('refinedstorage:controller')
else
controller = Peripheral.getBySide(self.wrapSide)
if controller and not controller.listAvailableItems then
controller = nil
end
end
if controller then
Util.merge(self, controller)
end
@@ -37,9 +48,7 @@ function RefinedAdapter:isOnline()
end
function RefinedAdapter:getCachedItemDetails(item)
local key = { item.name, item.damage, item.nbtHash }
local detail = itemDB:get(key)
local detail = itemDB:get(item)
if not detail then
detail = self.findItem(item)
if detail then
@@ -56,7 +65,7 @@ function RefinedAdapter:getCachedItemDetails(item)
end
detail = t
itemDB:add(key, detail)
itemDB:add(detail)
end
end
if detail then
@@ -91,10 +100,7 @@ function RefinedAdapter:listItems()
end
function RefinedAdapter:getItemInfo(fingerprint)
local key = { fingerprint.name, fingerprint.damage, fingerprint.nbtHash }
local item = itemDB:get(key)
local item = itemDB:get(fingerprint)
if not item then
return self:getCachedItemDetails(fingerprint)
end
@@ -109,8 +115,8 @@ end
function RefinedAdapter:isCrafting(item)
for _,task in pairs(self.getCraftingTasks()) do
local output = task.getPattern().outputs[1]
if output.name == item.name and
output.damage == item.damage and
if output.name == item.name and
output.damage == item.damage and
output.nbtHash == item.nbtHash then
return true
end
@@ -125,18 +131,18 @@ function RefinedAdapter:craft(item, qty)
end
end
function RefinedAdapter:craftItems(items)
function RefinedAdapter:craftItems()
return false
end
function RefinedAdapter:provide(item, qty, slot)
function RefinedAdapter:provide()
end
function RefinedAdapter:extract(slot, qty)
function RefinedAdapter:extract()
-- self.pushItems(self.direction, slot, qty)
end
function RefinedAdapter:insert(slot, qty)
function RefinedAdapter:insert()
-- self.pullItems(self.direction, slot, qty)
end

View File

@@ -11,14 +11,14 @@ function TableDB:init(args)
Util.merge(defaults, args)
Util.merge(self, defaults)
end
function TableDB:load()
local t = Util.readTable(self.fileName)
if t then
self.data = t.data or t
end
end
function TableDB:add(key, entry)
if type(key) == 'table' then
key = table.concat(key, ':')
@@ -26,19 +26,19 @@ function TableDB:add(key, entry)
self.data[key] = entry
self.dirty = true
end
function TableDB:get(key)
if type(key) == 'table' then
key = table.concat(key, ':')
end
return self.data[key]
end
function TableDB:remove(key)
self.data[key] = nil
self.dirty = true
end
function TableDB:flush()
if self.dirty then
Util.writeTable(self.fileName, self.data)

View File

@@ -1,6 +1,11 @@
local itemDB = require('itemDB')
local Util = require('util')
local fs = _G.fs
local turtle = _G.turtle
local RECIPES_DIR = 'usr/etc/recipes'
local Craft = { }
local function clearGrid(inventoryAdapter)
@@ -9,6 +14,7 @@ local function clearGrid(inventoryAdapter)
if count > 0 then
inventoryAdapter:insert(i, count)
if turtle.getItemCount(i) ~= 0 then
-- inventory is possibly full
return false
end
end
@@ -27,27 +33,44 @@ local function splitKey(key)
return item
end
local function getItemCount(items, key)
local item = splitKey(key)
function Craft.getItemCount(items, item)
if type(item) == 'string' then
item = splitKey(item)
end
local count = 0
for _,v in pairs(items) do
if v.name == item.name and
v.damage == item.damage and
(not item.damage or v.damage == item.damage) and
v.nbtHash == item.nbtHash then
return v.count
if item.damage then
return v.count
end
count = count + v.count
end
end
return 0
return count
end
local function turtleCraft(recipe, qty, inventoryAdapter)
clearGrid(inventoryAdapter)
if not clearGrid(inventoryAdapter) then
return false
end
for k,v in pairs(recipe.ingredients) do
local item = splitKey(v)
inventoryAdapter:provide(item, qty, k)
local provideQty = qty
--[[
Turtles can only craft 1 item at a time when using a tool.
if recipe.craftingTools and recipe.craftingTools[k] then
provideQty = 1
end
]]--
inventoryAdapter:provide(item, provideQty, k)
if turtle.getItemCount(k) == 0 then -- ~= qty then
-- FIX: ingredients cannot be stacked
--debug('failed ' .. v .. ' - ' .. provideQty)
return false
end
end
@@ -55,65 +78,166 @@ local function turtleCraft(recipe, qty, inventoryAdapter)
return turtle.craft()
end
function Craft.loadRecipes()
Craft.recipes = Util.readTable(fs.combine(RECIPES_DIR, 'minecraft.db')) or { }
local files = fs.list('usr/etc/recipes')
table.sort(files)
Util.removeByValue(files, 'minecraft.db')
for _,file in ipairs(files) do
local recipes = Util.readTable(fs.combine(RECIPES_DIR, file))
Util.merge(Craft.recipes, recipes)
end
local recipes = Util.readTable('usr/config/recipes.db') or { }
Util.merge(Craft.recipes, recipes)
end
function Craft.sumIngredients(recipe)
-- produces { ['minecraft:planks:0'] = 8 }
local t = { }
for _,item in pairs(recipe.ingredients) do
t[item] = (t[item] or 0) + 1
end
-- need a check for crafting tool
return t
end
function Craft.craftRecipe(recipe, count, inventoryAdapter)
if type(recipe) == 'string' then
recipe = Craft.recipes[recipe]
if not recipe then
return 0, 'No recipe'
end
end
local items = inventoryAdapter:listItems()
local function sumItems(items)
-- produces { ['minecraft:planks:0'] = 8 }
local t = {}
for _,item in pairs(items) do
t[item] = (t[item] or 0) + 1
end
return t
if not items then
return 0, 'Inventory changed'
end
count = math.ceil(count / recipe.count)
local maxCount = recipe.maxCount or math.floor(64 / recipe.count)
local summedItems = sumItems(recipe.ingredients)
for key,icount in pairs(summedItems) do
local itemCount = getItemCount(items, key)
for key,icount in pairs(Craft.sumIngredients(recipe)) do
local itemCount = Craft.getItemCount(items, key)
if itemCount < icount * count then
local irecipe = Craft.recipes[key]
if irecipe then
--Util.print('Crafting %d %s', icount * count - itemCount, key)
if not Craft.craftRecipe(irecipe,
icount * count - itemCount,
inventoryAdapter) then
local iqty = icount * count - itemCount
local crafted = Craft.craftRecipe(irecipe, iqty, inventoryAdapter)
if crafted ~= iqty then
turtle.select(1)
return
return 0
end
end
end
end
local crafted = 0
repeat
if not turtleCraft(recipe, math.min(count, maxCount), inventoryAdapter) then
turtle.select(1)
return false
break
end
crafted = crafted + math.min(count, maxCount)
count = count - maxCount
until count <= 0
turtle.select(1)
return true
return crafted * recipe.count
end
local function makeRecipeKey(item)
if type(item) == 'string' then
item = splitKey(item)
end
return table.concat({ item.name, item.damage or 0, item.nbtHash }, ':')
end
function Craft.findRecipe(item)
return Craft.recipes[makeRecipeKey(item)]
end
-- determine the full list of ingredients needed to craft
-- a quantity of a recipe.
function Craft.getResourceList(recipe, items, inCount)
local summed = { }
local function sumItems(key, count)
local item = itemDB:splitKey(key)
local summedItem = summed[key]
if not summedItem then
summedItem = Util.shallowCopy(item)
summedItem.recipe = Craft.findRecipe(key)
summedItem.count = Craft.getItemCount(items, item)
summedItem.displayName = itemDB:getName(item)
summedItem.total = 0
summedItem.need = 0
summedItem.used = 0
summed[key] = summedItem
end
local total = count
local used = math.min(summedItem.count, total)
local need = total - used
if summedItem.recipe and summedItem.recipe.craftingTools and summedItem.recipe.craftingTools[key] then
summedItem.total = 1
if summedItem.count > 0 then
summedItem.used = 1
summedItem.need = 0
need = 0
else
if not summedItem.recipe then
summedItem.need = 1
need = 1
end
end
else
summedItem.total = summedItem.total + total
summedItem.count = summedItem.count - used
summedItem.used = summedItem.used + used
if not summedItem.recipe then
summedItem.need = summedItem.need + need
end
end
if need > 0 and summedItem.recipe then
need = math.ceil(need / summedItem.recipe.count)
for ikey,iqty in pairs(Craft.sumIngredients(summedItem.recipe)) do
sumItems(ikey, math.ceil(need * iqty))
end
end
end
inCount = math.ceil(inCount / recipe.count)
for ikey,iqty in pairs(Craft.sumIngredients(recipe)) do
sumItems(ikey, math.ceil(inCount * iqty))
end
return summed
end
function Craft.getResourceList4(inRecipe, items, count)
local summed = Craft.getResourceList(inRecipe, items, count)
-- filter down to just raw materials
return Util.filter(summed, function(a) return a.used > 0 or a.need > 0 end)
end
-- given a certain quantity, return how many of those can be crafted
function Craft.getCraftableAmount(recipe, count, items, missing)
local function sumItems(recipe, items, summedItems, count)
local function sumItems(recipe, summedItems, count)
local canCraft = 0
for i = 1, count do
for _ = 1, count do
for _,item in pairs(recipe.ingredients) do
local summedItem = summedItems[item] or getItemCount(items, item)
local summedItem = summedItems[item] or Craft.getItemCount(items, item)
local irecipe = Craft.recipes[item]
if irecipe and summedItem <= 0 then
summedItem = summedItem + sumItems(irecipe, items, summedItems, 1)
summedItem = summedItem + sumItems(irecipe, summedItems, 1)
end
if summedItem <= 0 then
if missing then
@@ -121,7 +245,9 @@ function Craft.getCraftableAmount(recipe, count, items, missing)
end
return canCraft
end
summedItems[item] = summedItem - 1
if not recipe.craftingTools or not recipe.craftingTools[item] then
summedItems[item] = summedItem - 1
end
end
canCraft = canCraft + recipe.count
end
@@ -129,7 +255,7 @@ function Craft.getCraftableAmount(recipe, count, items, missing)
return canCraft
end
return sumItems(recipe, items, { }, math.ceil(count / recipe.count), missing)
return sumItems(recipe, { }, math.ceil(count / recipe.count))
end
function Craft.canCraft(item, count, items)
@@ -148,13 +274,15 @@ function Craft.getCraftableAmountTest()
{ name = 'minecraft:planks', damage = 0, count = 5 },
{ name = 'minecraft:log', damage = 0, count = 2 },
}
results[1] = { item = 'chest', expected = 1, got = Craft.getCraftableAmount(Craft.recipes['minecraft:chest:0'], 2, items) }
results[1] = { item = 'chest', expected = 1,
got = Craft.getCraftableAmount(Craft.recipes['minecraft:chest:0'], 2, items) }
items = {
{ name = 'minecraft:log', damage = 0, count = 1 },
{ name = 'minecraft:coal', damage = 1, count = 1 },
}
results[2] = { item = 'torch', expected = 4, got = Craft.getCraftableAmount(Craft.recipes['minecraft:torch:0'], 4, items) }
results[2] = { item = 'torch', expected = 4,
got = Craft.getCraftableAmount(Craft.recipes['minecraft:torch:0'], 4, items) }
return results
end
@@ -166,4 +294,6 @@ function Craft.craftRecipeTest(name, count)
return { Craft.craftRecipe(Craft.recipes[name], count, chestAdapter) }
end
Craft.loadRecipes()
return Craft

67
apis/turtle/crafting.lua Normal file
View File

@@ -0,0 +1,67 @@
local Adapter = require('inventoryAdapter')
local Craft = require('turtle.craft')
local turtle = _G.turtle
local CRAFTING_TABLE = 'minecraft:crafting_table'
local function clearGrid(inventory)
print('clearing')
for i = 1, 16 do
local count = turtle.getItemCount(i)
if count > 0 then
inventory:insert(i, count)
if turtle.getItemCount(i) ~= 0 then
print('failed to insert')
return false
end
end
end
return true
end
function turtle.craftItem(item, count, inventoryInfo)
local success, msg
local inventory = Adapter.wrap(inventoryInfo)
if not inventory then
return false, 'Invalid inventory'
end
local equipped, side
if not turtle.isEquipped('workbench') then
local modemSide = turtle.isEquipped('modem') or 'right'
local osides = { left = 'right', right = 'left' }
side = osides[modemSide]
if not turtle.select(CRAFTING_TABLE) then
clearGrid(inventory)
if not turtle.selectOpenSlot() then
return false, 'Inventory is full'
end
if not inventory:provide({ name = CRAFTING_TABLE, damage = 0 }, 1) then
return false, 'Missing crafting table'
end
end
local slot = turtle.select(CRAFTING_TABLE)
turtle.equip(side, CRAFTING_TABLE)
equipped = turtle.getItemDetail(slot.index)
end
clearGrid(inventory)
success, msg = Craft.craftRecipe(item, count or 1, inventory)
if equipped then
turtle.selectOpenSlot()
inventory:provide({ name = equipped.name, damage = equipped.damage }, 1)
turtle.equip(side, equipped.name .. ':' .. equipped.damage)
end
return success, msg
end
function turtle.canCraft(item, count, items)
return Craft.canCraft(item, count, items)
end
return true

42
apis/turtle/home.lua Normal file
View File

@@ -0,0 +1,42 @@
local Config = require('config')
local GPS = require('gps')
local turtle = _G.turtle
local Home = { }
function Home.go()
local config = { }
Config.load('gps', config)
if config.home then
if turtle.enableGPS() then
return turtle.pathfind(config.home)
end
end
end
function Home.set()
local config = { }
Config.load('gps', config)
local pt = GPS.getPoint()
if pt then
local originalHeading = turtle.point.heading
local heading = GPS.getHeading()
if heading then
local turns = (turtle.point.heading - originalHeading) % 4
pt.heading = (heading - turns) % 4
config.home = pt
Config.update('gps', config)
pt = GPS.getPoint()
pt.heading = heading
turtle.setPoint(pt, true)
turtle._goto(config.home)
return config.home
end
end
end
return Home

View File

@@ -1,6 +1,8 @@
local Point = require('point')
local Util = require('util')
local turtle = _G.turtle
local checkedNodes = { }
local nodes = { }
local box = { }
@@ -11,7 +13,6 @@ local function toKey(pt)
end
local function addNode(node)
for i = 0, 5 do
local hi = turtle.getHeadingInfo(i)
local testNode = { x = node.x + hi.xd, y = node.y + hi.yd, z = node.z + hi.zd }
@@ -26,14 +27,13 @@ local function addNode(node)
end
local function dig(action)
local directions = {
top = 'up',
bottom = 'down',
}
-- convert to up, down, north, south, east, west
local direction = directions[action.side] or
local direction = directions[action.side] or
turtle.getHeadingInfo(turtle.point.heading).direction
local hi = turtle.getHeadingInfo(direction)
@@ -75,7 +75,7 @@ end
-- find the closest block
-- * favor same plane
-- * going backwards only if the dest is above or below
function closestPoint(reference, pts)
local function closestPoint(reference, pts)
local lpt, lm -- lowest
for _,pt in pairs(pts) do
local m = Point.turtleDistance(reference, pt)
@@ -113,8 +113,7 @@ local function getAdjacentPoint(pt)
return closestPoint(turtle.getPoint(), t)
end
return function(startPt, endPt, firstPt, verbose)
function turtle.level(startPt, endPt, firstPt, verbose)
checkedNodes = { }
nodes = { }
box = { }
@@ -126,6 +125,10 @@ return function(startPt, endPt, firstPt, verbose)
box.ey = math.max(startPt.y, endPt.y)
box.ez = math.max(startPt.z, endPt.z)
if not Point.inBox(firstPt, box) then
error('Starting point is not in leveling area')
end
if not turtle.pathfind(firstPt) then
error('failed to reach starting point')
end
@@ -155,11 +158,13 @@ return function(startPt, endPt, firstPt, verbose)
local node = closestPoint(turtle.point, nodes)
node = getAdjacentPoint(node)
if not turtle.gotoPoint(node) then
if not turtle._goto(node) then
break
end
until turtle.abort
until turtle.isAborted()
turtle.resetState()
turtle.setMoveCallback(oldCallback)
end
return true

View File

@@ -1,25 +1,28 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Ansi = require('ansi')
local Config = require('config')
local SHA1 = require('sha1')
local UI = require('ui')
local Util = require('util')
-- scrap this entire file. don't muck with standard apis
local fs = _G.fs
local http = _G.http
local multishell = _ENV.multishell
local os = _G.os
local shell = _ENV.shell
local REGISTRY_DIR = 'usr/.registry'
-- FIX SOMEDAY
function os.registerApp(app, key)
local function registerApp(app, key)
app.key = SHA1.sha1(key)
Util.writeTable(fs.combine(REGISTRY_DIR, app.key), app)
os.queueEvent('os_register_app')
end
function os.unregisterApp(key)
local function unregisterApp(key)
local filename = fs.combine(REGISTRY_DIR, SHA1.sha1(key))
if fs.exists(filename) then
@@ -29,7 +32,7 @@ function os.unregisterApp(key)
end
local sandboxEnv = Util.shallowCopy(getfenv(1))
local sandboxEnv = Util.shallowCopy(_ENV)
setmetatable(sandboxEnv, { __index = _G })
multishell.setTitle(multishell.getCurrent(), 'App Store')
@@ -56,7 +59,7 @@ local sources = {
shell.setDir(APP_DIR)
function downloadApp(app)
local function downloadApp(app)
local h
if type(app.url) == "table" then
@@ -72,7 +75,7 @@ function downloadApp(app)
end
end
function runApp(app, checkExists, ...)
local function runApp(app, checkExists, ...)
local path, fn
local args = { ... }
@@ -82,7 +85,7 @@ function runApp(app, checkExists, ...)
else
local program = downloadApp(app)
fn = function()
fn = function()
if not program then
error('Failed to download')
@@ -173,37 +176,35 @@ local getSourceListing = function(source)
end
end
local appPage = UI.Page({
menuBar = UI.MenuBar({
showBackButton = not pocket,
local appPage = UI.Page {
menuBar = UI.MenuBar {
-- showBackButton = not pocket,
buttons = {
{ text = '\027', event = 'back' },
{ text = 'Install', event = 'install' },
{ text = 'Run', event = 'run' },
{ text = 'View', event = 'view' },
{ text = 'Remove', event = 'uninstall', name = 'removeButton' },
},
}),
container = UI.Window({
x = 2,
y = 3,
height = UI.term.height - 3,
width = UI.term.width - 2,
viewport = UI.ViewportWindow(),
}),
},
container = UI.Window {
x = 2, y = 3, ex = -2, ey = -3,
viewport = UI.Viewport(),
},
notification = UI.Notification(),
accelerators = {
q = 'back',
backspace = 'back',
},
})
}
function appPage.container.viewport:draw()
local app = self.parent.parent.app
local str = string.format(
'%s \nBy: %s \nCategory: %s\nFile name: %s\n\n%s',
Ansi.yellow .. app.title .. Ansi.reset,
app.creator,
app.categoryName, app.name,
app.creator,
app.categoryName, app.name,
Ansi.yellow .. app.description .. Ansi.reset)
self:clear()
@@ -245,7 +246,7 @@ function appPage:eventHandler(event)
elseif event.type == 'uninstall' then
if self.app.runOnly then
s,m = runApp(self.app, false, 'uninstall')
runApp(self.app, false, 'uninstall')
else
fs.delete(fs.combine(APP_DIR, self.app.name))
self.notification:success("Uninstalled " .. self.app.name, 3)
@@ -253,7 +254,7 @@ function appPage:eventHandler(event)
self.menuBar.removeButton:disable('Remove')
self.menuBar:draw()
os.unregisterApp(self.app.creator .. '.' .. self.app.name)
unregisterApp(self.app.creator .. '.' .. self.app.name)
end
elseif event.type == 'install' then
@@ -277,7 +278,7 @@ function appPage:eventHandler(event)
category = 'Games'
end
os.registerApp({
registerApp({
run = fs.combine(APP_DIR, self.app.name),
title = self.app.title,
category = category,
@@ -293,35 +294,30 @@ function appPage:eventHandler(event)
return true
end
local categoryPage = UI.Page({
menuBar = UI.MenuBar({
local categoryPage = UI.Page {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Catalog', event = 'dropdown', dropdown = 'sourceMenu' },
{ text = 'Category', event = 'dropdown', dropdown = 'categoryMenu' },
{ text = 'Catalog', dropdown = sources },
{ text = 'Category', name = 'categoryButton', dropdown = { } },
},
}),
sourceMenu = UI.DropMenu({
buttons = sources,
}),
grid = UI.ScrollingGrid({
y = 2,
height = UI.term.height - 2,
},
grid = UI.ScrollingGrid {
y = 2, ey = -2,
columns = {
{ heading = 'Title', key = 'title' },
},
sortColumn = 'title',
autospace = true,
}),
},
statusBar = UI.StatusBar(),
accelerators = {
l = 'lua',
q = 'quit',
},
})
}
function categoryPage:setCategory(source, name, index)
self.grid.values = { }
for k,v in pairs(source.storeURLs) do
for _,v in pairs(source.storeURLs) do
if index == 0 or index == v.catagory then
table.insert(self.grid.values, v)
end
@@ -346,7 +342,7 @@ function categoryPage:setSource(source)
end
local buttons = { }
for k,v in Util.spairs(source.storeCatagoryNames,
for k,v in Util.spairs(source.storeCatagoryNames,
function(a, b) return a:lower() < b:lower() end) do
if v ~= 'Operating System' then
@@ -359,19 +355,17 @@ function categoryPage:setSource(source)
end
source.categoryMenu = UI.DropMenu({
y = 2,
x = 1,
buttons = buttons,
})
source.index, source.name = Util.first(source.storeCatagoryNames)
categoryPage:add({
categoryPage.menuBar.categoryButton:add({
categoryMenu = source.categoryMenu
})
end
self.source = source
self.categoryMenu = source.categoryMenu
self.menuBar.categoryButton.dropmenu = source.categoryMenu
categoryPage:setCategory(source, source.name, source.index)
end

View File

@@ -1,9 +1,12 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Event = require('event')
local UI = require('ui')
local Util = require('util')
local multishell = _ENV.multishell
local os = _G.os
multishell.setTitle(multishell.getCurrent(), 'Events')
UI:configure('Events', ...)
@@ -123,7 +126,7 @@ Event.addRoutine(function()
p4 = e[5],
p5 = e[6],
})
if #page.grid.values > page.grid.height - 1 then
if #page.grid.values > page.grid.height then
table.remove(page.grid.values, #page.grid.values)
end
page.grid:update()

View File

@@ -1,24 +1,29 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Ansi = require('ansi')
local Event = require('event')
local UI = require('ui')
local Util = require('util')
local colors = _G.colors
local multishell = _ENV.multishell
local peripheral = _G.peripheral
multishell.setTitle(multishell.getCurrent(), 'Devices')
--[[ -- PeripheralsPage -- ]] --
local peripheralsPage = UI.Page {
grid = UI.ScrollingGrid {
columns = {
ey = -2,
columns = {
{ heading = 'Type', key = 'type' },
{ heading = 'Side', key = 'side' },
},
},
sortColumn = 'type',
height = UI.term.height - 1,
autospace = true,
},
statusBar = UI.StatusBar {
status = 'Select peripheral'
values = 'Select peripheral',
},
accelerators = {
q = 'quit',
@@ -60,16 +65,17 @@ end
--[[ -- MethodsPage -- ]] --
local methodsPage = UI.Page {
grid = UI.ScrollingGrid {
columns = {
{ heading = 'Name', key = 'name', width = UI.term.width }
},
sortColumn = 'name',
height = 7,
backgroundColor = colors.black,
doc = UI.TextArea {
backgroundColor = colors.black,
x = 2, y = 2, ex = -1, ey = -7,
},
viewportConsole = UI.ViewportWindow {
y = 8,
height = UI.term.height - 8,
grid = UI.ScrollingGrid {
y = -6, ey = -2,
columns = {
{ heading = 'Name', key = 'name', width = UI.term.width }
},
sortColumn = 'name',
},
statusBar = UI.StatusBar {
status = 'q to return',
@@ -84,8 +90,9 @@ function methodsPage:enable(p)
self.peripheral = p or self.peripheral
local p = peripheral.wrap(self.peripheral.side)
p = peripheral.wrap(self.peripheral.side)
if p.getDocs then
-- plethora
self.grid.values = { }
for k,v in pairs(p.getDocs()) do
table.insert(self.grid.values, {
@@ -94,27 +101,31 @@ function methodsPage:enable(p)
})
end
elseif not p.getAdvancedMethodsData then
-- computercraft
self.grid.values = { }
for name,f in pairs(p) do
for name in pairs(p) do
table.insert(self.grid.values, {
name = name,
noext = true,
})
end
else
-- open peripherals
self.grid.values = p.getAdvancedMethodsData()
for name,f in pairs(self.grid.values) do
f.name = name
end
end
self.viewportConsole.offy = 0
self.grid:update()
self.grid:setIndex(1)
self.doc:setText(self:getDocumentation())
self.statusBar:setStatus(self.peripheral.type)
UI.Page.enable(self)
self:setFocus(self.grid)
end
function methodsPage:eventHandler(event)
@@ -122,82 +133,62 @@ function methodsPage:eventHandler(event)
UI:setPage(peripheralsPage)
return true
elseif event.type == 'grid_focus_row' then
self.viewportConsole.offy = 0
self.viewportConsole:draw()
self.doc:setText(self:getDocumentation())
end
return UI.Page.eventHandler(self, event)
end
function methodsPage.viewportConsole:draw()
local c = self
local method = methodsPage.grid:getSelected()
function methodsPage:getDocumentation()
c:clear()
c:setCursorPos(1, 1)
local method = self.grid:getSelected()
if method.noext then
c.cursorY = 2
c:print('No extended Information')
return 2
if method.noext then -- computercraft docs
return 'No documentation'
end
if method.doc then
c:print(method.doc, nil, colors.yellow)
c.ymax = c.cursorY + 1
return
if method.doc then -- plethora docs
return Ansi.yellow .. method.doc
end
-- open peripherals docs
local sb = { }
if method.description then
c:print(method.description)
table.insert(sb, method.description .. '\n\n')
end
c.cursorY = c.cursorY + 2
c.cursorX = 1
if method.returnTypes ~= '()' then
c:print(method.returnTypes .. ' ', nil, colors.yellow)
table.insert(sb, Ansi.yellow .. method.returnTypes .. ' ')
end
c:print(method.name, nil, colors.black)
c:print('(')
local maxArgLen = 1
table.insert(sb, Ansi.blue .. method.name .. Ansi.reset .. '(')
for k,arg in ipairs(method.args) do
if #arg.description > 0 then
maxArgLen = math.max(#arg.name, maxArgLen)
end
local argName = arg.name
local fg = colors.green
if arg.optional then
argName = string.format('[%s]', arg.name)
fg = colors.orange
table.insert(sb, Ansi.orange .. string.format('[%s]', arg.name))
else
table.insert(sb, Ansi.green .. arg.name)
end
c:print(argName, nil, fg)
if k < #method.args then
c:print(', ')
table.insert(sb, ',')
end
end
c:print(')')
c.cursorY = c.cursorY + 1
table.insert(sb, Ansi.reset .. ')')
Util.filterInplace(method.args, function(a) return #a.description > 0 end)
if #method.args > 0 then
for _,arg in ipairs(method.args) do
if #arg.description > 0 then
c.cursorY = c.cursorY + 1
c.cursorX = 1
local fg = colors.green
if arg.optional then
fg = colors.orange
end
c:print(arg.name .. ': ', nil, fg)
c.cursorX = maxArgLen + 3
c:print(arg.description, nil, nil, maxArgLen + 3)
table.insert(sb, '\n\n')
for k,arg in ipairs(method.args) do
if arg.optional then
table.insert(sb, Ansi.orange)
else
table.insert(sb, Ansi.green)
end
table.insert(sb, arg.name .. Ansi.reset .. ': ' .. arg.description)
if k ~= #method.args then
table.insert(sb, '\n\n')
end
end
end
c.ymax = c.cursorY + 1
return table.concat(sb)
end
Event.on('peripheral', function()

View File

@@ -1,4 +1,4 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Config = require('config')
local Event = require('event')
@@ -6,6 +6,12 @@ local Socket = require('socket')
local UI = require('ui')
local Util = require('util')
local colors = _G.colors
local fs = _G.fs
local multishell = _ENV.multishell
local os = _G.os
local shell = _ENV.shell
local GROUPS_PATH = 'usr/groups'
local SCRIPTS_PATH = 'usr/etc/scripts'
@@ -26,7 +32,7 @@ if UI.term.width % 2 ~= 0 then
width = width + 1
end
function processVariables(script)
local function processVariables(script)
local fn = loadstring('return ' .. config.variables)
if fn then
@@ -40,7 +46,7 @@ function processVariables(script)
return script
end
function invokeScript(computer, scriptName)
local function invokeScript(computer, scriptName)
local script = Util.readFile(scriptName)
if not script then
@@ -74,7 +80,7 @@ function invokeScript(computer, scriptName)
socket:close()
end
function runScript(computerOrGroup, scriptName)
local function runScript(computerOrGroup, scriptName)
if computerOrGroup.id then
invokeScript(computerOrGroup, scriptName)
else
@@ -208,14 +214,14 @@ local editorPage = UI.Page({
y = 3,
}),
right = UI.Button({
text = '>',
text = '>',
event = 'right',
x = width - 2,
y = 2,
width = 3,
}),
left = UI.Button({
text = '<',
text = '<',
event = 'left',
x = UI.term.width - width + 1,
y = 2,
@@ -302,7 +308,6 @@ function editorPage:enable()
end
function editorPage.grid2:draw()
getActiveComputers(self.values)
for k in pairs(editorPage.grid1.values) do
@@ -314,7 +319,6 @@ function editorPage.grid2:draw()
end
function editorPage:eventHandler(event)
if event.type == 'back' then
UI:setPage(groupsPage)
@@ -341,18 +345,17 @@ function editorPage:eventHandler(event)
end
local function nameDialog(f)
local dialog = UI.Dialog({
-- x = (UI.term.width - 28) / 2,
local dialog = UI.Dialog {
width = 22,
height = 6,
title = 'Enter Name',
form = UI.Form {
x = 2, ex = -2, y = 2,
textEntry = UI.TextEntry({ y = 2, width = 20, limit = 20 })
textEntry = UI.TextEntry { y = 2, width = 20, limit = 20 },
},
})
}
dialog.eventHandler = function(self, event)
function dialog:eventHandler(event)
if event.type == 'form_complete' then
local name = self.form.textEntry.value
if name then
@@ -459,11 +462,6 @@ function mainPage:eventHandler(event)
elseif event.type == 'toggle' then
config.showGroups = not config.showGroups
local text = 'Computers'
if config.showGroups then
text = 'Groups'
end
-- self.statusBar.toggleButton.text = text
self:draw()
Config.update('script', config)

View File

@@ -1,4 +1,4 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Config = require('config')
local Event = require('event')
@@ -8,6 +8,14 @@ local Terminal = require('terminal')
local UI = require('ui')
local Util = require('util')
local colors = _G.colors
local fs = _G.fs
local multishell = _ENV.multishell
local network = _G.network
local os = _G.os
local shell = _ENV.shell
local term = _G.term
multishell.setTitle(multishell.getCurrent(), 'Turtles')
UI.Button.defaults.focusIndicator = ' '
UI:configure('Turtles', ...)
@@ -27,15 +35,7 @@ local options = {
local SCRIPTS_PATH = 'usr/etc/scripts'
local nullTerm = Terminal.getNullTerm(term.current())
local turtles = { }
local socket
local policies = {
{ label = 'none' },
{ label = 'digOnly' },
{ label = 'attackOnly' },
{ label = 'digAttack' },
{ label = 'turtleSafe' },
}
local page = UI.Page {
coords = UI.Window {
@@ -125,7 +125,8 @@ local page = UI.Page {
fn = 'turtle.turnRight',
},
info = UI.TextArea {
x = 2, y = 9
x = 2, y = 9,
inactive = true,
}
},
},
@@ -142,7 +143,7 @@ function page:enable(turtle)
end
function page:runFunction(script, nowrap)
for i = 1, 2 do
for _ = 1, 2 do
if not socket then
socket = Socket.connect(self.turtle.id, 161)
end
@@ -186,7 +187,7 @@ function page.coords:draw()
if not t.point.gps then
ind = 'REL'
end
self:print(string.format('%s : %d,%d,%d\n Fuel: %s\n',
self:print(string.format('%s : %d,%d,%d\n Fuel: %s\n',
ind, t.point.x, t.point.y, t.point.z, Util.toBytes(t.fuel)))
end
end
@@ -210,12 +211,6 @@ function page.tabs.inventory:draw()
v.selected = true
end
if v.id then
-- local item = itemDB:get({ v.id, v.dmg })
-- if item then
-- v.id = item.displayName
-- else
-- v.id = v.id:gsub('.*:(.*)', '%1')
-- end
v.id = itemDB:getName(v)
end
end
@@ -303,14 +298,6 @@ function page.statusBar:draw()
UI.StatusBar.draw(self)
end
function page.tabs.tabBar:selectTab(tabTitle)
if tabTitle then
config.tab = tabTitle
Config.update('Turtles', config)
return UI.TabBar.selectTab(self, tabTitle)
end
end
function page:showBlocks()
local script = [[
@@ -333,6 +320,11 @@ end
function page:eventHandler(event)
if event.type == 'quit' then
UI:exitPullEvents()
elseif event.type == 'tab_select' then
config.tab = event.button.text
Config.update('Turtles', config)
elseif event.type == 'button_press' then
if event.button.fn then
self:runFunction(event.button.fn, event.button.nowrap)
@@ -356,7 +348,7 @@ if not Util.getOptions(options, { ... }, true) then
end
if options.turtle.value >= 0 then
for i = 1, 10 do
for _ = 1, 10 do
page.turtle = _G.network[options.turtle.value]
if page.turtle then
break
@@ -374,18 +366,10 @@ Event.onInterval(1, function()
end
end)
UI:setPage(page)
local lookup = {
Run = page.tabs.scripts,
Select = page.tabs.turtles,
Inv = page.tabs.inventory,
-- Mod = page.tabs.policy,
Action = page.tabs.action,
}
if lookup[options.tab.value] then
page.tabs:activateTab(lookup[options.tab.value])
if config.tab then
page.tabs.tabBar:selectTab(config.tab)
end
UI:setPage(page)
UI:pullEvents()

View File

@@ -1,6 +1,10 @@
requireInjector(getfenv(1))
_G.requireInjector()
Base64 = require('base64')
local Base64 = require('base64')
local http = _G.http
local os = _G.os
local shell = _ENV.shell
local args = { ... }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1055
apps/crafter.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,13 @@
shell.setCompletionFunction(shell.getRunningProgram(), function(shell, index, text)
local colors = _G.colors
local fs = _G.fs
local keys = _G.keys
local multishell = _ENV.multishell
local os = _G.os
local shell = _ENV.shell
local term = _G.term
local textutils = _G.textutils
shell.setCompletionFunction(shell.getRunningProgram(), function(_, index, text)
if index == 1 then
return fs.complete(text, shell.dir(), true, false)
end
@@ -17,7 +26,7 @@ if fs.exists(sPath) and fs.isDir(sPath) then
end
if multishell then
multishell.setTitle(multishell.getCurrent(), sPath)
multishell.setTitle(multishell.getCurrent(), fs.getName(sPath))
end
local x, y = 1, 1
@@ -26,43 +35,38 @@ local scrollX = 0
local scrollY = 0
local lastPos = { x = 1, y = 1 }
local tLines = { }
local input = { pressed = { } }
local bRunning = true
local sStatus = ""
local isError
local fileInfo
local lastAction
local dirty = { y = 1, ey = h }
local mark = { anchor, active, continue }
local keyboard
local mark = { }
local searchPattern
local undo = { chain = { }, pointer = 0 }
local complete = { }
local clipboard
if not clipboard then
_G.clipboard = { internal, data }
clipboard.shim = true
-- do we need a clipboard shim
if not multishell or not multishell.hook then -- is this OpusOS ?
if _G.clipboard then -- has it been installed already
clipboard = _G.clipboard
else
clipboard = { }
function clipboard.setData(data)
clipboard.data = data
if data then
clipboard.useInternal(true)
function clipboard.setData(data)
clipboard.data = data
end
end
function clipboard.getText()
if clipboard.data then
return tostring(clipboard.data)
function clipboard.getText()
if clipboard.data then
return tostring(clipboard.data)
end
end
end
function clipboard.isInternal()
return clipboard.internal
end
function clipboard.useInternal(mode)
if mode ~= clipboard.mode then
clipboard.internal = mode
end
_G.clipboard = clipboard
end
end
@@ -110,7 +114,7 @@ local keyMapping = {
[ 'control-up' ] = 'scroll_up',
[ 'scrollDown' ] = 'scroll_down',
[ 'control-down' ] = 'scroll_down',
[ 'mouse_click' ] = 'goto',
[ 'mouse_click' ] = 'go_to',
[ 'control-l' ] = 'goto_line',
-- marking
@@ -139,8 +143,7 @@ local keyMapping = {
-- copy/paste
[ 'control-x' ] = 'cut',
[ 'control-c' ] = 'copy',
[ 'control-v' ] = 'paste',
[ 'control-t' ] = 'toggle_clipboard',
[ 'shift-paste' ] = 'paste_internal',
-- file
[ 'control-s' ] = 'save',
@@ -155,7 +158,7 @@ local keyMapping = {
-- misc
[ 'control-g' ] = 'status',
[ 'control-r' ] = 'refresh',
[ 'leftCtrl' ] = 'menu',
[ 'control' ] = 'menu',
}
local messages = {
@@ -171,7 +174,7 @@ end
local function getFileInfo(path)
local abspath = shell.resolve(path)
local fi = {
abspath = abspath,
path = path,
@@ -184,7 +187,7 @@ local function getFileInfo(path)
else
fi.isReadOnly = fs.isReadOnly(fi.abspath)
end
return fi
end
@@ -246,16 +249,16 @@ local function save( _sPath )
local function innerSave()
file = fs.open( _sPath, "w" )
if file then
for n, sLine in ipairs( tLines ) do
for _,sLine in ipairs( tLines ) do
file.write(sLine .. "\n")
end
else
error( "Failed to open ".._sPath )
end
end
local ok, err = pcall( innerSave )
if file then
if file then
file.close()
end
return ok, err
@@ -265,7 +268,7 @@ local function split(str, pattern)
pattern = pattern or "(.-)\n"
local t = {}
local function helper(line) table.insert(t, line) return "" end
helper((str:gsub(pattern, helper)))
helper((str:gsub(pattern, helper)))
return t
end
@@ -299,8 +302,8 @@ local function writeHighlighted(sLine, ny)
text = '',
}
local function tryWrite(sLine, regex, fgcolor)
local match = sLine:match(regex)
local function tryWrite(line, regex, fgcolor)
local match = line:match(regex)
if match then
local fg
if type(fgcolor) == "string" then
@@ -310,13 +313,13 @@ local function writeHighlighted(sLine, ny)
end
buffer.text = buffer.text .. match
buffer.fg = buffer.fg .. string.rep(fg, #match)
return sLine:sub(#match + 1)
return line:sub(#match + 1)
end
return nil
end
while #sLine > 0 do
sLine =
while #sLine > 0 do
sLine =
tryWrite(sLine, "^%-%-%[%[.-%]%]", color.commentColor ) or
tryWrite(sLine, "^%-%-.*", color.commentColor ) or
tryWrite(sLine, "^\".-[^\\]\"", color.stringColor ) or
@@ -343,8 +346,8 @@ local function writeHighlighted(sLine, ny)
if ny == mark.ey then
ex = mark.ex
end
buffer.bg = string.rep('f', sx - 1) ..
string.rep('7', ex - sx) ..
buffer.bg = string.rep('f', sx - 1) ..
string.rep('7', ex - sx) ..
string.rep('f', #buffer.text - ex + 1)
else
@@ -388,18 +391,13 @@ local function redraw()
end
if not (w < 32 and #sStatus > 0) then
local clipboardIndicator = 'S'
if clipboard.isInternal() then
clipboardIndicator = 'I'
end
local modifiedIndicator = ' '
if undo.chain[1] then
modifiedIndicator = '*'
end
local str = string.format(' %d:%d %s%s',
y, x, clipboardIndicator, modifiedIndicator)
local str = string.format(' %d:%d %s',
y, x, modifiedIndicator)
term.setTextColor(color.highlightColor)
term.setBackgroundColor(colors.gray)
term.setCursorPos(w - #str + 1, h)
@@ -434,15 +432,15 @@ local function hacky_read()
local _oldSetCursorPos = term.setCursorPos
local _oldGetCursorPos = term.getCursorPos
term.setCursorPos = function(x, y)
return _oldSetCursorPos(x, h)
term.setCursorPos = function(cx)
return _oldSetCursorPos(cx, h)
end
term.getCursorPos = function()
local x, y = _oldGetCursorPos()
return x, 1
local cx = _oldGetCursorPos()
return cx, 1
end
local s, m = pcall(function() return read() end)
local s, m = pcall(function() return _G.read() end)
term.setCursorPos = _oldSetCursorPos
term.getCursorPos = _oldGetCursorPos
if s then
@@ -465,7 +463,7 @@ local __actions = {
term.write(prompt)
local str = hacky_read()
term.setCursorBlink(true)
keyboard.shift, keyboard.control = false, false
input:reset()
term.setCursorPos(x - scrollX, y - scrollY)
actions.dirty_line(scrollY + h)
return str
@@ -485,13 +483,6 @@ local __actions = {
addUndo = function(entry)
local last = undo.chain[#undo.chain]
if last and last.action == entry.action then
--[[
debug('---')
debug(last)
debug(last.args)
debug(entry)
debug(entry.args)
]]--
if last.action == 'deleteText' then
if last.args[3] == entry.args[1] and
last.args[4] == entry.args[2] then
@@ -512,7 +503,7 @@ local __actions = {
end,
autocomplete = function()
if keyboard.lastAction ~= 'autocomplete' or not complete.results then
if lastAction ~= 'autocomplete' or not complete.results then
local sLine = tLines[y]:sub(1, x - 1)
local nStartPos = sLine:find("[a-zA-Z0-9_%.]+$")
if nStartPos then
@@ -575,7 +566,7 @@ local __actions = {
goto_line = function()
local lineNo = tonumber(actions.input('Line: '))
if lineNo then
actions.goto(1, lineNo)
actions.go_to(1, lineNo)
else
setStatus('Invalid line number')
end
@@ -593,9 +584,9 @@ local __actions = {
if ny < y or ny == y and nx <= x then
setStatus(messages.wrapped)
end
actions.goto(nx, ny)
actions.go_to(nx, ny)
actions.mark_to(nx + #pattern, ny)
actions.goto(nx, ny)
actions.go_to(nx, ny)
return
end
sx = 1
@@ -625,7 +616,7 @@ local __actions = {
if bReadOnly then
setError("Access denied")
else
local ok, err = save(sPath)
local ok = save(sPath)
if ok then
setStatus('"%s" %dL, %dC written',
fileInfo.path, #tLines, fs.getSize(fileInfo.abspath))
@@ -641,7 +632,7 @@ local __actions = {
run = function()
local sTempPath = "/.temp"
local ok, err = save(sTempPath)
local ok = save(sTempPath)
if ok then
local nTask = shell.openTab(sTempPath)
if nTask then
@@ -732,7 +723,7 @@ local __actions = {
mark_to = function(nx, ny)
actions.mark_begin()
actions.goto(nx, ny)
actions.go_to(nx, ny)
actions.mark_finish()
end,
@@ -795,9 +786,7 @@ local __actions = {
actions.dirty_all()
end,
setCursor = function(newX, newY)
local oldX, oldY = lastPos.x, lastPos.y
setCursor = function()
lastPos.x = x
lastPos.y = y
@@ -806,27 +795,23 @@ local __actions = {
if screenX < 1 then
scrollX = x - 1
screenX = 1
actions.dirty_all()
elseif screenX > w then
scrollX = x - w
screenX = w
actions.dirty_all()
end
if screenY < 1 then
scrollY = y - 1
screenY = 1
actions.dirty_all()
elseif screenY > h - 1 then
scrollY = y - (h - 1)
screenY = h - 1
actions.dirty_all()
end
end,
top = function()
actions.goto(1, 1)
actions.go_to(1, 1)
end,
bottom = function()
@@ -856,11 +841,11 @@ local __actions = {
end,
pageUp = function()
actions.goto(x, y - (h - 1))
actions.go_to(x, y - (h - 1))
end,
pageDown = function()
actions.goto(x, y + (h - 1))
actions.go_to(x, y + (h - 1))
end,
home = function()
@@ -966,7 +951,7 @@ local __actions = {
local front = tLines[sy]:sub(1, sx - 1)
local back = tLines[ey]:sub(ex, #tLines[ey])
for k = 2, ey - sy + 1 do
for _ = 2, ey - sy + 1 do
table.remove(tLines, y + 1)
end
tLines[y] = front .. back
@@ -981,18 +966,18 @@ local __actions = {
local count = 0
local lines = { }
for y = csy, cey do
local line = tLines[y]
for cy = csy, cey do
local line = tLines[cy]
if line then
local x = 1
local cx = 1
local ex = #line
if y == csy then
x = csx
if cy == csy then
cx = csx
end
if y == cey then
if cy == cey then
ex = cex - 1
end
local str = line:sub(x, ex)
local str = line:sub(cx, ex)
count = count + #str
table.insert(lines, str)
end
@@ -1041,23 +1026,14 @@ local __actions = {
actions.insertText(x, y, ch)
end,
toggle_clipboard = function()
if clipboard.shim then
clipboard.setInternal(not clipboard.internal)
end
if clipboard.isInternal() then
setStatus('Using internal clipboard')
else
setStatus('Using system clipboard')
end
end,
copy_marked = function()
local text, size =
actions.copyText(mark.x, mark.y, mark.ex, mark.ey)
clipboard.setData(text)
setStatus('%d chars copied', size)
clipboard.useInternal(true)
local text = actions.copyText(mark.x, mark.y, mark.ex, mark.ey)
if clipboard then
clipboard.setData(text)
else
os.queueEvent('clipboard_copy', text)
end
setStatus('shift-^v to paste')
end,
cut = function()
@@ -1078,9 +1054,6 @@ local __actions = {
if mark.active then
actions.delete()
end
if clipboard.isInternal() then
text = clipboard.getText()
end
if text then
actions.insertText(x, y, text)
setStatus('%d chars added', #text)
@@ -1089,7 +1062,13 @@ local __actions = {
end
end,
goto = function(cx, cy)
paste_internal = function()
if clipboard then
actions.paste(clipboard.getText())
end
end,
go_to = function(cx, cy)
y = math.min(math.max(cy, 1), #tLines)
x = math.min(math.max(cx, 1), #tLines[y] + 1)
end,
@@ -1114,116 +1093,158 @@ local __actions = {
actions = __actions
-- Actual program functionality begins
load(sPath)
local modifiers = {
[ keys.leftCtrl ] = true,
[ keys.rightCtrl ] = true,
[ keys.leftShift ] = true,
[ keys.rightShift ] = true,
[ keys.leftAlt ] = true,
[ keys.rightAlt ] = true,
}
term.setCursorBlink(true)
redraw()
function input:modifierPressed()
return self.pressed[keys.leftCtrl] or
self.pressed[keys.rightCtrl] or
self.pressed[keys.leftAlt] or
self.pressed[keys.rightAlt]
end
if not keyboard then
keyboard = { control, shift, combo }
function input:toCode(ch, code)
local result = { }
function keyboard:translate(event, code)
if event == 'key' then
local ch = keys.getName(code)
if ch then
if self.pressed[keys.leftCtrl] or self.pressed[keys.rightCtrl] then
table.insert(result, 'control')
end
if code == keys.leftCtrl or code == keys.rightCtrl then
self.control = true
self.combo = false
return
end
if self.pressed[keys.leftAlt] or self.pressed[keys.rightAlt] then
table.insert(result, 'alt')
end
if code == keys.leftShift or code == keys.rightShift then
self.shift = true
self.combo = false
return
end
if self.shift then
if #ch > 1 then
ch = 'shift-' .. ch
elseif self.control then
-- will create control-X
-- better than shift-control-x
ch = ch:upper()
end
self.combo = true
end
if self.control then
ch = 'control-' .. ch
self.combo = true
-- even return numbers such as
-- control-seven
return ch
end
-- filter out characters that will be processed in
-- the subsequent char event
if ch and #ch > 1 and (code < 2 or code > 11) then
return ch
end
end
elseif event == 'key_up' then
if code == keys.leftCtrl or code == keys.rightCtrl then
self.control = false
elseif code == keys.leftShift or code == keys.rightShift then
self.shift = false
else
return
end
-- only send through the shift / control event if it wasn't
-- used in combination with another event
if not self.combo then
return keys.getName(code)
end
elseif event == 'char' then
if not self.control then
self.combo = true
return event
end
elseif event == 'mouse_click' then
local buttons = { 'mouse_click', 'mouse_rightclick', 'mouse_doubleclick' }
self.combo = true
if self.shift then
return 'shift-' .. buttons[code]
end
return buttons[code]
elseif event == "mouse_scroll" then
local directions = {
[ -1 ] = 'scrollUp',
[ 1 ] = 'scrollDown'
}
return directions[code]
elseif event == 'paste' then
self.combo = true
return event
elseif event == 'mouse_drag' then
return event
if self.pressed[keys.leftShift] or self.pressed[keys.rightShift] then
if code and modifiers[code] then
table.insert(result, 'shift')
elseif #ch == 1 then
table.insert(result, ch:upper())
else
table.insert(result, 'shift')
table.insert(result, ch)
end
elseif not code or not modifiers[code] then
table.insert(result, ch)
end
return table.concat(result, '-')
end
function input:reset()
self.pressed = { }
self.fired = nil
self.timer = nil
self.mch = nil
self.mfired = nil
end
function input:translate(event, code, p1, p2)
if event == 'key' then
if p1 then -- key is held down
if not modifiers[code] then
self.fired = true
return input:toCode(keys.getName(code), code)
end
else
self.pressed[code] = true
if self:modifierPressed() and not modifiers[code] or code == 57 then
self.fired = true
return input:toCode(keys.getName(code), code)
else
self.fired = false
end
end
elseif event == 'char' then
if not self:modifierPressed() then
self.fired = true
return input:toCode(code)
end
elseif event == 'key_up' then
if not self.fired then
if self.pressed[code] then
self.fired = true
local ch = input:toCode(keys.getName(code), code)
self.pressed[code] = nil
return ch
end
end
self.pressed[code] = nil
elseif event == 'paste' then
self.pressed[keys.leftCtrl] = nil
self.pressed[keys.rightCtrl] = nil
self.fired = true
if clipboard then
return 'paste'
end
return input:toCode('paste', 255)
elseif event == 'mouse_click' then
local buttons = { 'mouse_click', 'mouse_rightclick' }
self.mch = buttons[code]
self.mfired = nil
elseif event == 'mouse_drag' then
self.mfired = true
self.fired = true
return input:toCode('mouse_drag', 255)
elseif event == 'mouse_up' then
if not self.mfired then
local clock = os.clock()
if self.timer and
p1 == self.x and p2 == self.y and
(clock - self.timer < .5) then
self.mch = 'mouse_doubleclick'
self.timer = nil
else
self.timer = os.clock()
self.x = p1
self.y = p2
end
self.mfired = input:toCode(self.mch, 255)
else
self.mch = 'mouse_up'
self.mfired = input:toCode(self.mch, 255)
end
self.fired = true
return self.mfired
elseif event == "mouse_scroll" then
local directions = {
[ -1 ] = 'scrollUp',
[ 1 ] = 'scrollDown'
}
self.fired = true
return input:toCode(directions[code], 255)
end
end
load(sPath)
term.setCursorBlink(true)
redraw()
while bRunning do
local sEvent, param, param2, param3 = os.pullEventRaw()
local action
if sEvent == 'terminate' then
action = 'exit'
elseif sEvent == "mouse_click" or sEvent == 'mouse_drag' then
elseif sEvent == 'multishell_focus' then -- opus only event
input:reset()
elseif sEvent == "mouse_click" or sEvent == 'mouse_drag' or sEvent == 'mouse_up' then
local ch = input:translate(sEvent, param, param2, param3)
if param3 < h or sEvent == 'mouse_drag' then
local ch = keyboard:translate(sEvent, param)
if ch then
action = keyMapping[ch]
param = param2 + scrollX
@@ -1231,9 +1252,14 @@ while bRunning do
end
end
else
local ch = keyboard:translate(sEvent, param)
local ch = input:translate(sEvent, param, param2)
if ch then
action = keyMapping[ch]
if #ch == 1 then
action = keyMapping.char
param = ch
else
action = keyMapping[ch]
end
end
end
@@ -1247,7 +1273,7 @@ while bRunning do
actions[action](param, param2)
if action ~= 'menu' then
keyboard.lastAction = action
lastAction = action
end
if x ~= lastPos.x or y ~= lastPos.y then

376
apps/levelEmitter.lua Normal file
View File

@@ -0,0 +1,376 @@
_G.requireInjector()
local InventoryAdapter = require('inventoryAdapter')
local Config = require('config')
local Event = require('event')
local itemDB = require('itemDB')
local UI = require('ui')
local Util = require('util')
local colors = _G.colors
local multishell = _ENV.multishell
local rs = _G.rs
local RESOURCE_FILE = 'usr/config/levelEmitter.db'
multishell.setTitle(multishell.getCurrent(), 'Level Emitter')
local config = {
inventorySide = 'bottom',
}
Config.loadWithCheck('levelEmitter', config)
local inventoryAdapter = InventoryAdapter.wrap({ wrapSide = config.inventorySide })
if not inventoryAdapter then
error('No inventory found')
end
local resources
local function getItem(items, inItem, ignoreDamage, ignoreNbtHash)
for _,item in pairs(items) do
if item.name == inItem.name and
(ignoreDamage or item.damage == inItem.damage) and
(ignoreNbtHash or item.nbtHash == inItem.nbtHash) then
return item
end
end
end
local function uniqueKey(item)
return table.concat({ item.name, item.damage, item.nbtHash }, ':')
end
local function mergeResources(t)
for _,v in pairs(resources) do
local item = getItem(t, v)
if item then
Util.merge(item, v)
else
item = Util.shallowCopy(v)
item.count = 0
table.insert(t, item)
end
end
for _,v in pairs(t) do
if not v.displayName then
v.displayName = itemDB:getName(v)
end
v.lname = v.displayName:lower()
end
end
local function getItemWithQty(items, res, ignoreDamage, ignoreNbtHash)
local item = getItem(items, res, ignoreDamage, ignoreNbtHash)
if item and (ignoreDamage or ignoreNbtHash) then
local count = 0
for _,v in pairs(items) do
if item.name == v.name and
(ignoreDamage or item.damage == v.damage) and
(ignoreNbtHash or item.nbtHash == v.nbtHash) then
count = count + v.count
end
end
item.count = count
end
return item
end
local function loadResources()
resources = Util.readTable(RESOURCE_FILE) or { }
for k,v in pairs(resources) do
Util.merge(v, itemDB:splitKey(k))
end
end
local function saveResources()
local t = { }
for k,v in pairs(resources) do
v = Util.shallowCopy(v)
local keys = Util.transpose({ 'limit', 'low', 'ignoreDamage', 'ignoreNbtHash' })
for _,key in pairs(Util.keys(v)) do
if not keys[key] then
v[key] = nil
end
end
if not Util.empty(v) then
t[k] = v
end
end
Util.writeTable(RESOURCE_FILE, t)
end
local itemPage = UI.Page {
titleBar = UI.TitleBar {
title = 'Limit Resource',
previousPage = true,
event = 'form_cancel',
},
form = UI.Form {
x = 1, y = 2, height = 10, ex = -1,
[1] = UI.TextEntry {
width = 7,
formLabel = 'Min', formKey = 'low', help = 'Output a signal if below'
},
[2] = UI.TextEntry {
width = 7,
formLabel = 'Max', formKey = 'limit', help = 'Output a signal if above'
},
[4] = UI.Chooser {
width = 7,
formLabel = 'Ignore Dmg', formKey = 'ignoreDamage',
nochoice = 'No',
choices = {
{ name = 'Yes', value = true },
{ name = 'No', value = false },
},
help = 'Ignore damage of item'
},
[5] = UI.Chooser {
width = 7,
formLabel = 'Ignore NBT', formKey = 'ignoreNbtHash',
nochoice = 'No',
choices = {
{ name = 'Yes', value = true },
{ name = 'No', value = false },
},
help = 'Ignore NBT of item'
},
},
statusBar = UI.StatusBar { }
}
function itemPage:enable(item)
self.item = Util.shallowCopy(item)
self.form:setValues(item)
self.titleBar.title = item.displayName or item.name
UI.Page.enable(self)
self:focusFirst()
end
function itemPage:eventHandler(event)
if event.type == 'form_cancel' then
UI:setPreviousPage()
elseif event.type == 'focus_change' then
self.statusBar:setStatus(event.focused.help)
self.statusBar:draw()
elseif event.type == 'form_complete' then
local filtered = Util.shallowCopy(self.form.values)
if filtered.ignoreDamage == true then
filtered.damage = 0
else
filtered.ignoreDamage = nil
end
if filtered.ignoreNbtHash == true then
filtered.nbtHash = nil
else
filtered.ignoreNbtHash = nil
end
local originalKey = uniqueKey(self.item)
resources[originalKey] = nil
filtered.low = tonumber(filtered.low)
filtered.limit = tonumber(filtered.limit)
if filtered.limit or filtered.low then
resources[uniqueKey(filtered)] = filtered
else
resources[uniqueKey(filtered)] = nil
end
saveResources()
UI:setPreviousPage()
else
return UI.Page.eventHandler(self, event)
end
return true
end
local listingPage = UI.Page {
menuBar = UI.MenuBar {
buttons = {
{ text = 'Forget', event = 'forget' },
{ text = 'Refresh', event = 'refresh', x = -9 },
},
},
grid = UI.Grid {
y = 2, height = UI.term.height - 2,
columns = {
{ heading = 'Name', key = 'displayName' , width = 22 },
{ heading = 'Qty', key = 'count' , width = 5 },
{ heading = 'Min', key = 'limit' , width = 4 },
{ heading = 'Max', key = 'low' , width = 4 },
},
sortColumn = 'displayName',
},
statusBar = UI.StatusBar {
filterText = UI.Text {
x = 2,
value = 'Filter',
},
filter = UI.TextEntry {
x = 9, ex = -5,
limit = 50,
backgroundColor = colors.gray,
backgroundFocusColor = colors.gray,
},
display = UI.Button {
x = -3,
event = 'toggle_display',
value = 0,
text = 'A',
},
},
accelerators = {
r = 'refresh',
q = 'quit',
},
displayMode = 0,
}
function listingPage.grid:getDisplayValues(row)
row = Util.shallowCopy(row)
row.count = Util.toBytes(row.count)
if row.low then
row.low = Util.toBytes(row.low)
end
if row.limit then
row.limit = Util.toBytes(row.limit)
end
return row
end
function listingPage:eventHandler(event)
if event.type == 'quit' then
UI:exitPullEvents()
elseif event.type == 'grid_select' then
local selected = event.selected
UI:setPage('item', selected)
elseif event.type == 'refresh' then
self:refresh()
self.grid:draw()
self.statusBar.filter:focus()
elseif event.type == 'toggle_display' then
local values = {
[0] = 'A',
[1] = 'I',
[2] = 'C',
}
event.button.value = (event.button.value + 1) % 3
self.displayMode = event.button.value
event.button.text = values[event.button.value]
event.button:draw()
self:applyFilter()
self.grid:draw()
elseif event.type == 'forget' then
local item = self.grid:getSelected()
if item then
local key = uniqueKey(item)
if resources[key] then
resources[key] = nil
saveResources()
end
self.statusBar:timedStatus('Forgot: ' .. item.name, 3)
self:refresh()
self.grid:draw()
end
elseif event.type == 'text_change' then
self.filter = event.text
if #self.filter == 0 then
self.filter = nil
end
self:applyFilter()
self.grid:draw()
self.statusBar.filter:focus()
else
UI.Page.eventHandler(self, event)
end
return true
end
function listingPage:enable()
self:refresh()
self:setFocus(self.statusBar.filter)
UI.Page.enable(self)
end
function listingPage:refresh()
self.allItems = inventoryAdapter:listItems()
mergeResources(self.allItems)
self:applyFilter()
end
function listingPage:applyFilter()
local filter = self.filter
local displayMode = self.displayMode
local t = self.allItems
if filter or displayMode > 0 then
t = { }
if filter then
filter = filter:lower()
end
for _,v in pairs(self.allItems) do
if not filter or string.find(v.lname, filter, 1, true) then
if not displayMode or
displayMode == 0 or
displayMode == 1 and v.count > 0 or
displayMode == 2 and v.has_recipe then
table.insert(t, v)
end
end
end
end
self.grid:setValues(t)
end
loadResources()
UI:setPages({
listing = listingPage,
item = itemPage,
})
UI:setPage(listingPage)
listingPage:setFocus(listingPage.statusBar.filter)
Event.onInterval(5, function()
local items = inventoryAdapter:listItems()
if items and Util.size(items) > 0 then
for _,res in pairs(resources) do
local item = getItemWithQty(items, res, res.ignoreDamage, res.ignoreNbtHash)
rs.setOutput('bottom', (res.limit and
item and item.count > res.limit) or
(res.low and
(not item or item.count < res.low)) or false)
end
end
end)
UI:pullEvents()

View File

@@ -36,6 +36,31 @@ elseif device.monitor then
})
end
--[[-- ScrollingText --]]--
UI.ScrollingText = class(UI.Window)
UI.ScrollingText.defaults = {
UIElement = 'ScrollingText',
backgroundColor = colors.black,
buffer = { },
}
function UI.ScrollingText:appendLine(text)
if #self.buffer+1 >= self.height then
table.remove(self.buffer, 1)
end
table.insert(self.buffer, text)
end
function UI.ScrollingText:clear()
self.buffer = { }
UI.Window.clear(self)
end
function UI.ScrollingText:draw()
for k,text in ipairs(self.buffer) do
self:write(1, k, Util.widthify(text, self.width), self.backgroundColor)
end
end
terminal:clear()
function getClient(id)

View File

@@ -1,9 +1,12 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Terminal = require('terminal')
local shell = _ENV.shell
local term = _G.term
local args = { ... }
local mon = device[table.remove(args, 1) or 'monitor']
local mon = _G.device[table.remove(args, 1) or 'monitor']
if not mon then
error('mirror: Invalid device')
end

View File

@@ -1,11 +1,13 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Event = require('event')
local Logger = require('logger')
local Socket = require('socket')
local Terminal = require('terminal')
local Util = require('util')
local multishell = _ENV.multishell
local os = _G.os
Logger.setScreenLogging()
local remoteId
@@ -14,7 +16,7 @@ if #args == 1 then
remoteId = tonumber(args[1])
else
print('Enter host ID')
remoteId = tonumber(read())
remoteId = tonumber(_G.read())
end
if not remoteId then
@@ -70,7 +72,7 @@ while true do
while true do
local e = Event.pullEvent()
if e[1] == 'terminate' then
break
break
end
if not socket.connected then
break

View File

@@ -1,15 +1,18 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Event = require('event')
local Logger = require('logger')
local Socket = require('socket')
local colors = _G.colors
local term = _G.term
Logger.setScreenLogging()
local mon = term.current()
local args = { ... }
if args[1] then
mon = device[args[1]]
mon = _G.device[args[1]]
end
if not mon then
@@ -36,13 +39,6 @@ while true do
end
end)
-- ensure socket is connected
Event.onInterval(3, function(h)
if not socket:ping() then
Event.off(h)
end
end)
while true do
Event.pullEvent()
if not socket.connected then

View File

@@ -1,23 +1,27 @@
require = requireInjector(getfenv(1))
_G.requireInjector()
local Event = require('event')
local UI = require('ui')
local colors = _G.colors
local device = _G.device
local turtle = _G.turtle
local multishell = _ENV.multishell
multishell.setTitle(multishell.getCurrent(), 'Music')
if not turtle then
error('This program can only be run on a turtle')
end
local radio = device.drive or error('No drive attached')
if radio.side ~= 'top' and radio.side ~= 'bottom' then
error('Disk drive must be above or below turtle')
end
if not turtle then
error('This program can only be run on a turtle')
end
UI:configure('Music', ...)
local monitor = UI.term
UI.Button.defaults.backgroundFocusColor = colors.gray
local page = UI.Page({
@@ -146,12 +150,12 @@ function page:eventHandler(event)
end
end
function page:setVolume(volume, displayOnly)
function page:setVolume(volume)
volume = math.min(volume, 15)
volume = math.max(volume, 1)
self.volume = volume
volume = math.ceil(volume / 2)
for i = 1, volume do
self.volumeControls[i].backgroundColor =
self.volumeControls[i].color
@@ -224,7 +228,7 @@ end
function page:updateStationName()
local title = radio.getAudioTitle()
if title then
self.stationName.value = title
self.stationName:draw()
@@ -248,9 +252,9 @@ page:setVolume(page.volume, true)
UI:setPage(page)
turtle.status = 'Jamming'
turtle.setStatus('Jamming')
UI:pullEvents()
turtle.status = 'idle'
turtle.setStatus('idle')
page:play(false)
UI.term:reset()

View File

@@ -1,9 +1,17 @@
local injector = requireInjector or load(http.get('https://raw.githubusercontent.com/kepler155c/opus/master/sys/apis/injector.lua').readAll())()
injector(getfenv(1))
local injector = _G.requireInjector or load(http.get('https://raw.githubusercontent.com/kepler155c/opus/develop/sys/apis/injector.lua').readAll())()
injector()
local Canvas = require('ui.canvas')
local Util = require('util')
local colors = _G.colors
local os = _G.os
local peripheral = _G.peripheral
local printError = _G.printError
local shell = _ENV.shell
local term = _G.term
local window = _G.window
local function syntax()
printError('Syntax:')
error('mwm sessionName [monitor]')
@@ -14,11 +22,11 @@ local UID = 0
local multishell = { }
local processes = { }
local parentTerm = term.current()
local sessionFile = args[1] or syntax()
local sessionFile = args[1] or 'usr/config/mwm'
local running
local monitor
local defaultEnv = Util.shallowCopy(getfenv(1))
local defaultEnv = Util.shallowCopy(_ENV)
defaultEnv.multishell = multishell
if args[2] then
@@ -55,7 +63,7 @@ end
local function getProcessAt(x, y)
for k = #processes, 1, -1 do
local process = processes[k]
if x >= process.x and
if x >= process.x and
y >= process.y and
x <= process.x + process.width - 1 and
y <= process.y + process.height - 1 then
@@ -356,7 +364,7 @@ function multishell.removeProcess(process)
redraw()
end
function multishell.saveSession(sessionFile)
function multishell.saveSession(filename)
local t = { }
for _,process in pairs(processes) do
if process.path and not process.isShell then
@@ -370,11 +378,11 @@ function multishell.saveSession(sessionFile)
})
end
end
Util.writeTable(sessionFile, t)
Util.writeTable(filename, t)
end
function multishell.loadSession(sessionFile)
local config = Util.readTable(sessionFile)
function multishell.loadSession(filename)
local config = Util.readTable(filename)
if config then
for _,v in pairs(config) do
multishell.openTab(v)

View File

@@ -1,12 +1,17 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Event = require('event')
local GPS = require('gps')
local ChestAdapter = require('chestAdapter18')
local Point = require('point')
local Socket = require('socket')
local Util = require('util')
local device = _G.device
local os = _G.os
local peripheral = _G.peripheral
local printError = _G.printError
local turtle = _G.turtle
if not device.wireless_modem then
error('Modem is required')
end
@@ -35,7 +40,7 @@ local fuel = {
local slots
turtle.setMoveCallback(function(action, pt)
turtle.setMoveCallback(function()
if slots then
for _,slot in pairs(slots) do
if turtle.getItemCount(slot.index) ~= slot.qty then
@@ -46,10 +51,38 @@ turtle.setMoveCallback(function(action, pt)
end
end)
function refuel()
local function gotoPoint(pt, doDetect)
slots = turtle.getInventory()
while not turtle.pathfind(pt, { blocks = blocks }) do
if turtle.isAborted() then
error('aborted')
end
turtle.setStatus('blocked')
os.sleep(5)
end
if doDetect and not turtle.detectDown() then
printError('Missing target')
Event.exitPullEvents()
end
end
local function dropOff(pt)
if turtle.selectSlotWithItems() then
gotoPoint(pt, true)
turtle.emptyInventory(turtle.dropDown)
if pt == locations.dropPt then
print('refreshing items')
local chestAdapter = ChestAdapter()
items = chestAdapter:refresh()
end
end
end
local function refuel()
if turtle.getFuelLevel() < 5000 and locations.dropPt then
print('refueling')
turtle.status = 'refueling'
turtle.setStatus('refueling')
gotoPoint(locations.dropPt, true)
dropOff(locations.dropPt)
local chestAdapter = ChestAdapter({
@@ -66,8 +99,8 @@ function refuel()
end
end
function pickUp(pt)
turtle.status = 'picking up'
local function pickUp(pt)
turtle.setStatus('picking up')
gotoPoint(pt, true)
while true do
if not turtle.selectOpenSlot() then
@@ -81,41 +114,13 @@ function pickUp(pt)
end
end
function dropOff(pt)
if turtle.selectSlotWithItems() then
gotoPoint(pt, true)
turtle.emptyInventory(turtle.dropDown)
if pt == locations.dropPt then
print('refreshing items')
chestAdapter = ChestAdapter()
items = chestAdapter:refresh()
end
end
end
function gotoPoint(pt, doDetect)
slots = turtle.getInventory()
while not turtle.pathfind(pt, { blocks = blocks }) do
if turtle.abort then
error('aborted')
end
turtle.status = 'blocked'
os.sleep(5)
end
if doDetect and not turtle.detectDown() then
printError('Missing target')
Event.exitPullEvents()
end
end
function checkCell(pt)
local function checkCell(pt)
if not turtle.selectOpenSlot() then
dropOff(locations.dropPt)
end
print('checking cell')
turtle.status = 'recharging'
turtle.setStatus('recharging')
gotoPoint(pt, true)
local c = peripheral.wrap('bottom')
local energy = c.getMaxEnergyStored() -
@@ -136,9 +141,9 @@ function checkCell(pt)
end
end
function fluid(points)
local function fluid(points)
print('checking fluid')
turtle.status = 'fluiding'
turtle.setStatus('fluiding')
gotoPoint(points.source, true)
turtle.select(1)
turtle.digDown()
@@ -152,10 +157,10 @@ function fluid(points)
turtle.placeDown()
end
function refill(entry)
local function refill(entry)
dropOff(locations.dropPt)
turtle.status = 'refilling'
turtle.setStatus('refilling')
gotoPoint(locations.dropPt)
local chestAdapter = ChestAdapter()
for _,item in pairs(entry.items) do
@@ -169,21 +174,6 @@ function refill(entry)
end
end
function oldRefill(points)
gotoPoint(points.source)
repeat until not turtle.suckDown(64)
if points.target then
dropOff(points.target)
end
if points.targets then
for k,target in pairs(points.targets) do
dropOff(target)
end
end
dropOff(points.source)
dropOff(locations.dropPt)
end
local function makeKey(pt)
return string.format('%d:%d:%d', pt.x, pt.y, pt.z)
end
@@ -198,7 +188,7 @@ local function pickupHost(socket)
end
print('command: ' .. data.type)
if data.type == 'pickup' then
local key = makeKey(data.point)
locations.pickups[key] = data.point
@@ -207,7 +197,7 @@ local function pickupHost(socket)
elseif data.type == 'items' then
socket:write( { type = "response", response = items })
elseif data.type == 'refill' then
local key = makeKey(data.entry.point)
locations.refills[key] = data.entry
@@ -223,14 +213,12 @@ local function pickupHost(socket)
locations.chargePt = data.point
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'Location set' })
elseif data.type == 'charge' then
local key = makeKey(data.point)
locations.cells[key] = data.point
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'added' })
elseif data.type == 'fluid' then
elseif data.type == 'clear' then
local key = makeKey(data.point)
@@ -240,7 +228,7 @@ local function pickupHost(socket)
locations.pickups[key] = nil
Util.writeTable('/usr/config/pickup', locations)
socket:write( { type = "response", response = 'cleared' })
else
print('unknown command')
@@ -264,7 +252,7 @@ local function eachEntry(t, fn)
local keys = Util.keys(t)
for _,key in pairs(keys) do
if t[key] then
if turtle.abort then
if turtle.isAborted() then
return
end
fn(t[key])
@@ -283,7 +271,7 @@ local function eachClosestEntry(t, fn)
while not Util.empty(points) do
local closest = Point.closest(turtle.point, points)
if turtle.abort then
if turtle.isAborted() then
return
end
if t[closest.key] then
@@ -299,7 +287,6 @@ local function eachClosestEntry(t, fn)
end
Event.addRoutine(function()
if not turtle.enableGPS() then
error('turtle: No GPS found')
end
@@ -318,8 +305,8 @@ Event.addRoutine(function()
eachEntry(locations.cells, checkCell)
end
print('sleeping')
turtle.status = 'sleeping'
if turtle.abort then
turtle.setStatus('sleeping')
if turtle.isAborted() then
printError('aborted')
break
end

View File

@@ -83,7 +83,10 @@ local function loadAPI(url, env)
apiEnv.shell = nil
apiEnv.multishell = nil
setmetatable(apiEnv, { __index = _G })
local fn = Util.loadUrl(url, apiEnv)
local fn, m = Util.loadUrl(url, apiEnv)
if not fn then
error(m)
end
fn()
return apiEnv
end
@@ -91,7 +94,10 @@ end
bbpack = loadAPI('http://pastebin.com/raw/PdrJjb5S', getfenv(1))
GIF = loadAPI('http://pastebin.com/raw/5uk9uRjC', getfenv(1))
Util.runUrl(getfenv(1), 'http://pastebin.com/raw/cUYTGbpb', 'get', 'CnLzL5fg')
local s, m = Util.runUrl(getfenv(1), 'http://pastebin.com/raw/cUYTGbpb', 'get', 'CnLzL5fg')
if not s then
error(m)
end
-- 'Y0eLUPtr')
-- CnLzL5fg
local function snooze()
@@ -141,7 +147,7 @@ end
local tabId = multishell.getCurrent()
multishell.addHotkey(25, function()
multishell.addHotkey('control-p', function()
os.queueEvent('recorder_stop')
end)
@@ -179,7 +185,7 @@ while true do
end
end
multishell.removeHotkey(25)
multishell.removeHotkey('control-p')
for k,fn in pairs(oldTerm) do
multishell.term[k] = fn

View File

@@ -1,283 +1,47 @@
requireInjector(getfenv(1))
_G.requireInjector()
local GPS = require('gps')
local Socket = require('socket')
local UI = require('ui')
local Util = require('util')
local multishell = _ENV.multishell
local textutils = _G.textutils
multishell.setTitle(multishell.getCurrent(), 'Shapes')
local args = { ... }
local turtleId = args[1] or error('Supply turtle ID')
turtleId = tonumber(turtleId)
local script = [[
requireInjector(getfenv(1))
local GPS = require('gps')
local ChestAdapter = require('chestAdapter18')
local Point = require('point')
local Util = require('util')
local itemAdapter
function dumpInventory()
for i = 1, 16 do
local qty = turtle.getItemCount(i)
if qty > 0 then
itemAdapter:insert(i, qty)
end
if turtle.getItemCount(i) ~= 0 then
print('Adapter is full or missing - make space or replace')
print('Press enter to continue')
read()
end
end
turtle.select(1)
end
local function refuel()
while turtle.getFuelLevel() < 4000 do
print('Refueling')
turtle.select(1)
itemAdapter:provide({ name = 'minecraft:coal', damage = 0 }, 64, 1)
if turtle.getItemCount(1) == 0 then
print('Out of fuel, add fuel to chest/ME system')
turtle.status = 'waiting'
os.sleep(5)
else
turtle.refuel(64)
end
end
end
local function goto(pt)
while not turtle.gotoPoint(pt) do
print('stuck')
os.sleep(5)
end
end
local function pathTo(pt)
while not turtle.pathfind(pt) do
print('stuck')
os.sleep(5)
end
end
local function resupply()
if data.suppliesPt then
pathTo(data.suppliesPt)
itemAdapter = ChestAdapter({ direction = 'up', wrapSide = 'bottom' })
dumpInventory()
refuel()
end
end
local function makePlane(y)
local pt = { x = math.min(data.startPt.x, data.endPt.x),
ex = math.max(data.startPt.x, data.endPt.x),
z = math.min(data.startPt.z, data.endPt.z),
ez = math.max(data.startPt.z, data.endPt.z) }
local blocks = { }
for z = pt.z, pt.ez do
for x = pt.x, pt.ex do
table.insert(blocks, { x = x, y = y, z = z })
end
end
return blocks
end
local function optimizeRoute(plane, ptb)
local maxDistance = 99999999
local function getNearestNeighbor(p, pt, threshold)
local key, block, heading
local moves = maxDistance
local function getMoves(b, k)
local distance = math.abs(pt.x - b.x) + math.abs(pt.z - b.z)
if distance < moves then
-- this operation is expensive - only run if distance is close
local c, h = Point.calculateMoves(pt, b, distance)
if c < moves then
block = b
key = k
moves = c
heading = h
end
end
end
local function blockReady(b)
return not b.u
end
local mid = pt.index
local forward = mid + 1
local backward = mid - 1
while forward <= #p or backward > 0 do
if forward <= #p then
local b = p[forward]
if blockReady(b) then
getMoves(b, forward)
if moves <= threshold then
break
end
if moves < maxDistance and math.abs(b.z - pt.z) > moves and pt.index > 0 then
forward = #p
end
end
forward = forward + 1
end
if backward > 0 then
local b = p[backward]
if blockReady(b) then
getMoves(b, backward)
if moves <= threshold then
break
end
if moves < maxDistance and math.abs(pt.z - b.z) > moves then
backward = 0
end
end
backward = backward - 1
end
end
pt.x = block.x
pt.z = block.z
pt.y = block.y
pt.heading = heading
pt.index = key
block.u = true
return block
end
local throttle = Util.throttle()
local t = { }
ptb.index = 0
local threshold = 0
for i = 1, #plane do
local b = getNearestNeighbor(plane, ptb, threshold)
table.insert(t, b)
throttle()
threshold = 1
end
return t
end
local function clear()
local pt = Util.shallowCopy(data.startPt)
pt.y = math.min(data.startPt.y, data.endPt.y)
pt.heading = 0
local osy = pt.y
local sy = osy + 1
local ey = math.max(data.startPt.y, data.endPt.y)
local firstPlane = true
resupply()
while true do
if sy > ey then
sy = ey
end
local plane = makePlane(sy)
plane = optimizeRoute(plane, pt)
if firstPlane then
turtle.pathfind(plane[1])
turtle.setPolicy(turtle.policies.digAttack)
firstPlane = false
end
for _,b in ipairs(plane) do
turtle.gotoPoint(b)
if sy < ey then
turtle.digUp()
end
if sy > osy then
turtle.digDown()
end
if turtle.abort then
break
end
end
if turtle.abort then
break
end
if sy + 1 >= ey then
break
end
sy = sy + 3
end
turtle.setPolicy(turtle.policies.none)
resupply()
end
turtle.run(function()
turtle.status = 'Clearing'
if turtle.enableGPS() then
local pt = Util.shallowCopy(turtle.point)
local s, m = pcall(clear)
pathTo(pt)
if not s and m then
error(m)
read()
end
end
end)
]]
local levelScript = [[
requireInjector(getfenv(1))
requireInjector(getfenv(1))
local Util = require('util')
local Level = require('turtle.level')
local Util = require('util')
local s, m = turtle.run(function()
turtle.addFeatures('level')
turtle.setStatus('Leveling')
local s, m = turtle.run(function()
turtle.status = 'Leveling'
if turtle.enableGPS() then
local pt = Util.shallowCopy(turtle.point)
local s, m = pcall(function()
turtle.level(data.startPt, data.endPt, data.firstPt)
end)
if turtle.enableGPS() then
turtle.pathfind(pt)
local pt = Util.shallowCopy(turtle.point)
local s, m = pcall(function()
Level(data.startPt, data.endPt, data.firstPt)
end)
turtle.pathfind(pt)
if not s and m then
error(m)
if not s and m then
error(m)
end
end
end)
if not s then
error(m)
end
end)
if not s then
error(m)
end
]]
local data = Util.readTable('/usr/config/shapes') or { }
local page = UI.Page {
@@ -295,7 +59,6 @@ local page = UI.Page {
}
function page.info:draw()
local function size(a, b)
return (math.abs(a.x - b.x) + 1) *
(math.abs(a.y - b.y) + 1) *
@@ -321,13 +84,12 @@ function page:getPoint()
end
function page:runFunction(id, script)
--Util.writeFile('script.tmp', script)
self.notification:info('Connecting')
local fn, msg = loadstring(script, 'script')
if not fn then
self.notification:error('Error in script')
-- debug(msg)
--debug(msg)
return
end
@@ -379,7 +141,7 @@ function page:eventHandler(event)
end
self.statusBar:setStatus('')
elseif event.type == 'cancel' then
self:runFunction(turtleId, 'turtle.abortAction()')
self:runFunction(turtleId, 'turtle.abort(true)')
self.statusBar:setStatus('')
else
return UI.Page.eventHandler(self, event)
@@ -388,6 +150,4 @@ function page:eventHandler(event)
end
UI:setPage(page)
UI:pullEvents()
UI.term:reset()

View File

@@ -1,13 +1,13 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Logger = require('logger')
local Pathing = require('turtle.pathfind')
local Point = require('point')
local Util = require('util')
if device and device.wireless_modem then
Logger.setWirelessLogging()
end
local fs = _G.fs
local read = _G.read
local os = _G.os
local turtle = _G.turtle
local args = { ... }
local options = {
@@ -37,25 +37,20 @@ local fortuneBlocks = {
local MIN_FUEL = 7500
local LOW_FUEL = 1500
local MAX_FUEL = 100000
local MAX_FUEL = turtle.getFuelLimit()
local PROGRESS_FILE = 'usr/config/mining.progress'
local TRASH_FILE = 'usr/config/mining.trash'
if not term.isColor() then
MAX_FUEL = 20000
end
local mining = {
diameter = 1,
chunkIndex = 0,
chunks = -1,
}
local trash
local boreDirection
local trash, boreDirection, unload
function getChunkCoordinates(diameter, index, x, z)
local function getChunkCoordinates(diameter, index, x, z)
local dirs = { -- circumference of grid
{ xd = 0, zd = 1, heading = 1 }, -- south
{ xd = -1, zd = 0, heading = 2 },
@@ -68,13 +63,13 @@ function getChunkCoordinates(diameter, index, x, z)
dirs[4].z = z
return dirs[4]
end
dir = dirs[math.floor(index / (diameter - 1)) + 1]
local dir = dirs[math.floor(index / (diameter - 1)) + 1]
dir.x = x + dir.xd * 16
dir.z = z + dir.zd * 16
return dir
end
function getBoreLocations(x, z)
local function getBoreLocations(x, z)
local locations = {}
@@ -116,7 +111,7 @@ function getBoreLocations(x, z)
end
-- get the bore location closest to the miner
local function getClosestLocation(points, b)
local function getClosestLocation(points)
local key = 1
local leastMoves = 9000
for k,pt in pairs(points) do
@@ -124,21 +119,21 @@ local function getClosestLocation(points, b)
local moves = Point.calculateMoves(turtle.point, pt)
if moves < leastMoves then
key = k
key = k
leastMoves = moves
if leastMoves == 0 then
break
end
end
end
end
end
end
return table.remove(points, key)
end
end
function getCornerOf(c)
local function getCornerOf(c)
return math.floor(c.x / 16) * 16, math.floor(c.z / 16) * 16
end
function nextChunk()
local function nextChunk()
local x, z = getCornerOf({ x = mining.x, z = mining.z })
local points = math.pow(mining.diameter, 2) - math.pow(mining.diameter-2, 2)
@@ -168,15 +163,15 @@ function nextChunk()
return true
end
function addTrash()
local function addTrash()
if not trash then
trash = { }
end
local slots = turtle.getFilledSlots()
for k,slot in pairs(slots) do
for _,slot in pairs(slots) do
trash[slot.iddmg] = true
end
@@ -184,19 +179,18 @@ function addTrash()
Util.writeTable(TRASH_FILE, trash)
end
function log(text)
local function log(text)
print(text)
Logger.log('mineWorker', text)
end
function status(status)
turtle.status = status
log(status)
local function status(newStatus)
turtle.setStatus(newStatus)
log(newStatus)
end
function refuel()
local function refuel()
if turtle.getFuelLevel() < MIN_FUEL then
local oldStatus = turtle.status
local oldStatus = turtle.getStatus()
status('refueling')
if turtle.select('minecraft:coal:0') then
@@ -220,54 +214,37 @@ function refuel()
turtle.select(1)
end
function enderChestUnload()
log('unloading')
turtle.select(1)
if not Util.tryTimed(5, function()
turtle.digDown()
return turtle.placeDown()
end) then
log('placedown failed')
else
turtle.reconcileInventory(slots, turtle.dropDown)
turtle.select(1)
turtle.drop(64)
turtle.digDown()
end
end
function safeGoto(x, z, y, h)
local oldStatus = turtle.status
local function safeGoto(x, z, y, h)
local oldStatus = turtle.getStatus()
-- only pathfind above or around other turtles (never down)
Pathing.setBox({ x = 0, y = 0, z = 0, ex = x, ey = y + 1, ez = z })
Pathing.setBox({ x = turtle.point.x, y = turtle.point.y, z = turtle.point.z, ex = x, ey = y, ez = z })
while not turtle.pathfind({ x = x, z = z, y = y or turtle.point.y, heading = h }) do
--status('stuck')
if turtle.abort then
if turtle.isAborted() then
return false
end
--os.sleep(1)
os.sleep(3)
end
turtle.status = oldStatus
turtle.setStatus(oldStatus)
return true
end
function safeGotoY(y)
local oldStatus = turtle.status
local function safeGotoY(y)
local oldStatus = turtle.getStatus()
while not turtle.gotoY(y) do
status('stuck')
if turtle.abort then
if turtle.isAborted() then
return false
end
os.sleep(1)
end
turtle.status = oldStatus
turtle.setStatus(oldStatus)
return true
end
function makeWalkableTunnel(action, tpt, pt)
local function makeWalkableTunnel(action, tpt, pt)
if action ~= 'turn' and not Point.compare(tpt, { x = 0, z = 0 }) then -- not at source
if not Point.compare(tpt, pt) then -- not at dest
local r, block = turtle.inspectUp()
@@ -281,8 +258,27 @@ function makeWalkableTunnel(action, tpt, pt)
end
end
function normalChestUnload()
local oldStatus = turtle.status
--[[
local function enderChestUnload()
log('unloading')
turtle.select(1)
if not Util.tryTimed(5, function()
turtle.digDown()
return turtle.placeDown()
end) then
log('placedown failed')
else
turtle.reconcileInventory(slots, turtle.dropDown)
turtle.select(1)
turtle.drop(64)
turtle.digDown()
end
end
]]
local function normalChestUnload()
local oldStatus = turtle.getStatus()
status('unloading')
local pt = Util.shallowCopy(turtle.point)
safeGotoY(0)
@@ -291,13 +287,13 @@ function normalChestUnload()
makeWalkableTunnel(action, tpt, { x = pt.x, z = pt.z })
end)
safeGoto(0, 0)
safeGoto(0, 0, 0)
if not turtle.detectUp() then
error('no chest')
end
local slots = turtle.getFilledSlots()
for _,slot in pairs(slots) do
if not trash[slot.iddmg] and
if not trash[slot.iddmg] and
slot.iddmg ~= 'minecraft:bucket:0' and
slot.id ~= 'minecraft:diamond_pickaxe' and
slot.id ~= 'cctweaks:toolHost' then
@@ -317,7 +313,7 @@ function normalChestUnload()
status(oldStatus)
end
function ejectTrash()
local function ejectTrash()
local cobbleSlotCount = 0
@@ -325,7 +321,7 @@ function ejectTrash()
if slot.iddmg == 'minecraft:cobblestone:0' then
if cobbleSlotCount == 0 and slot.count > 36 then
turtle.select(slot.index)
turtle.dropDown(32)
turtle.dropDown(slot.count - 36)
end
cobbleSlotCount = cobbleSlotCount + 1
end
@@ -340,7 +336,35 @@ function ejectTrash()
end)
end
function mineable(action)
local function checkSpace()
if turtle.getItemCount(16) > 0 then
refuel()
local oldStatus = turtle.getStatus()
status('condensing')
ejectTrash()
turtle.condense()
local lastSlot = 16
if boreDirection == 'down' then
lastSlot = 15
end
if turtle.getItemCount(lastSlot) > 0 then
unload()
end
status(oldStatus)
turtle.select(1)
end
end
local function collectDrops(suckAction)
for _ = 1, 50 do
if not suckAction() then
break
end
checkSpace()
end
end
local function mineable(action)
local r, block = action.inspect()
if not r then
return false
@@ -375,12 +399,12 @@ function mineable(action)
return block.name
end
function fortuneDig(action, blockName)
local function fortuneDig(action, blockName)
if options.fortunePick.value and fortuneBlocks[blockName] then
turtle.select('cctweaks:toolHost')
turtle.equipRight()
turtle.select(options.fortunePick.value)
repeat until not turtle.dig()
repeat until not action.dig()
turtle.select('minecraft:diamond_pickaxe')
turtle.equipRight()
turtle.select(1)
@@ -388,7 +412,7 @@ function fortuneDig(action, blockName)
end
end
function mine(action)
local function mine(action)
local blockName = mineable(action)
if blockName then
checkSpace()
@@ -398,18 +422,18 @@ function mine(action)
end
end
end
function bore()
local function bore()
local loc = turtle.point
local level = loc.y
turtle.select(1)
status('boring down')
boreDirection = 'down'
while true do
if turtle.abort then
if turtle.isAborted() then
status('aborting')
return false
end
@@ -417,15 +441,11 @@ function bore()
break
end
if turtle.point.y < -2 then
-- turtle.setDigPolicy(turtle.digPolicies.turtleSafe)
end
mine(turtle.getAction('down'))
if not Util.tryTimed(3, turtle.down) then
break
end
if loc.y < level - 1 then
mine(turtle.getAction('forward'))
turtle.turnRight()
@@ -438,38 +458,34 @@ function bore()
turtle.turnRight()
mine(turtle.getAction('forward'))
turtle.turnRight()
mine(turtle.getAction('forward'))
turtle.turnLeft()
while true do
if turtle.abort then
if turtle.isAborted() then
status('aborting')
return false
end
if turtle.point.y > -2 then
-- turtle.setDigPolicy(turtle.digPolicies.turtleSafe)
end
while not Util.tryTimed(3, turtle.up) do
status('stuck')
end
if turtle.status == 'stuck' then
if turtle.getStatus() == 'stuck' then
status('boring up')
end
if loc.y >= level - 1 then
break
end
mine(turtle.getAction('forward'))
turtle.turnLeft()
mine(turtle.getAction('forward'))
end
if turtle.getFuelLevel() < LOW_FUEL then
refuel()
local veryMinFuel = Point.turtleDistance(turtle.point, { x = 0, y = 0, z = 0}) + 512
@@ -481,34 +497,6 @@ function bore()
return true
end
function checkSpace()
if turtle.getItemCount(16) > 0 then
refuel()
local oldStatus = turtle.status
status('condensing')
ejectTrash()
turtle.condense()
local lastSlot = 16
if boreDirection == 'down' then
lastSlot = 15
end
if turtle.getItemCount(lastSlot) > 0 then
unload()
end
status(oldStatus)
turtle.select(1)
end
end
function collectDrops(suckAction)
for i = 1, 50 do
if not suckAction() then
break
end
checkSpace()
end
end
function Point.compare(pta, ptb)
if pta.x == ptb.x and pta.z == ptb.z then
@@ -520,15 +508,15 @@ function Point.compare(pta, ptb)
return false
end
function inspect(action, name)
local function inspect(action, name)
local r, block = action.inspect()
if r and block.name == name then
return true
end
end
function boreCommand()
local pt = getClosestLocation(mining.locations, turtle.point)
local function boreCommand()
local pt = getClosestLocation(mining.locations)
turtle.setMoveCallback(function(action, tpt)
makeWalkableTunnel(action, tpt, pt)
@@ -566,6 +554,7 @@ if not Util.getOptions(options, args) then
return
end
-- TODO: this won't work - need to Util.merge file into mining
mining.depth = options.depth.value
mining.chunks = options.chunks.value
@@ -628,16 +617,14 @@ turtle.run(function()
turtle.reset()
turtle.setPolicy(turtle.policies.digAttack)
turtle.setDigPolicy(turtle.digPolicies.turtleSafe)
unload()
status('mining')
local s, m = pcall(function() main() end)
local s, m = pcall(main)
if not s and m then
printError(m)
_G.printError(m)
end
turtle.abort = false
turtle.abort(false)
safeGotoY(0)
safeGoto(0, 0, 0, 0)
unload()

View File

@@ -1,22 +1,16 @@
requireInjector(getfenv(1))
_G.requireInjector()
local ChestAdapter = require('chestAdapter18')
local Event = require('event')
local MEAdapter = require('meAdapter')
local RefinedAdapter = require('refinedAdapter')
local UI = require('ui')
local Util = require('util')
local InventoryAdapter = require('inventoryAdapter')
local Event = require('event')
local UI = require('ui')
local Util = require('util')
local storage = RefinedAdapter()
if not storage:isValid() then
storage = MEAdapter({ auto = true })
if not storage:isValid() then
storage = ChestAdapter()
end
end
local colors = _G.colors
local multishell = _ENV.multishell
if not storage:isValid() then
error('Not connected to a storage device')
local storage = InventoryAdapter.wrap()
if not storage then
error('Not connected to a valid inventory')
end
multishell.setTitle(multishell.getCurrent(), 'Storage Activity')
@@ -26,8 +20,9 @@ local changedPage = UI.Page {
grid = UI.Grid {
ey = -6,
columns = {
{ heading = 'Qty', key = 'count', width = 5 },
{ heading = 'Change', key = 'change', width = 6 },
{ heading = 'Qty', key = 'count', width = 5 },
{ heading = 'Change', key = 'change', width = 6 },
{ heading = 'Rate', key = 'rate', width = 6 },
{ heading = 'Name', key = 'displayName' },
},
sortColumn = 'displayName',
@@ -66,6 +61,7 @@ function changedPage.grid:getDisplayValues(row)
if row.change < 0 then
ind = ''
end
row.change = ind .. Util.toBytes(row.change)
row.count = Util.toBytes(row.count)
@@ -73,7 +69,6 @@ function changedPage.grid:getDisplayValues(row)
end
function changedPage:eventHandler(event)
if event.type == 'reset' then
self.lastItems = nil
self.grid:setValues({ })
@@ -102,22 +97,25 @@ end
function changedPage:refresh()
local t = storage:listItems()
if not t or Util.empty(t) then
self:clear()
self:centeredWrite(math.ceil(self.height/2), 'Communication failure')
self.grid:clear()
self.grid:centeredWrite(math.ceil(self.height/2), 'Communication failure')
return
end
for k,v in pairs(t) do
t[k] = Util.shallowCopy(v)
end
if not self.lastItems then
self.lastItems = t
self.timestamp = os.clock()
self.grid:setValues({ })
else
local changedItems = {}
self.elapsed = os.clock() - self.timestamp
local changedItems = { }
local found
for _,v in pairs(self.lastItems) do
found = false
for k2,v2 in pairs(t) do
@@ -141,24 +139,26 @@ function changedPage:refresh()
end
end
-- No items left
for k,v in pairs(t) do
for _,v in pairs(t) do
v.lastCount = 0
table.insert(changedItems, v)
end
for k,v in pairs(changedItems) do
for _,v in pairs(changedItems) do
v.change = v.count - v.lastCount
v.rate = Util.round(60 / self.elapsed * v.change, 1)
end
self.grid:setValues(changedItems)
end
self.grid:draw()
end
Event.onInterval(5, function()
changedPage:refresh()
changedPage:sync()
end)
UI:setPage(changedPage)
changedPage:draw()
UI:pullEvents()

View File

@@ -1,4 +1,4 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Event = require('event')
local Logger = require('logger')
@@ -8,6 +8,10 @@ local Point = require('point')
local TableDB = require('tableDB')
local Util = require('util')
local device = _G.device
local os = _G.os
local turtle = _G.turtle
--[[
A supplier turtle for the builder turtle. For larger builds, use
ender modems.
@@ -57,7 +61,7 @@ local maxStackDB = TableDB({
}
}
})
function maxStackDB:get(id, dmg)
return self.data[id .. ':' .. dmg] or 64
end
@@ -87,7 +91,7 @@ function Builder:dumpInventoryWithCheck()
print('Press enter to continue')
--turtle.setHeading(0)
self.ready = false
read()
_G.read()
end
self.ready = true
end
@@ -95,7 +99,7 @@ end
function Builder:autocraft(supplies)
local t = { }
for i,s in pairs(supplies) do
for _,s in pairs(supplies) do
local key = s.id .. ':' .. s.dmg
local item = t[key]
if not item then
@@ -108,7 +112,7 @@ function Builder:autocraft(supplies)
end
item.qty = item.qty + (s.need-s.qty)
end
Builder.itemProvider:craftItems(t)
end
@@ -133,9 +137,9 @@ function Builder:log(...)
end
function Builder:getSupplies()
Builder.itemProvider:refresh()
local t = { }
for _,s in ipairs(self.slots) do
if s.need > 0 then
@@ -171,7 +175,7 @@ function Builder:getSupplies()
Builder:log('Need %d %s', s.need - s.qty, name)
end
end
return t
end
@@ -179,11 +183,11 @@ local function moveTowardsX(dx)
local direction = dx - turtle.point.x
local move
if direction == 0 then
return false
end
if direction > 0 and turtle.point.heading == 0 or
direction < 0 and turtle.point.heading == 2 then
move = turtle.forward
@@ -202,7 +206,7 @@ local function moveTowardsZ(dz)
if direction == 0 then
return false
end
if direction > 0 and turtle.point.heading == 1 or
direction < 0 and turtle.point.heading == 3 then
move = turtle.forward
@@ -214,7 +218,6 @@ local function moveTowardsZ(dz)
end
function Builder:finish()
Builder.resupplying = true
Builder.ready = false
if turtle.gotoLocation('supplies') then
@@ -227,9 +230,8 @@ function Builder:finish()
end
function Builder:gotoBuilder()
if Builder.lastPoint then
turtle.status = 'tracking'
turtle.setStatus('tracking')
while true do
local pt = Point.copy(Builder.lastPoint)
pt.y = pt.y + 3
@@ -260,140 +262,137 @@ function Builder:gotoBuilder()
end
end
Message.addHandler('builder',
function(h, id, msg, distance)
if not id or id ~= __BUILDER_ID then
return
end
Message.addHandler('builder',
function(_, id, msg)
if not id or id ~= __BUILDER_ID then
return
end
if not Builder.resupplying then
local pt = msg.contents
pt.y = pt.y + 3
local pt = msg.contents
pt.y = pt.y + 3
turtle.status = 'supervising'
turtle.gotoYfirst(pt)
end
turtle.setStatus('supervising')
turtle.gotoYfirst(pt)
end
end)
Message.addHandler('supplyList',
function(h, id, msg, distance)
if not id or id ~= __BUILDER_ID then
return
end
Message.addHandler('supplyList',
function(_, id, msg)
if not id or id ~= __BUILDER_ID then
return
end
turtle.status = 'resupplying'
Builder.resupplying = true
Builder.slots = msg.contents.slots
Builder.slotUid = msg.contents.uid
turtle.setStatus('resupplying')
Builder.resupplying = true
Builder.slots = msg.contents.slots
Builder.slotUid = msg.contents.uid
Builder:log('Received supply list ' .. Builder.slotUid)
os.sleep(0)
if not turtle.gotoLocation('supplies') then
Builder:log('Failed to go to supply location')
self.ready = false
Event.exitPullEvents()
end
os.sleep(0)
if not turtle.gotoLocation('supplies') then
Builder:log('Failed to go to supply location')
Builder.ready = false
Event.exitPullEvents()
end
turtle.setHeading(1)
os.sleep(.2) -- random 'Computer is not connected' error...
Builder:dumpInventoryWithCheck()
Builder:refuel()
while true do
local supplies = Builder:getSupplies()
if #supplies == 0 then
break
end
Builder:autocraft(supplies)
turtle.status = 'waiting'
os.sleep(5)
end
Builder:log('Got all supplies')
os.sleep(0)
Builder:gotoBuilder()
Builder.resupplying = false
local supplies = Builder:getSupplies()
if #supplies == 0 then
break
end
Builder:autocraft(supplies)
turtle.setStatus('waiting')
os.sleep(5)
end
Builder:log('Got all supplies')
os.sleep(0)
Builder:gotoBuilder()
Builder.resupplying = false
end)
Message.addHandler('needSupplies',
function(h, id, msg, distance)
if not id or id ~= __BUILDER_ID then
return
end
Message.addHandler('needSupplies',
function(_, id, msg)
if not id or id ~= __BUILDER_ID then
return
end
if Builder.resupplying or msg.contents.uid ~= Builder.slotUid then
Builder:log('No supplies ready')
if Builder.resupplying or msg.contents.uid ~= Builder.slotUid then
Builder:log('No supplies ready')
Message.send(__BUILDER_ID, 'gotSupplies')
else
turtle.setStatus('supplying')
Builder:log('Supplying')
os.sleep(0)
Message.send(__BUILDER_ID, 'gotSupplies')
else
turtle.status = 'supplying'
Builder:log('Supplying')
os.sleep(0)
local pt = msg.contents.point
pt.y = turtle.getPoint().y
pt.heading = nil
if not turtle.gotoYfirst(pt) then -- location of builder
Builder.resupplying = true
Message.send(__BUILDER_ID, 'gotSupplies')
os.sleep(0)
if not turtle.gotoLocation('supplies') then
Builder:log('failed to go to supply location')
--self.ready = false
Event.exitPullEvents()
end
local pt = msg.contents.point
pt.y = turtle.getPoint().y
pt.heading = nil
if not turtle.gotoYfirst(pt) then -- location of builder
Builder.resupplying = true
Message.send(__BUILDER_ID, 'gotSupplies')
os.sleep(0)
if not turtle.gotoLocation('supplies') then
Builder:log('failed to go to supply location')
Event.exitPullEvents()
end
turtle.setHeading(1)
return
end
pt.y = pt.y - 2 -- location where builder should go for the chest to be above
return
end
pt.y = pt.y - 2 -- location where builder should go for the chest to be above
turtle.select(15)
turtle.placeDown()
os.sleep(.1) -- random computer not connected error
turtle.select(15)
turtle.placeDown()
os.sleep(.1) -- random computer not connected error
local p = ChestProvider({ direction = 'up', wrapSide = 'bottom' })
for i = 1, 16 do
p:insert(i, 64)
end
for i = 1, 16 do
p:insert(i, 64)
end
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true, point = pt })
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true, point = pt })
Message.waitForMessage('thanks', 5, __BUILDER_ID)
--os.sleep(0)
Message.waitForMessage('thanks', 5, __BUILDER_ID)
--os.sleep(0)
--p.condenseItems()
for i = 1, 16 do
p:extract(i, 64)
end
turtle.digDown()
turtle.status = 'waiting'
end
--p.condenseItems()
for i = 1, 16 do
p:extract(i, 64)
end
turtle.digDown()
turtle.setStatus('waiting')
end
end)
Message.addHandler('finished',
function(h, id)
if not id or id ~= __BUILDER_ID then
return
end
function(_, id)
if not id or id ~= __BUILDER_ID then
return
end
Builder:finish()
end)
Event.on('turtle_abort',
function()
turtle.abort = false
turtle.status = 'aborting'
turtle.abort(false)
turtle.setStatus('aborting')
Builder:finish()
end)
local function onTheWay() -- parallel routine
while true do
local e, side, _id, id, msg, distance = os.pullEvent('modem_message')
local _, _, _, id, msg, _ = os.pullEvent('modem_message')
if Builder.ready then
if id == __BUILDER_ID and msg and msg.type then
if msg.type == 'needSupplies' then
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true })
elseif msg.type == 'builder' then
Builder.lastPoint = msg.contents
end
if msg.type == 'needSupplies' then
Message.send(__BUILDER_ID, 'gotSupplies', { supplies = true })
elseif msg.type == 'builder' then
Builder.lastPoint = msg.contents
end
end
end
end

22
apps/termShare.lua Normal file
View File

@@ -0,0 +1,22 @@
local device = _G.device
local multishell = _ENV.multishell
local os = _G.os
local term = _G.term
-- list this terminal in the devices list so it's available via
-- peripheral sharing
local args = { ... }
local name = args[1] or error('Syntax: termShare [device name] <title>')
local title = args[2]
device[name] = term.current()
device[name].name = name
device[name].side = name
device[name].type = 'terminal'
if title then
multishell.setTitle(multishell.getCurrent(), title)
end
os.pullEvent('terminate')
os.queueEvent('peripheral_detach', name)

View File

@@ -1,4 +1,4 @@
requireInjector(getfenv(1))
_G.requireInjector()
--[[
Requirements:
@@ -6,7 +6,7 @@ requireInjector(getfenv(1))
Area around turtle must be flat and can only be dirt or grass
(10 blocks in each direction from turtle)
Turtle must have: crafting table, chest
Turtle must have a pick equipped on the left side
Turtle must have a pick equipped
Optional:
Add additional sapling types that can grow with a single sapling
@@ -20,12 +20,12 @@ requireInjector(getfenv(1))
place the turtle in the original position before restarting the program.
]]--
local ChestAdapter = require('chestAdapter18')
local Craft = require('turtle.craft')
local Level = require('turtle.level')
local Pathing = require('turtle.pathfind')
local Point = require('point')
local Util = require('util')
local Point = require('point')
local Util = require('util')
local os = _G.os
local read = _G.read
local turtle = _G.turtle
local FUEL_BASE = 0
local FUEL_DIRE = FUEL_BASE + 10
@@ -76,9 +76,6 @@ local state = Util.readTable('usr/config/treefarm') or {
}
local clock = os.clock()
local recipes = Util.readTable('usr/etc/recipes.db') or { }
Craft.setRecipes(recipes)
local function inspect(fn)
local s, item = fn()
@@ -121,28 +118,21 @@ local function safePlaceBlock(item)
end
local function craftItem(item, qty)
local success
local success, msg
if safePlaceBlock(CHEST) then
if turtle.equip('left', 'minecraft:crafting_table') then
local chestAdapter = ChestAdapter({
Util.print('Crafting %d %s', (qty or 1), item)
success, msg = turtle.craftItem(item, qty or 1, {
wrapSide = 'top',
direction = 'down',
})
if not chestAdapter:isValid() then
print('invalid chestAdapter')
read()
end
repeat until not turtle.suckUp()
Util.print('Crafting %d %s', (qty or 1), item)
success = Craft.craftRecipe(recipes[item], qty or 1, chestAdapter)
repeat until not turtle.suckUp()
if not success then
print(msg)
end
turtle.equip('left', 'minecraft:diamond_pickaxe')
turtle.digUp()
end
@@ -175,7 +165,7 @@ local function makeSingleCharcoal()
local slots = turtle.getSummedInventory()
if not state.furnace or
if not state.furnace or
slots[CHARCOAL] or
not slots[OAK_LOG] or
slots[OAK_LOG].count < 2 then
@@ -195,13 +185,13 @@ local function makeCharcoal()
local slots = turtle.getSummedInventory()
if not state.furnace or
if not state.furnace or
not slots[CHARCOAL] or
slots[CHARCOAL].count >= MIN_CHARCOAL then
return true
end
local function getLogSlot(slots)
local function getLogSlot()
local maxslot = { count = 0 }
for k,slot in pairs(slots) do
if string.match(k, 'minecraft:log') then
@@ -214,7 +204,8 @@ local function makeCharcoal()
end
repeat
local slots = turtle.getSummedInventory()
slots = turtle.getSummedInventory()
local charcoal = slots[CHARCOAL].count
local slot = getLogSlot(slots)
@@ -266,7 +257,7 @@ local function getCobblestone(count)
turtle.select(1)
turtle.digDown()
turtle.down()
for i = 1, 4 do
for _ = 1, 4 do
if inspect(turtle.inspect) == STONE then
turtle.dig()
end
@@ -281,7 +272,7 @@ local function getCobblestone(count)
until turtle.getItemCount(COBBLESTONE) >= count
turtle.gotoPoint(pt)
turtle._goto(pt)
turtle.placeDown(DIRT)
turtle.drop(DIRT)
@@ -297,8 +288,8 @@ local function createFurnace()
print('Adding a furnace')
getCobblestone(8)
if craftItem(FURNACE) then
turtle.drop(COBBLESTONE)
if turtle.has(FURNACE) or craftItem(FURNACE) then
-- turtle.drop(COBBLESTONE)
local furnacePt = { x = GRID.BL.x + 2, y = 1, z = GRID.BL.z + 2 }
turtle.placeAt(furnacePt, FURNACE)
setState('furnace', furnacePt)
@@ -319,7 +310,9 @@ local function createPerimeter()
print('Creating a perimeter')
getCobblestone(GRID_WIDTH * 2 + 1)
cook(COBBLESTONE, 2, STONE, OAK_PLANK, 2)
if not turtle.has(STONE, 2) then
cook(COBBLESTONE, 2, STONE, OAK_PLANK, 2)
end
turtle.refuel(OAK_PLANK)
turtle.pathfind(GRID.BL)
@@ -350,35 +343,32 @@ local function createPerimeter()
end
local function createChests()
if state.chest_1 then
if state.chest then
return
end
if state.perimeter and
turtle.getFuelLevel() > FUEL_GOOD and
Craft.canCraft(CHEST, 4, turtle.getSummedInventory()) then
turtle.canCraft(CHEST, 4, turtle.getSummedInventory()) then
print('Adding storage')
if craftItem(CHEST, 4) then
if turtle.has(CHEST, 2) or craftItem(CHEST, 2) then
local pt = Point.copy(GRID.BL)
pt.x = pt.x + 1
pt.y = pt.y - 1
for i = 1, 2 do
pt.z = pt.z + 1
pt.z = pt.z + 1
turtle.digDownAt(pt)
turtle.placeDown(CHEST)
turtle.digDownAt(pt)
turtle.placeDown(CHEST)
pt.z = pt.z + 1
pt.z = pt.z + 1
turtle.digDownAt(pt)
turtle.placeDown(CHEST)
turtle.digDownAt(pt)
turtle.placeDown(CHEST)
setState('chest_' .. i, Util.shallowCopy(pt))
setState('chest', Util.shallowCopy(pt))
pt.z = pt.z + 1
end
turtle.drop(DIRT)
turtle.refuel(OAK_PLANK)
end
@@ -388,24 +378,27 @@ end
local function dropOffItems()
if state.chest_1 then
if state.chest then
local slots = turtle.getSummedInventory()
if state.chest_1 and
slots[CHARCOAL] and
slots[CHARCOAL].count >= MIN_CHARCOAL and
if state.chest and
slots[CHARCOAL] and
slots[CHARCOAL].count >= MIN_CHARCOAL and
(turtle.getItemCount('minecraft:log') > 0 or
turtle.getItemCount('minecraft:log2') > 0) then
print('Storing logs')
turtle.pathfind(Point.above(state.chest_1))
turtle.pathfind(Point.above(state.chest))
turtle.dropDown('minecraft:log')
turtle.dropDown('minecraft:log2')
end
if slots[APPLE] then
print('Storing apples')
turtle.dropDownAt(state.chest_2, APPLE)
for _, sapling in pairs(ALL_SAPLINGS) do
if slots[sapling] and slots[sapling].count > MAX_SAPLINGS then
turtle.dropDown(sapling, slots[sapling].count - MAX_SAPLINGS)
end
end
turtle.dropDown(APPLE)
end
end
@@ -430,11 +423,11 @@ local function placeTorches()
end
if turtle.getFuelLevel() > 100 and
Craft.canCraft(TORCH, 4, turtle.getSummedInventory()) then
turtle.canCraft(TORCH, 4, turtle.getSummedInventory()) then
print('Placing torches')
if craftItem(TORCH, 4) then
if turtle.has(TORCH, 4) or craftItem(TORCH, 4) then
local pts = { }
for x = -4, 4, 8 do
for z = -4, 4, 8 do
@@ -493,7 +486,7 @@ local function fellTree(pt)
desperateRefuel(FUEL_DIRE)
if turtle.digUpAt(Point.above(pt)) then
Level(
turtle.level(
{ x = GRID_WIDTH-1, y = 1, z = GRID_WIDTH-1 },
{ x = -(GRID_WIDTH-1), y = 50, z = -(GRID_WIDTH-1) },
Point.above(pt))
@@ -510,10 +503,10 @@ local function fell()
local pts = Util.shallowCopy(state.trees)
local pt = table.remove(pts, math.random(1, #pts))
local rpt = table.remove(pts, math.random(1, #pts))
-- give the pathfinder hints about what to avoid (state.trees)
if not turtle.faceAgainst(pt, { blocks = Util.shallowCopy(state.trees) }) or
if not turtle.faceAgainst(rpt, { blocks = Util.shallowCopy(state.trees) }) or
not string.match(inspect(turtle.inspect), 'minecraft:log') then
return true
end
@@ -523,7 +516,7 @@ local function fell()
local fuel = turtle.getFuelLevel()
-- push this point to the start of this list
table.insert(pts, 1, pt)
table.insert(pts, 1, rpt)
Point.eachClosest(turtle.point, pts, function(pt)
if turtle.faceAgainst(pt, { blocks = Util.shallowCopy(state.trees) }) and
@@ -545,7 +538,7 @@ local function moreTrees()
return
end
if not state.chest_1 or turtle.getItemCount('minecraft:sapling') < 15 then
if not state.chest or turtle.getItemCount('minecraft:sapling') < 15 then
return true
end
@@ -570,7 +563,7 @@ local function moreTrees()
end)
end
function getTurtleFacing(block)
local function getTurtleFacing(block)
local directions = {
[5] = 2,
[3] = 3,
@@ -586,7 +579,7 @@ function getTurtleFacing(block)
return directions[bi.metadata]
end
function saveTurtleFacing()
local function saveTurtleFacing()
if not state.facing then
setState('facing', getTurtleFacing(CHEST))
end
@@ -600,9 +593,9 @@ local function findGround()
local s, block = turtle.inspectDown()
if not s then block = { name = 'minecraft:air', metadata = 0 } end
b = block.name .. ':' .. block.metadata
local b = block.name .. ':' .. block.metadata
if b == 'minecraft:dirt:0' or
if b == 'minecraft:dirt:0' or
b == 'minecraft:grass:0' or
block.name == 'minecraft:chest' then
break
@@ -633,10 +626,7 @@ local function findHome()
end
print('Determining location')
turtle.point.heading = getTurtleFacing(CHEST)
turtle.setHeading(state.facing)
turtle.point.heading = 0
turtle.point.heading = (getTurtleFacing(CHEST) - state.facing) % 4
local pt = Point.copy(turtle.point)
@@ -663,7 +653,7 @@ local function findHome()
})
-- when pathfinding - don't leave this box
Pathing.setBox({
turtle.setPathingBox({
x = GRID.TL.x,
y = GRID.TL.y,
z = GRID.TL.z,
@@ -710,7 +700,7 @@ local tasks = {
{ desc = 'Emptying furnace', fn = emptyFurnace },
{ desc = 'Adding trees', fn = moreTrees },
{ desc = 'Chopping', fn = fell },
{ desc = 'Snacking', fn = eatSaplings },
-- { desc = 'Snacking', fn = eatSaplings },
{ desc = 'Creating chest', fn = createChests },
{ desc = 'Creating furnace', fn = createFurnace },
{ desc = 'Making charcoal', fn = makeSingleCharcoal },
@@ -719,27 +709,28 @@ local tasks = {
{ desc = 'Placing torches', fn = placeTorches },
{ desc = 'Refueling', fn = refuel },
{ desc = 'Dropping off items', fn = dropOffItems },
{ desc = 'Condensing', fn = turtle.condense },
{ desc = 'Condensing', fn = turtle.condense },
{ desc = 'Sleeping', fn = updateClock },
}
local s, m = turtle.run(function()
turtle.addFeatures('level', 'crafting')
turtle.setPolicy("attack")
while not turtle.abort do
while not turtle.isAborted() do
print('fuel: ' .. turtle.getFuelLevel())
for _,task in ipairs(Util.shallowCopy(tasks)) do
--print(task.desc)
turtle.status = task.desc
turtle.setStatus(task.desc)
turtle.select(1)
if not task.fn() then
Util.filterInplace(tasks, function(v) return v.fn ~= task.fn end)
Util.filterInplace(tasks, function(v) return v.fn ~= task.fn end)
end
end
end
end)
if not s then
error('Failed')
error(m or 'Failed')
end

1
etc/fstab.ignore Normal file
View File

@@ -0,0 +1 @@
forced fstab overwrite

View File

@@ -0,0 +1,87 @@
{
[ "appliedenergistics2:quartz_glass:0" ] = {
ingredients = {
"appliedenergistics2:material:2",
"minecraft:glass:0",
"appliedenergistics2:material:2",
[ 9 ] = "appliedenergistics2:material:2",
[ 10 ] = "minecraft:glass:0",
[ 11 ] = "appliedenergistics2:material:2",
[ 5 ] = "minecraft:glass:0",
[ 6 ] = "appliedenergistics2:material:2",
[ 7 ] = "minecraft:glass:0",
},
count = 4,
},
[ "appliedenergistics2:material:43" ] = {
ingredients = {
"appliedenergistics2:material:0",
"appliedenergistics2:material:8",
"appliedenergistics2:material:22",
},
count = 2,
},
[ "appliedenergistics2:material:44" ] = {
ingredients = {
[ 5 ] = "minecraft:quartz:0",
[ 6 ] = "appliedenergistics2:material:8",
[ 7 ] = "appliedenergistics2:material:22",
},
count = 2,
},
[ "appliedenergistics2:material:35" ] = {
ingredients = {
"minecraft:redstone:0",
"appliedenergistics2:material:0",
"minecraft:redstone:0",
[ 5 ] = "appliedenergistics2:material:0",
[ 6 ] = "appliedenergistics2:material:22",
[ 7 ] = "appliedenergistics2:material:0",
[ 9 ] = "minecraft:redstone:0",
[ 10 ] = "appliedenergistics2:material:0",
[ 11 ] = "minecraft:redstone:0",
},
count = 1,
},
[ "appliedenergistics2:interface:0" ] = {
ingredients = {
"minecraft:iron_ingot:0",
"minecraft:glass:0",
"minecraft:iron_ingot:0",
[ 9 ] = "minecraft:iron_ingot:0",
[ 10 ] = "minecraft:glass:0",
[ 11 ] = "minecraft:iron_ingot:0",
[ 5 ] = "appliedenergistics2:material:44",
[ 7 ] = "appliedenergistics2:material:43",
},
count = 1,
},
[ "appliedenergistics2:material:36" ] = {
ingredients = {
"minecraft:redstone:0",
"appliedenergistics2:material:23",
"minecraft:redstone:0",
[ 5 ] = "appliedenergistics2:material:35",
[ 6 ] = "appliedenergistics2:quartz_glass:0",
[ 7 ] = "appliedenergistics2:material:35",
[ 9 ] = "minecraft:redstone:0",
[ 10 ] = "appliedenergistics2:material:35",
[ 11 ] = "minecraft:redstone:0",
},
count = 1,
},
[ "appliedenergistics2:material:37" ] = {
ingredients = {
"minecraft:glowstone_dust:0",
"appliedenergistics2:material:24",
"minecraft:glowstone_dust:0",
[ 5 ] = "appliedenergistics2:material:36",
[ 6 ] = "appliedenergistics2:quartz_glass:0",
[ 7 ] = "appliedenergistics2:material:36",
[ 9 ] = "minecraft:glowstone_dust:0",
[ 10 ] = "appliedenergistics2:material:36",
[ 11 ] = "minecraft:glowstone_dust:0",
},
count = 1,
},
}

View File

@@ -0,0 +1,87 @@
{
[ "computercraft:turtle_advanced:0" ] = {
ingredients = {
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
[ 9 ] = "minecraft:gold_ingot:0",
[ 10 ] = "minecraft:chest:0",
[ 11 ] = "minecraft:gold_ingot:0",
[ 5 ] = "minecraft:gold_ingot:0",
[ 6 ] = "computercraft:computer:16384",
[ 7 ] = "minecraft:gold_ingot:0",
},
count = 1,
},
[ "computercraft:pocket_computer:1" ] = {
count = 1,
ingredients = {
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
[ 9 ] = "minecraft:gold_ingot:0",
[ 10 ] = "minecraft:glass_pane:0",
[ 11 ] = "minecraft:gold_ingot:0",
[ 5 ] = "minecraft:gold_ingot:0",
[ 6 ] = "minecraft:golden_apple:0",
[ 7 ] = "minecraft:gold_ingot:0",
},
maxCount = 1,
},
[ "computercraft:peripheral:0" ] = {
ingredients = {
"minecraft:stone:0",
"minecraft:stone:0",
"minecraft:stone:0",
[ 9 ] = "minecraft:stone:0",
[ 10 ] = "minecraft:redstone:0",
[ 11 ] = "minecraft:stone:0",
[ 5 ] = "minecraft:stone:0",
[ 6 ] = "minecraft:redstone:0",
[ 7 ] = "minecraft:stone:0",
},
count = 1,
},
[ "computercraft:peripheral:4" ] = {
ingredients = {
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
[ 9 ] = "minecraft:gold_ingot:0",
[ 10 ] = "minecraft:gold_ingot:0",
[ 11 ] = "minecraft:gold_ingot:0",
[ 5 ] = "minecraft:gold_ingot:0",
[ 6 ] = "minecraft:glass_pane:0",
[ 7 ] = "minecraft:gold_ingot:0",
},
count = 4,
},
[ "computercraft:advanced_modem:0" ] = {
ingredients = {
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
[ 9 ] = "minecraft:gold_ingot:0",
[ 10 ] = "minecraft:gold_ingot:0",
[ 11 ] = "minecraft:gold_ingot:0",
[ 5 ] = "minecraft:gold_ingot:0",
[ 6 ] = "minecraft:ender_eye:0",
[ 7 ] = "minecraft:gold_ingot:0",
},
count = 1,
},
[ "computercraft:computer:16384" ] = {
ingredients = {
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
"minecraft:gold_ingot:0",
[ 9 ] = "minecraft:gold_ingot:0",
[ 10 ] = "minecraft:glass_pane:0",
[ 11 ] = "minecraft:gold_ingot:0",
[ 5 ] = "minecraft:gold_ingot:0",
[ 6 ] = "minecraft:redstone:0",
[ 7 ] = "minecraft:gold_ingot:0",
},
count = 1,
},
}

544
etc/recipes/enderio.db Normal file
View File

@@ -0,0 +1,544 @@
{
[ "enderio:blockAlloySmelter:0" ] = {
ingredients = {
"minecraft:iron_ingot:0",
"minecraft:furnace:0",
"minecraft:iron_ingot:0",
[ 9 ] = "minecraft:iron_ingot:0",
[ 10 ] = "minecraft:cauldron:0",
[ 11 ] = "minecraft:iron_ingot:0",
[ 5 ] = "minecraft:furnace:0",
[ 6 ] = "enderio:itemMachinePart:0",
[ 7 ] = "minecraft:furnace:0",
},
count = 1,
},
[ "enderio:blockBuffer:0" ] = {
ingredients = {
"minecraft:iron_ingot:0",
"enderio:itemAlloy:0",
"minecraft:iron_ingot:0",
[ 9 ] = "minecraft:iron_ingot:0",
[ 10 ] = "enderio:itemAlloy:0",
[ 11 ] = "minecraft:iron_ingot:0",
[ 5 ] = "enderio:itemAlloy:0",
[ 6 ] = "minecraft:chest:0",
[ 7 ] = "enderio:itemAlloy:0",
},
count = 1,
},
[ "enderio:blockCapBank:3" ] = {
ingredients = {
"enderio:itemAlloy:0",
"enderio:itemBasicCapacitor:2",
"enderio:itemAlloy:0",
[ 9 ] = "enderio:itemAlloy:0",
[ 10 ] = "enderio:itemBasicCapacitor:2",
[ 11 ] = "enderio:itemAlloy:0",
[ 5 ] = "enderio:itemBasicCapacitor:2",
[ 6 ] = "enderio:itemMaterial:6",
[ 7 ] = "enderio:itemBasicCapacitor:2",
},
count = 1,
},
[ "enderio:blockExperienceObelisk:0" ] = {
ingredients = {
[ 9 ] = "enderio:itemAlloy:7",
[ 10 ] = "enderio:itemMachinePart:0",
[ 11 ] = "enderio:itemAlloy:7",
[ 2 ] = "enderio:itemXpTransfer:0",
[ 6 ] = "enderio:itemAlloy:7",
},
count = 1,
},
[ "enderio:blockFarmStation:0" ] = {
ingredients = {
"enderio:itemAlloy:0",
"minecraft:diamond_hoe:*",
"enderio:itemAlloy:0",
[ 9 ] = "enderio:itemMaterial:5",
[ 10 ] = "enderio:itemFrankenSkull:1",
[ 11 ] = "enderio:itemMaterial:5",
[ 5 ] = "enderio:itemAlloy:0",
[ 6 ] = "enderio:itemMachinePart:0",
[ 7 ] = "enderio:itemAlloy:0",
},
count = 1,
},
[ "enderio:blockKillerJoe:0" ] = {
ingredients = {
"enderio:itemAlloy:6",
"enderio:itemAlloy:6",
"enderio:itemAlloy:6",
[ 9 ] = "enderio:blockFusedQuartz:0",
[ 10 ] = "enderio:blockFusedQuartz:0",
[ 11 ] = "enderio:blockFusedQuartz:0",
[ 5 ] = "enderio:blockFusedQuartz:0",
[ 6 ] = "enderio:itemFrankenSkull:2",
[ 7 ] = "enderio:blockFusedQuartz:0",
},
count = 1,
},
[ "enderio:blockPainter:0" ] = {
ingredients = {
"minecraft:quartz:0",
"minecraft:diamond:0",
"minecraft:quartz:0",
[ 9 ] = "enderio:itemAlloy:0",
[ 10 ] = "enderio:itemAlloy:0",
[ 11 ] = "enderio:itemAlloy:0",
[ 5 ] = "enderio:itemAlloy:0",
[ 6 ] = "enderio:itemMachinePart:0",
[ 7 ] = "enderio:itemAlloy:0",
},
count = 1,
},
[ "enderio:blockReservoir:0" ] = {
ingredients = {
"enderio:blockFusedQuartz:0",
"enderio:blockFusedQuartz:0",
"enderio:blockFusedQuartz:0",
[ 9 ] = "enderio:blockFusedQuartz:0",
[ 10 ] = "enderio:blockFusedQuartz:0",
[ 11 ] = "enderio:blockFusedQuartz:0",
[ 5 ] = "enderio:blockFusedQuartz:0",
[ 6 ] = "minecraft:cauldron:0",
[ 7 ] = "enderio:blockFusedQuartz:0",
},
count = 4,
},
[ "enderio:blockSagMill:0" ] = {
ingredients = {
"minecraft:flint:0",
"minecraft:flint:0",
"minecraft:flint:0",
[ 9 ] = "minecraft:iron_ingot:0",
[ 10 ] = "minecraft:piston:0",
[ 11 ] = "minecraft:iron_ingot:0",
[ 5 ] = "minecraft:iron_ingot:0",
[ 6 ] = "enderio:itemMachinePart:0",
[ 7 ] = "minecraft:iron_ingot:0",
},
count = 1,
},
[ "enderio:blockSliceAndSplice:0" ] = {
ingredients = {
"enderio:itemAlloy:7",
"minecraft:skull:0",
"enderio:itemAlloy:7",
[ 9 ] = "enderio:itemAlloy:7",
[ 10 ] = "enderio:itemAlloy:7",
[ 11 ] = "enderio:itemAlloy:7",
[ 5 ] = "minecraft:iron_axe:*",
[ 6 ] = "enderio:itemMachinePart:0",
[ 7 ] = "minecraft:shears:*",
},
count = 1,
},
[ "enderio:blockSolarPanel:0" ] = {
ingredients = {
"enderio:itemAlloy:1",
"enderio:blockFusedQuartz:0",
"enderio:itemAlloy:1",
[ 9 ] = "enderio:itemBasicCapacitor:0",
[ 10 ] = "minecraft:daylight_detector:0",
[ 11 ] = "enderio:itemBasicCapacitor:0",
[ 5 ] = "enderio:itemAlloy:2",
[ 6 ] = "enderio:blockFusedQuartz:0",
[ 7 ] = "enderio:itemAlloy:2",
},
count = 1,
},
[ "enderio:blockSolarPanel:1" ] = {
ingredients = {
"enderio:itemAlloy:5",
"enderio:blockFusedQuartz:2",
"enderio:itemAlloy:5",
[ 9 ] = "enderio:itemBasicCapacitor:1",
[ 10 ] = "minecraft:daylight_detector:0",
[ 11 ] = "enderio:itemBasicCapacitor:1",
[ 5 ] = "enderio:itemAlloy:2",
[ 6 ] = "enderio:blockFusedQuartz:2",
[ 7 ] = "enderio:itemAlloy:2",
},
count = 1,
},
[ "enderio:blockSolarPanel:2" ] = {
ingredients = {
"enderio:itemAlloy:7",
"enderio:blockFusedQuartz:4",
"enderio:itemAlloy:7",
[ 9 ] = "enderio:blockSolarPanel:1",
[ 10 ] = "enderio:blockSolarPanel:1",
[ 11 ] = "enderio:blockSolarPanel:1",
[ 5 ] = "enderio:itemBasicCapacitor:2",
[ 6 ] = "enderio:itemMaterial:8",
[ 7 ] = "enderio:itemBasicCapacitor:2",
},
count = 1,
},
[ "enderio:blockSoulBinder:0" ] = {
ingredients = {
"enderio:itemAlloy:7",
"enderio:blockEndermanSkull:0",
"enderio:itemAlloy:7",
[ 9 ] = "enderio:itemAlloy:7",
[ 10 ] = "minecraft:skull:0",
[ 11 ] = "enderio:itemAlloy:7",
[ 5 ] = "minecraft:skull:4",
[ 6 ] = "enderio:itemMachinePart:0",
[ 7 ] = "minecraft:skull:2",
},
count = 1,
},
[ "enderio:blockTank:0" ] = {
ingredients = {
"minecraft:iron_ingot:0",
"minecraft:iron_bars:0",
"minecraft:iron_ingot:0",
[ 9 ] = "minecraft:iron_ingot:0",
[ 10 ] = "minecraft:iron_bars:0",
[ 11 ] = "minecraft:iron_ingot:0",
[ 5 ] = "minecraft:iron_bars:0",
[ 6 ] = "minecraft:glass:0",
[ 7 ] = "minecraft:iron_bars:0",
},
count = 1,
},
[ "enderio:blockTransceiver:0" ] = {
ingredients = {
"enderio:itemAlloy:0",
"enderio:itemFrankenSkull:3",
"enderio:itemAlloy:0",
[ 9 ] = "enderio:itemAlloy:0",
[ 10 ] = "enderio:itemBasicCapacitor:2",
[ 11 ] = "enderio:itemAlloy:0",
[ 5 ] = "enderio:blockFusedQuartz:0",
[ 6 ] = "enderio:itemMaterial:8",
[ 7 ] = "enderio:blockFusedQuartz:0",
},
count = 1,
},
[ "enderio:blockVacuumChest:0" ] = {
ingredients = {
"minecraft:iron_ingot:0",
"minecraft:iron_ingot:0",
"minecraft:iron_ingot:0",
[ 9 ] = "minecraft:iron_ingot:0",
[ 10 ] = "enderio:itemMaterial:5",
[ 11 ] = "minecraft:iron_ingot:0",
[ 5 ] = "minecraft:iron_ingot:0",
[ 6 ] = "minecraft:chest:0",
[ 7 ] = "minecraft:iron_ingot:0",
},
count = 1,
},
[ "enderio:blockVat:0" ] = {
ingredients = {
"enderio:itemAlloy:0",
"minecraft:cauldron:0",
"enderio:itemAlloy:0",
[ 9 ] = "enderio:itemAlloy:0",
[ 10 ] = "minecraft:furnace:0",
[ 11 ] = "enderio:itemAlloy:0",
[ 5 ] = "enderio:blockTank:0",
[ 6 ] = "enderio:itemMachinePart:0",
[ 7 ] = "enderio:blockTank:0",
},
count = 1,
},
[ "enderio:blockWirelessCharger:0" ] = {
ingredients = {
"enderio:itemAlloy:0",
"enderio:itemAlloy:0",
"enderio:itemAlloy:0",
[ 9 ] = "enderio:itemAlloy:0",
[ 10 ] = "enderio:itemBasicCapacitor:2",
[ 11 ] = "enderio:itemAlloy:0",
[ 5 ] = "enderio:itemAlloy:0",
[ 6 ] = "enderio:itemFrankenSkull:3",
[ 7 ] = "enderio:itemAlloy:0",
},
count = 1,
},
[ "enderio:itemBasicCapacitor:2" ] = {
ingredients = {
[ 10 ] = "enderio:itemAlloy:2",
[ 2 ] = "enderio:itemAlloy:2",
[ 5 ] = "enderio:itemBasicCapacitor:1",
[ 6 ] = "minecraft:glowstone:0",
[ 7 ] = "enderio:itemBasicCapacitor:1",
},
count = 1,
},
[ "enderio:itemBasicFilterUpgrade:0" ] = {
ingredients = {
[ 10 ] = "minecraft:paper:0",
[ 2 ] = "minecraft:paper:0",
[ 5 ] = "minecraft:paper:0",
[ 6 ] = "minecraft:hopper:0",
[ 7 ] = "minecraft:paper:0",
},
count = 1,
},
[ "enderio:itemBasicFilterUpgrade:1" ] = {
ingredients = {
"minecraft:redstone:0",
"minecraft:paper:0",
"minecraft:redstone:0",
[ 9 ] = "minecraft:redstone:0",
[ 10 ] = "minecraft:paper:0",
[ 11 ] = "minecraft:redstone:0",
[ 5 ] = "minecraft:paper:0",
[ 6 ] = "enderio:itemFrankenSkull:1",
[ 7 ] = "minecraft:paper:0",
},
count = 1,
},
[ "enderio:itemBasicFilterUpgrade:2" ] = {
ingredients = {
"minecraft:comparator:0",
"enderio:itemBasicFilterUpgrade:1",
"minecraft:comparator:0",
},
count = 1,
},
[ "enderio:itemConduitFacade:0" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:itemMaterial:1",
[ 7 ] = "enderio:itemMaterial:1",
},
count = 1,
},
[ "enderio:itemExtractSpeedUpgrade:0" ] = {
ingredients = {
"minecraft:iron_ingot:0",
"minecraft:iron_ingot:0",
"minecraft:iron_ingot:0",
[ 9 ] = "enderio:itemAlloy:0",
[ 10 ] = "minecraft:redstone_torch:0",
[ 11 ] = "enderio:itemAlloy:0",
[ 5 ] = "enderio:itemAlloy:0",
[ 6 ] = "minecraft:piston:0",
[ 7 ] = "enderio:itemAlloy:0",
},
count = 1,
},
[ "enderio:itemItemConduit:0" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:itemMaterial:3",
[ 6 ] = "enderio:itemMaterial:3",
[ 7 ] = "enderio:itemMaterial:3",
},
count = 8,
},
[ "enderio:itemLiquidConduit:0" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:blockFusedQuartz:1",
[ 6 ] = "enderio:blockFusedQuartz:1",
[ 7 ] = "enderio:blockFusedQuartz:1",
},
count = 8,
},
[ "enderio:itemLiquidConduit:1" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:blockFusedQuartz:0",
[ 6 ] = "enderio:blockFusedQuartz:0",
[ 7 ] = "enderio:blockFusedQuartz:0",
},
count = 8,
},
[ "enderio:itemLiquidConduit:2" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:itemAlloy:2",
[ 6 ] = "enderio:blockFusedQuartz:0",
[ 7 ] = "enderio:itemAlloy:2",
},
count = 8,
},
[ "enderio:itemMachinePart:0" ] = {
ingredients = {
"minecraft:iron_bars:0",
"minecraft:iron_ingot:0",
"minecraft:iron_bars:0",
[ 9 ] = "minecraft:iron_bars:0",
[ 10 ] = "minecraft:iron_ingot:0",
[ 11 ] = "minecraft:iron_bars:0",
[ 5 ] = "minecraft:iron_ingot:0",
[ 6 ] = "enderio:itemBasicCapacitor:0",
[ 7 ] = "minecraft:iron_ingot:0",
},
count = 1,
},
[ "enderio:itemMachinePart:1" ] = {
ingredients = {
"minecraft:stick:0",
"minecraft:cobblestone:0",
"minecraft:stick:0",
[ 9 ] = "minecraft:stick:0",
[ 10 ] = "minecraft:cobblestone:0",
[ 11 ] = "minecraft:stick:0",
[ 5 ] = "minecraft:cobblestone:0",
[ 7 ] = "minecraft:cobblestone:0",
},
count = 1,
},
[ "enderio:itemMaterial:2" ] = {
ingredients = {
"minecraft:gravel:0",
"minecraft:clay_ball:0",
"minecraft:gravel:0",
[ 9 ] = "minecraft:gravel:0",
[ 10 ] = "minecraft:clay_ball:0",
[ 11 ] = "minecraft:gravel:0",
[ 5 ] = "minecraft:sand:0",
[ 6 ] = "minecraft:gravel:0",
[ 7 ] = "minecraft:sand:0",
},
count = 8,
},
[ "enderio:itemMaterial:3" ] = {
ingredients = {
"enderio:itemAlloy:5",
},
count = 9,
},
[ "enderio:itemMaterial:4" ] = {
ingredients = {
"enderio:itemAlloy:2",
},
count = 9,
},
[ "enderio:itemMaterial:5" ] = {
ingredients = {
"enderio:itemMaterial:3",
"enderio:itemMaterial:3",
"enderio:itemMaterial:3",
[ 9 ] = "enderio:itemMaterial:3",
[ 10 ] = "enderio:itemMaterial:3",
[ 11 ] = "enderio:itemMaterial:3",
[ 5 ] = "enderio:itemMaterial:3",
[ 6 ] = "minecraft:diamond:0",
[ 7 ] = "enderio:itemMaterial:3",
},
count = 1,
},
[ "enderio:itemMaterial:6" ] = {
ingredients = {
"enderio:itemMaterial:4",
"enderio:itemMaterial:4",
"enderio:itemMaterial:4",
[ 9 ] = "enderio:itemMaterial:4",
[ 10 ] = "enderio:itemMaterial:4",
[ 11 ] = "enderio:itemMaterial:4",
[ 5 ] = "enderio:itemMaterial:4",
[ 6 ] = "minecraft:emerald:0",
[ 7 ] = "enderio:itemMaterial:4",
},
count = 1,
},
[ "enderio:itemPowerConduit:0" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:itemAlloy:4",
[ 6 ] = "enderio:itemAlloy:4",
[ 7 ] = "enderio:itemAlloy:4",
},
count = 8,
},
[ "enderio:itemPowerConduit:1" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:itemAlloy:1",
[ 6 ] = "enderio:itemPowerConduit:0",
[ 7 ] = "enderio:itemAlloy:1",
},
count = 8,
},
[ "enderio:itemPowerConduit:2" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:itemAlloy:2",
[ 6 ] = "enderio:itemAlloy:2",
[ 7 ] = "enderio:itemAlloy:2",
},
count = 8,
},
[ "enderio:itemRedstoneConduit:0" ] = {
ingredients = {
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
"enderio:itemMaterial:1",
[ 9 ] = "enderio:itemMaterial:1",
[ 10 ] = "enderio:itemMaterial:1",
[ 11 ] = "enderio:itemMaterial:1",
[ 5 ] = "enderio:itemAlloy:3",
[ 6 ] = "enderio:itemAlloy:3",
[ 7 ] = "enderio:itemAlloy:3",
},
count = 8,
},
[ "enderio:itemSoulVessel:0" ] = {
ingredients = {
[ 7 ] = "enderio:blockFusedQuartz:0",
[ 2 ] = "enderio:itemAlloy:7",
[ 10 ] = "enderio:blockFusedQuartz:0",
[ 5 ] = "enderio:blockFusedQuartz:0",
},
count = 1,
},
[ "enderio:itemXpTransfer:0" ] = {
count = 1,
ingredients = {
[ 6 ] = "enderio:itemAlloy:1",
[ 3 ] = "enderio:itemAlloy:7",
[ 9 ] = "enderio:itemAlloy:7",
},
maxCount = 1,
},
}

12
etc/recipes/exnihilo.db Normal file
View File

@@ -0,0 +1,12 @@
{
[ "exnihiloadscensio:hammerStone:0" ] = {
maxCount = 1,
ingredients = {
[ 7 ] = "minecraft:cobblestone:0",
[ 9 ] = "minecraft:stick:0",
[ 2 ] = "minecraft:cobblestone:0",
[ 6 ] = "minecraft:stick:0",
},
count = 1,
},
}

View File

@@ -0,0 +1,21 @@
{
[ "extrautils2:user:0" ] = {
ingredients = {
"minecraft:dropper:0",
"extrautils2:ingredients:0",
[ 5 ] = "minecraft:lever:0",
},
count = 1,
},
[ "extrautils2:endershard:0" ] = {
ingredients = {
"minecraft:ender_pearl:0",
"extrautils2:glasscutter:*",
},
craftingTools = {
[ "extrautils2:glasscutter:*" ] = true,
},
maxCount = 1,
count = 8,
},
}

58
etc/recipes/mekanism.db Normal file
View File

@@ -0,0 +1,58 @@
{
[ "mekanism:EnergyTablet:0:3a153e5a66ba42a2d96ffd50ba64918b" ] = {
ingredients = {
"minecraft:redstone:0",
"minecraft:gold_ingot:0",
"minecraft:redstone:0",
[ 9 ] = "minecraft:redstone:0",
[ 10 ] = "minecraft:gold_ingot:0",
[ 11 ] = "minecraft:redstone:0",
[ 5 ] = "mekanism:EnrichedAlloy:0",
[ 6 ] = "minecraft:gold_ingot:0",
[ 7 ] = "mekanism:EnrichedAlloy:0",
},
count = 1,
},
[ "mekanism:SpeedUpgrade:0" ] = {
ingredients = {
[ 10 ] = "minecraft:glass:0",
[ 2 ] = "minecraft:glass:0",
[ 5 ] = "mekanism:EnrichedAlloy:0",
[ 6 ] = "mekanism:Dust:2",
[ 7 ] = "mekanism:EnrichedAlloy:0",
},
count = 1,
},
[ "mekanism:ControlCircuit:1" ] = {
ingredients = {
"mekanism:EnrichedAlloy:0",
"mekanism:ControlCircuit:0",
"mekanism:EnrichedAlloy:0",
},
count = 1,
},
[ "mekanism:BasicBlock:8" ] = {
ingredients = {
"bigreactors:ingotmetals:5",
"minecraft:glass:0",
"bigreactors:ingotmetals:5",
[ 9 ] = "bigreactors:ingotmetals:5",
[ 10 ] = "minecraft:glass:0",
[ 11 ] = "bigreactors:ingotmetals:5",
[ 5 ] = "minecraft:glass:0",
[ 6 ] = "mekanism:Ingot:1",
[ 7 ] = "minecraft:glass:0",
},
count = 1,
},
[ "mekanism:EnergyUpgrade:0" ] = {
ingredients = {
[ 10 ] = "minecraft:glass:0",
[ 2 ] = "minecraft:glass:0",
[ 5 ] = "mekanism:EnrichedAlloy:0",
[ 6 ] = "exnihiloadscensio:itemOreGold:2",
[ 7 ] = "mekanism:EnrichedAlloy:0",
},
count = 1,
},
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,178 @@
{
[ "mysticalagriculture:supremium_ingot:0" ] = {
ingredients = {
[ 10 ] = "mysticalagriculture:supremium_essence:0",
[ 2 ] = "mysticalagriculture:supremium_essence:0",
[ 5 ] = "mysticalagriculture:supremium_essence:0",
[ 6 ] = "mysticalagriculture:superium_ingot:0",
[ 7 ] = "mysticalagriculture:supremium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:prudentium_ingot:0" ] = {
ingredients = {
[ 10 ] = "mysticalagriculture:prudentium_essence:0",
[ 2 ] = "mysticalagriculture:prudentium_essence:0",
[ 5 ] = "mysticalagriculture:prudentium_essence:0",
[ 6 ] = "mysticalagriculture:inferium_ingot:0",
[ 7 ] = "mysticalagriculture:prudentium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:intermedium_ingot:0" ] = {
ingredients = {
[ 10 ] = "mysticalagriculture:intermedium_essence:0",
[ 2 ] = "mysticalagriculture:intermedium_essence:0",
[ 5 ] = "mysticalagriculture:intermedium_essence:0",
[ 6 ] = "mysticalagriculture:prudentium_ingot:0",
[ 7 ] = "mysticalagriculture:intermedium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:superium_armor_core:0" ] = {
ingredients = {
"mysticalagriculture:superium_essence:0",
"minecraft:diamond_block:0",
"mysticalagriculture:superium_essence:0",
[ 5 ] = "minecraft:emerald:0",
[ 6 ] = "mysticalagriculture:intermedium_armor_core:0",
[ 7 ] = "minecraft:emerald:0",
[ 9 ] = "mysticalagriculture:superium_essence:0",
[ 10 ] = "minecraft:emerald:0",
[ 11 ] = "mysticalagriculture:superium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:inferium_ingot:0" ] = {
ingredients = {
[ 10 ] = "mysticalagriculture:inferium_essence:0",
[ 2 ] = "mysticalagriculture:inferium_essence:0",
[ 5 ] = "mysticalagriculture:inferium_essence:0",
[ 6 ] = "mysticalagriculture:base_essence_ingot:0",
[ 7 ] = "mysticalagriculture:inferium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:intermedium_armor_core:0" ] = {
ingredients = {
"mysticalagriculture:intermedium_essence:0",
"minecraft:gold_block:0",
"mysticalagriculture:intermedium_essence:0",
[ 5 ] = "minecraft:diamond:0",
[ 6 ] = "mysticalagriculture:prudentium_armor_core:0",
[ 7 ] = "minecraft:diamond:0",
[ 9 ] = "mysticalagriculture:intermedium_essence:0",
[ 10 ] = "minecraft:diamond:0",
[ 11 ] = "mysticalagriculture:intermedium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:infusion_crystal:0" ] = {
ingredients = {
"mysticalagriculture:prosperity_shard:0",
"mysticalagriculture:inferium_essence:0",
"mysticalagriculture:prosperity_shard:0",
[ 9 ] = "mysticalagriculture:prosperity_shard:0",
[ 10 ] = "mysticalagriculture:inferium_essence:0",
[ 11 ] = "mysticalagriculture:prosperity_shard:0",
[ 5 ] = "mysticalagriculture:inferium_essence:0",
[ 6 ] = "minecraft:diamond:0",
[ 7 ] = "mysticalagriculture:inferium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:supremium_armor_core:0" ] = {
ingredients = {
"mysticalagriculture:supremium_essence:0",
"minecraft:nether_star:0",
"mysticalagriculture:supremium_essence:0",
[ 5 ] = "minecraft:skull:1",
[ 6 ] = "mysticalagriculture:superium_armor_core:0",
[ 7 ] = "minecraft:skull:1",
[ 9 ] = "mysticalagriculture:supremium_essence:0",
[ 10 ] = "minecraft:skull:1",
[ 11 ] = "mysticalagriculture:supremium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:inferium_armor_core:0" ] = {
ingredients = {
"mysticalagriculture:inferium_essence:0",
"minecraft:gold_ingot:0",
"mysticalagriculture:inferium_essence:0",
[ 5 ] = "minecraft:leather:0",
[ 6 ] = "mysticalagriculture:base_essence_ingot:0",
[ 7 ] = "minecraft:leather:0",
[ 9 ] = "mysticalagriculture:inferium_essence:0",
[ 10 ] = "minecraft:leather:0",
[ 11 ] = "mysticalagriculture:inferium_essence:0",
},
count = 1,
},
[ "mysticalagriculture:base_essence_ingot:0" ] = {
ingredients = {
[ 10 ] = "mysticalagriculture:prosperity_shard:0",
[ 2 ] = "mysticalagriculture:prosperity_shard:0",
[ 5 ] = "mysticalagriculture:prosperity_shard:0",
[ 6 ] = "thermalfoundation:material:136",
[ 7 ] = "mysticalagriculture:prosperity_shard:0",
},
count = 1,
},
[ "mysticalagriculture:tier2_inferium_seeds:0" ] = {
count = 1,
ingredients = {
"mysticalagriculture:prudentium_essence:0",
"mysticalagriculture:prudentium_essence:0",
"mysticalagriculture:prudentium_essence:0",
[ 9 ] = "mysticalagriculture:prudentium_essence:0",
[ 10 ] = "mysticalagriculture:prudentium_essence:0",
[ 11 ] = "mysticalagriculture:prudentium_essence:0",
[ 5 ] = "mysticalagriculture:prudentium_essence:0",
[ 6 ] = "mysticalagriculture:tier1_inferium_seeds:0",
[ 7 ] = "mysticalagriculture:prudentium_essence:0",
},
},
[ "mysticalagriculture:tier3_inferium_seeds:0" ] = {
count = 1,
ingredients = {
"mysticalagriculture:intermedium_essence:0",
"mysticalagriculture:intermedium_essence:0",
"mysticalagriculture:intermedium_essence:0",
[ 9 ] = "mysticalagriculture:intermedium_essence:0",
[ 10 ] = "mysticalagriculture:intermedium_essence:0",
[ 11 ] = "mysticalagriculture:intermedium_essence:0",
[ 5 ] = "mysticalagriculture:intermedium_essence:0",
[ 6 ] = "mysticalagriculture:tier2_inferium_seeds:0",
[ 7 ] = "mysticalagriculture:intermedium_essence:0",
},
},
[ "mysticalagriculture:tier1_inferium_seeds:0" ] = {
count = 1,
ingredients = {
"mysticalagriculture:inferium_essence:0",
"mysticalagriculture:inferium_essence:0",
"mysticalagriculture:inferium_essence:0",
[ 9 ] = "mysticalagriculture:inferium_essence:0",
[ 10 ] = "mysticalagriculture:inferium_essence:0",
[ 11 ] = "mysticalagriculture:inferium_essence:0",
[ 5 ] = "mysticalagriculture:inferium_essence:0",
[ 6 ] = "minecraft:wheat_seeds:0",
[ 7 ] = "mysticalagriculture:inferium_essence:0",
},
},
[ "mysticalagriculture:prudentium_armor_core:0" ] = {
ingredients = {
"mysticalagriculture:prudentium_essence:0",
"minecraft:lapis_block:0",
"mysticalagriculture:prudentium_essence:0",
[ 5 ] = "minecraft:gold_ingot:0",
[ 6 ] = "mysticalagriculture:inferium_armor_core:0",
[ 7 ] = "minecraft:gold_ingot:0",
[ 9 ] = "mysticalagriculture:prudentium_essence:0",
[ 10 ] = "minecraft:gold_ingot:0",
[ 11 ] = "mysticalagriculture:prudentium_essence:0",
},
count = 1,
},
}

View File

@@ -0,0 +1,28 @@
{
[ "storagedrawers:basicDrawers:0:b85f006d9f6aa0e06184f8931d4e85c1" ] = {
ingredients = {
"minecraft:planks:0",
"minecraft:planks:0",
"minecraft:planks:0",
[ 9 ] = "minecraft:planks:0",
[ 10 ] = "minecraft:planks:0",
[ 11 ] = "minecraft:planks:0",
[ 6 ] = "minecraft:chest:0",
},
count = 1,
},
[ "storagedrawers:upgradeTemplate:0" ] = {
ingredients = {
"minecraft:stick:0",
"minecraft:stick:0",
"minecraft:stick:0",
[ 9 ] = "minecraft:stick:0",
[ 10 ] = "minecraft:stick:0",
[ 11 ] = "minecraft:stick:0",
[ 5 ] = "minecraft:stick:0",
[ 6 ] = "storagedrawers:basicDrawers:0:b85f006d9f6aa0e06184f8931d4e85c1",
[ 7 ] = "minecraft:stick:0",
},
count = 2,
},
}

22
etc/recipes/tconstruct.db Normal file
View File

@@ -0,0 +1,22 @@
{
[ "minecraft:book:0" ] = {
ingredients = {
"minecraft:paper:0",
"minecraft:paper:0",
"minecraft:paper:0",
[ 5 ] = "minecraft:string:0",
[ 6 ] = "tconstruct:pattern:0",
[ 7 ] = "tconstruct:pattern:0",
},
count = 1,
},
[ "tconstruct:pattern:0" ] = {
ingredients = {
"minecraft:planks:0",
"minecraft:stick:0",
[ 5 ] = "minecraft:stick:0",
[ 6 ] = "minecraft:planks:0",
},
count = 4,
},
}

View File

@@ -1 +1 @@
turtle.abortAction()
turtle.abort(true)

View File

@@ -1,12 +1,15 @@
local os = _G.os
local turtle = _G.turtle
local function follow(id)
requireInjector(getfenv(1))
_G.requireInjector()
local Event = require('event')
local Point = require('point')
local Socket = require('socket')
turtle.status = 'follow ' .. id
turtle.setStatus('follow ' .. id)
if not turtle.enableGPS() then
error('turtle: No GPS found')
@@ -55,7 +58,7 @@ local function follow(id)
Event.onInterval(.5, function()
local function getRemotePoint()
if not turtle.abort then
if not turtle.isAborted() then
if socket:write({ type = 'gps' }) then
return socket:read(3)
end
@@ -65,7 +68,7 @@ local function follow(id)
-- sometimes gps will fail if moving
local pt, d
for i = 1, 3 do
for _ = 1, 3 do
pt, d = getRemotePoint()
if pt then
break
@@ -73,22 +76,22 @@ local function follow(id)
os.sleep(.5)
end
if not pt or turtle.abort then
if not pt or turtle.isAborted() then
error('Did not receive GPS location')
end
if not lastPoint or (lastPoint.x ~= pt.x or lastPoint.y ~= pt.y or lastPoint.z ~= pt.z) then
if following then
turtle.abort = true
turtle.getState().abort = true
while following do
os.sleep(.1)
end
turtle.abort = false
turtle.getState().abort = false
end
-- check if gps is inaccurate (player moving too fast)
if d < Point.pythagoreanDistance(turtle.point, pt) + 10 then
if d < Point.distance(turtle.point, pt) + 10 then
lastPoint = Point.copy(pt)
following = true
os.queueEvent('turtle_follow', pt)

View File

@@ -1 +1,2 @@
turtle.run(turtle.gotoGPSHome)
local Home = require('turtle.home')
turtle.run(Home.go)

View File

@@ -1,85 +0,0 @@
requireInjector(getfenv(1))
local Point = require('point')
local Util = require('util')
local checkedNodes = { }
local nodes = { }
local box = { x = 65, ex = 69, y = 65, ey = 70, z = -23, ez = -19 }
local function inBox(pt, box)
return pt.x >= box.x and
pt.y >= box.y and
pt.z >= box.z and
pt.x <= box.ex and
pt.y <= box.ey and
pt.z <= box.ez
end
local function toKey(pt)
return table.concat({ pt.x, pt.y, pt.z }, ':')
end
local function addNode(node)
for i = 0, 5 do
local hi = turtle.getHeadingInfo(i)
local testNode = { x = node.x + hi.xd, y = node.y + hi.yd, z = node.z + hi.zd }
if inBox(testNode, box) then
local key = toKey(testNode)
if not checkedNodes[key] then
nodes[key] = testNode
end
end
end
end
local function dig(facing)
local direction = facing
if direction == 'forward' then
direction = turtle.getHeadingInfo(turtle.point.heading).direction
end
local hi = turtle.getHeadingInfo(direction)
local node = { x = turtle.point.x + hi.xd, y = turtle.point.y + hi.yd, z = turtle.point.z + hi.zd }
if inBox(node, box) then
if turtle.getAction(facing).dig() then
addNode(node)
end
end
end
local function level()
repeat
local node = { x = turtle.point.x, y = turtle.point.y, z = turtle.point.z }
local key = toKey(node)
checkedNodes[key] = true
nodes[key] = nil
dig('down')
dig('up')
dig('forward')
print(string.format('%d nodes remaining', Util.size(nodes)))
if Util.size(nodes) == 0 then
break
end
local node = Point.closest(turtle.point, nodes)
if not turtle.gotoPoint(node) then
break
end
until turtle.abort
end
local pt = Util.shallowCopy(turtle.point)
turtle.setPolicy(turtle.policies.none)
if turtle.pathfind({ x = 65, y = 70, z = -23 }) then
--turtle.reset()
turtle.setPolicy(turtle.policies.digOnly)
level()
end
turtle.pathfind(pt)
--local s, m = turtle.run(level)

View File

@@ -1,8 +1,11 @@
requireInjector(getfenv(1))
_G.requireInjector()
local Point = require('point')
local Util = require('util')
local os = _G.os
local turtle = _G.turtle
local checkedNodes, nodes
local function addNode(node)
@@ -47,7 +50,7 @@ local function findObsidian()
if turtle.getItemCount(16) > 0 then
print('Inventory full')
print('Enter to continue...')
read()
_G.read()
end
if b and b.name == 'minecraft:obsidian' then
@@ -63,40 +66,43 @@ local function findObsidian()
break
end
local node = Point.closest(turtle.point, nodes)
if not turtle.gotoPoint(node) then
node = Point.closest(turtle.point, nodes)
if not turtle._goto(node) then
break
end
until turtle.abort
until turtle.isAborted()
end
turtle.reset()
turtle.setPolicy(turtle.policies.digOnly)
local s, m = turtle.run(function()
repeat
turtle.run(function()
turtle.reset()
turtle.setPolicy(turtle.policies.digOnly)
checkedNodes = { }
nodes = { }
local s, m = pcall(function()
repeat
checkedNodes = { }
nodes = { }
local _,b = turtle.inspectDown()
if not b or b.name ~= 'minecraft:obsidian' then
break
end
local _,b = turtle.inspectDown()
if not b or b.name ~= 'minecraft:obsidian' then
break
end
findObsidian()
if not turtle.select('minecraft:water_bucket') then
break
end
turtle.goto(0, 0)
turtle.placeDown()
os.sleep(2)
turtle.placeDown()
turtle.down()
turtle.select(1)
until turtle.abort
findObsidian()
if not turtle.select('minecraft:water_bucket') then
break
end
turtle._goto({ x = 0, z = 0 })
turtle.placeDown()
os.sleep(2)
turtle.placeDown()
turtle.down()
turtle.select(1)
until turtle.isAborted()
end)
if not s and m then
error(m)
end
turtle._goto({ x = 0, y = 0, z = 0, heading = 0 })
end)
turtle.goto(0, 0, 0, 0)
turtle.reset()
if not s and m then
error(m)
end

View File

@@ -1 +1,2 @@
turtle.run(turtle.setGPSHome)
local Home = require('turtle.home')
turtle.run(Home.set)

View File

@@ -6,7 +6,7 @@ local function summon(id)
local Point = require('point')
local Socket = require('socket')
turtle.status = 'GPSing'
turtle.setStatus('GPSing')
turtle.setPoint({ x = 0, y = 0, z = 0, heading = 0 })
local pts = {
@@ -32,7 +32,7 @@ local function summon(id)
local function doGPS()
tFixes = { }
for i = 1, 4 do
if not turtle.gotoPoint(pts[i]) then
if not turtle._goto(pts[i]) then
error('turtle: Unable to perform GPS maneuver')
end
local distance = getDistance()
@@ -64,7 +64,7 @@ local function summon(id)
local pt = { x = pos.x, y = pos.y, z = pos.z }
local _, h = Point.calculateMoves(turtle.getPoint(), pt)
local hi = turtle.getHeadingInfo(h)
turtle.status = 'recalling'
turtle.setStatus('recalling')
turtle.pathfind({ x = pt.x - hi.xd, z = pt.z - hi.zd, y = pt.y - hi.yd, heading = h })
else
error("turtle: Could not determine position")