compression package - debugger fixes
This commit is contained in:
3525
compress/apis/libdeflate.lua
Normal file
3525
compress/apis/libdeflate.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,7 @@
|
|||||||
|
|
||||||
-- see: https://github.com/luarocks/luarocks/blob/master/src/luarocks/tools/tar.lua
|
-- see: https://github.com/luarocks/luarocks/blob/master/src/luarocks/tools/tar.lua
|
||||||
-- A pure-Lua implementation of untar (unpacking .tar archives)
|
-- A pure-Lua implementation of untar (unpacking .tar archives)
|
||||||
|
local Util = require('opus.util')
|
||||||
local tar = { }
|
|
||||||
|
|
||||||
local fs = _G.fs
|
local fs = _G.fs
|
||||||
|
|
||||||
@@ -54,7 +53,6 @@ local function checksum_header(block)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function nullterm(s)
|
local function nullterm(s)
|
||||||
_G._zz = s
|
|
||||||
return s:match("^[^%z]*")
|
return s:match("^[^%z]*")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -82,7 +80,7 @@ local function read_header_block(block)
|
|||||||
return header
|
return header
|
||||||
end
|
end
|
||||||
|
|
||||||
function tar.untar(filename, destdir, verbose)
|
local function untar(filename, destdir, verbose)
|
||||||
assert(type(filename) == "string")
|
assert(type(filename) == "string")
|
||||||
assert(type(destdir) == "string")
|
assert(type(destdir) == "string")
|
||||||
|
|
||||||
@@ -165,7 +163,7 @@ function tar.untar(filename, destdir, verbose)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function create_header_block(filename, abspath)
|
local function create_header_block(filename, abspath)
|
||||||
local block = ('\0'):rep(512)
|
local block = ('\0'):rep(blocksize)
|
||||||
|
|
||||||
local function number_to_octal(n)
|
local function number_to_octal(n)
|
||||||
return ('%o'):format(n)
|
return ('%o'):format(n)
|
||||||
@@ -185,7 +183,7 @@ local function create_header_block(filename, abspath)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- the bare minimum for this program to untar
|
-- the bare minimum for this program to untar
|
||||||
function tar.tar(filename, root, files)
|
local function tar(filename, root, files)
|
||||||
assert(type(filename) == "string")
|
assert(type(filename) == "string")
|
||||||
assert(type(root) == "string")
|
assert(type(root) == "string")
|
||||||
assert(type(files) == "table")
|
assert(type(files) == "table")
|
||||||
@@ -197,15 +195,18 @@ function tar.tar(filename, root, files)
|
|||||||
local abs = fs.combine(root, file)
|
local abs = fs.combine(root, file)
|
||||||
local block = create_header_block(file, abs)
|
local block = create_header_block(file, abs)
|
||||||
tar_handle:write(block)
|
tar_handle:write(block)
|
||||||
local f = require('opus.util').readFile(abs, 'rb')
|
local f = Util.readFile(abs, 'rb')
|
||||||
tar_handle:write(f)
|
tar_handle:write(f)
|
||||||
local padding = #f % 512
|
local padding = #f % blocksize
|
||||||
if padding > 0 then
|
if padding > 0 then
|
||||||
tar_handle:write(('\0'):rep(512 - padding))
|
tar_handle:write(('\0'):rep(blocksize - padding))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
tar_handle:close()
|
tar_handle:close()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
return tar
|
return {
|
||||||
|
tar = tar,
|
||||||
|
untar = untar,
|
||||||
|
}
|
||||||
|
|||||||
53
compress/compress.lua
Normal file
53
compress/compress.lua
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
local LZW = require('compress.lzw')
|
||||||
|
local Tar = require('compress.tar')
|
||||||
|
local Util = require('opus.util')
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
|
local shell = _ENV.shell
|
||||||
|
|
||||||
|
local TMP_FILE = '.out.tar'
|
||||||
|
|
||||||
|
local args = { ... }
|
||||||
|
local files = { }
|
||||||
|
|
||||||
|
if not args[2] then
|
||||||
|
error('Syntax: tar OUTFILE DIR')
|
||||||
|
end
|
||||||
|
|
||||||
|
local file = shell.resolve(args[1])
|
||||||
|
local dir = shell.resolve(args[2])
|
||||||
|
|
||||||
|
local filetype = 'tar'
|
||||||
|
if file:match('(.+)%.tar$') then
|
||||||
|
filetype = 'tar'
|
||||||
|
elseif file:match('(.+)%.lzw$') then
|
||||||
|
filetype = 'lzw'
|
||||||
|
end
|
||||||
|
|
||||||
|
local function recurse(rel)
|
||||||
|
local abs = fs.combine(dir, rel)
|
||||||
|
for _,f in ipairs(fs.list(abs)) do
|
||||||
|
local fullName = fs.combine(abs, f)
|
||||||
|
if fs.native.isDir(fullName) then -- skip virtual dirs
|
||||||
|
recurse(fs.combine(rel, f))
|
||||||
|
else
|
||||||
|
table.insert(files, fs.combine(rel, f))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
recurse('')
|
||||||
|
|
||||||
|
if filetype == 'tar' then
|
||||||
|
Tar.tar(file, dir, files)
|
||||||
|
|
||||||
|
elseif filetype == 'lzw' then
|
||||||
|
fs.mount(TMP_FILE, 'ramfs', 'file')
|
||||||
|
Tar.tar(TMP_FILE, dir, files)
|
||||||
|
|
||||||
|
local c = Util.readFile(TMP_FILE)
|
||||||
|
fs.delete(TMP_FILE)
|
||||||
|
|
||||||
|
c = LZW.compress(c)
|
||||||
|
Util.writeFile(file, c)
|
||||||
|
end
|
||||||
|
|
||||||
66
compress/uncompress.lua
Normal file
66
compress/uncompress.lua
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
local DEFLATE = require('compress.deflatelua')
|
||||||
|
local LZW = require('compress.lzw')
|
||||||
|
local Tar = require('compress.tar')
|
||||||
|
local Util = require('opus.util')
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
|
local io = _G.io
|
||||||
|
local shell = _ENV.shell
|
||||||
|
|
||||||
|
local TMP_FILE = '.out.tar'
|
||||||
|
|
||||||
|
local args = { ... }
|
||||||
|
|
||||||
|
if not args[2] then
|
||||||
|
error('Syntax: tar FILE DESTDIR')
|
||||||
|
end
|
||||||
|
|
||||||
|
local inFile = shell.resolve(args[1])
|
||||||
|
local outDir = shell.resolve(args[2])
|
||||||
|
|
||||||
|
local s, m = pcall(function()
|
||||||
|
if inFile:match('(.+)%.[gG][zZ]$') then
|
||||||
|
local fh = io.open(inFile, 'rb') or error('Error opening ' .. inFile)
|
||||||
|
|
||||||
|
fs.mount(TMP_FILE, 'ramfs', 'file')
|
||||||
|
local ofh = io.open(TMP_FILE, 'wb')
|
||||||
|
|
||||||
|
DEFLATE.gunzip {input=fh, output=ofh, disable_crc=true}
|
||||||
|
|
||||||
|
fh:close()
|
||||||
|
ofh:close()
|
||||||
|
|
||||||
|
local s, m = Tar.untar(TMP_FILE, outDir, true)
|
||||||
|
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif inFile:match('(.+)%.lzw$') then
|
||||||
|
local c = Util.readFile(inFile)
|
||||||
|
if not c then
|
||||||
|
error('Unable to open ' .. inFile)
|
||||||
|
end
|
||||||
|
|
||||||
|
fs.mount(TMP_FILE, 'ramfs', 'file')
|
||||||
|
Util.writeFile(TMP_FILE, LZW.decompress(c))
|
||||||
|
|
||||||
|
local s, m = Tar.untar(TMP_FILE, outDir, true)
|
||||||
|
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
local s, m = Tar.untar(inFile, outDir)
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
fs.delete(TMP_FILE)
|
||||||
|
|
||||||
|
if not s then
|
||||||
|
error(m)
|
||||||
|
end
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
-- see: https://github.com/luarocks/luarocks/blob/master/src/luarocks/tools/tar.lua
|
|
||||||
|
|
||||||
-- TODO: support normal tar syntax -- tar xvf
|
|
||||||
|
|
||||||
local DEFLATE = require('compress.deflatelua')
|
|
||||||
local tar = require('compress.tar')
|
|
||||||
|
|
||||||
local fs = _G.fs
|
|
||||||
local io = _G.io
|
|
||||||
local shell = _ENV.shell
|
|
||||||
|
|
||||||
local args = { ... }
|
|
||||||
|
|
||||||
if not args[2] then
|
|
||||||
error('Syntax: tar FILE DESTDIR')
|
|
||||||
end
|
|
||||||
|
|
||||||
local inFile = shell.resolve(args[1])
|
|
||||||
local outDir = shell.resolve(args[2])
|
|
||||||
|
|
||||||
if inFile:match('(.+)%.[gG][zZ]$') then
|
|
||||||
local TMP_FILE = '.out.tar'
|
|
||||||
|
|
||||||
local fh = io.open(inFile, 'rb') or error('Error opening ' .. inFile)
|
|
||||||
|
|
||||||
fs.mount(TMP_FILE, 'ramfs', 'file')
|
|
||||||
local ofh = io.open(TMP_FILE, 'wb')
|
|
||||||
|
|
||||||
DEFLATE.gunzip {input=fh, output=ofh, disable_crc=true}
|
|
||||||
|
|
||||||
fh:close()
|
|
||||||
ofh:close()
|
|
||||||
|
|
||||||
local s, m = tar.untar(TMP_FILE, outDir, true)
|
|
||||||
|
|
||||||
fs.delete(TMP_FILE)
|
|
||||||
|
|
||||||
if not s then
|
|
||||||
error(m)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local s, m = tar.untar(inFile, outDir)
|
|
||||||
if not s then
|
|
||||||
error(m)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -58,6 +58,8 @@ local function startClient()
|
|||||||
return cmd, param
|
return cmd, param
|
||||||
end
|
end
|
||||||
|
|
||||||
|
_ENV.arg = { table.unpack(args) }
|
||||||
|
_ENV.arg[0] = filename
|
||||||
-- breakpoint table is shared across processes
|
-- breakpoint table is shared across processes
|
||||||
dbg.breakpoints = breakpoints
|
dbg.breakpoints = breakpoints
|
||||||
dbg.debugger = debugger
|
dbg.debugger = debugger
|
||||||
@@ -111,13 +113,23 @@ local function message(...)
|
|||||||
client:resume('debugger', ...)
|
client:resume('debugger', ...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
UI.InverseButton = require('opus.class')(UI.Button)
|
||||||
|
UI.InverseButton.defaults = {
|
||||||
|
UIElement = 'InverseButton',
|
||||||
|
backgroundColor = 'primary',
|
||||||
|
backgroundFocusColor = 'gray',
|
||||||
|
textFocusColor = 'primary',
|
||||||
|
textColor = 'gray',
|
||||||
|
}
|
||||||
|
|
||||||
local page = UI.Page {
|
local page = UI.Page {
|
||||||
backgroundColor = 'black',
|
backgroundColor = 'gray',
|
||||||
|
|
||||||
container = UI.Window {
|
container = UI.Window {
|
||||||
y = 1, ey = '50%',
|
y = 1, ey = '50%',
|
||||||
tabs = UI.Tabs {
|
tabs = UI.Tabs {
|
||||||
ey = -2,
|
ey = -2,
|
||||||
|
barBackgroundColor = 'tertiary',
|
||||||
locals = UI.Tab {
|
locals = UI.Tab {
|
||||||
title = 'Locals',
|
title = 'Locals',
|
||||||
index = 1,
|
index = 1,
|
||||||
@@ -241,6 +253,8 @@ local page = UI.Page {
|
|||||||
|
|
||||||
menuBar = UI.MenuBar {
|
menuBar = UI.MenuBar {
|
||||||
y = -1,
|
y = -1,
|
||||||
|
backgroundColor = 'primary',
|
||||||
|
buttonClass = 'InverseButton',
|
||||||
buttons = {
|
buttons = {
|
||||||
{ text = 'Continue', event = 'cmd', cmd = 'c' },
|
{ text = 'Continue', event = 'cmd', cmd = 'c' },
|
||||||
{ text = 'Step', event = 'cmd', cmd = 's' },
|
{ text = 'Step', event = 'cmd', cmd = 's' },
|
||||||
@@ -254,6 +268,9 @@ local page = UI.Page {
|
|||||||
source = UI.ScrollingGrid {
|
source = UI.ScrollingGrid {
|
||||||
y = '50%', ey = -2,
|
y = '50%', ey = -2,
|
||||||
disableHeader = true,
|
disableHeader = true,
|
||||||
|
backgroundColor = 'gray',
|
||||||
|
backgroundSelectedColor = 'lightGray',
|
||||||
|
unfocusedBackgroundSelectedColor = 'lightGray',
|
||||||
columns = {
|
columns = {
|
||||||
{ key = 'marker', width = 1 },
|
{ key = 'marker', width = 1 },
|
||||||
{ key = 'line', textColor = 'cyan', width = 4 },
|
{ key = 'line', textColor = 'cyan', width = 4 },
|
||||||
@@ -302,7 +319,7 @@ local page = UI.Page {
|
|||||||
},
|
},
|
||||||
statusBar = UI.StatusBar {
|
statusBar = UI.StatusBar {
|
||||||
ex = -12, y = -1,
|
ex = -12, y = -1,
|
||||||
backgroundColor = 'black',
|
backgroundColor = 'gray',
|
||||||
textColor = 'orange',
|
textColor = 'orange',
|
||||||
},
|
},
|
||||||
UI.FlatButton {
|
UI.FlatButton {
|
||||||
@@ -385,6 +402,7 @@ local page = UI.Page {
|
|||||||
eventHandler = function(self, event)
|
eventHandler = function(self, event)
|
||||||
if event.type == 'cmd' then
|
if event.type == 'cmd' then
|
||||||
self.statusBar:setStatus('Running...')
|
self.statusBar:setStatus('Running...')
|
||||||
|
self:sync()
|
||||||
message(event.element.cmd)
|
message(event.element.cmd)
|
||||||
|
|
||||||
elseif event.type == 'restart' then
|
elseif event.type == 'restart' then
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
local w, h = term.getSize()
|
|
||||||
|
|
||||||
term.clear()
|
|
||||||
term.setCursorPos(1, 1)
|
|
||||||
|
|
||||||
local t = { }
|
|
||||||
for i = 1, 8 do
|
|
||||||
table.insert(t, '---')
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, 255 do
|
|
||||||
table.insert(t, string.format('%d %c', i, i))
|
|
||||||
end
|
|
||||||
|
|
||||||
textutils.pagedTabulate(t)
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
local class = require('opus.class')
|
|
||||||
local UI = require('opus.ui')
|
|
||||||
local Event = require('opus.event')
|
|
||||||
local Peripheral = require('opus.peripheral')
|
|
||||||
|
|
||||||
--[[-- Glasses device --]]--
|
|
||||||
local Glasses = class()
|
|
||||||
function Glasses:init(args)
|
|
||||||
|
|
||||||
local defaults = {
|
|
||||||
backgroundColor = colors.black,
|
|
||||||
textColor = colors.white,
|
|
||||||
textScale = .5,
|
|
||||||
backgroundOpacity = .5,
|
|
||||||
multiplier = 2.6665,
|
|
||||||
-- multiplier = 2.333,
|
|
||||||
}
|
|
||||||
defaults.width, defaults.height = term.getSize()
|
|
||||||
|
|
||||||
UI:setProperties(defaults, args)
|
|
||||||
UI:setProperties(self, defaults)
|
|
||||||
|
|
||||||
self.bridge = Peripheral.get({
|
|
||||||
type = 'openperipheral_bridge',
|
|
||||||
method = 'addBox',
|
|
||||||
})
|
|
||||||
self.bridge.clear()
|
|
||||||
|
|
||||||
self.setBackgroundColor = function(...) end
|
|
||||||
self.setTextColor = function(...) end
|
|
||||||
|
|
||||||
self.t = { }
|
|
||||||
for i = 1, self.height do
|
|
||||||
self.t[i] = {
|
|
||||||
text = string.rep(' ', self.width+1),
|
|
||||||
--text = self.bridge.addText(0, 40+i*4, string.rep(' ', self.width+1), 0xffffff),
|
|
||||||
bg = { },
|
|
||||||
textFields = { },
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Glasses:setBackgroundBox(boxes, ax, bx, y, bgColor)
|
|
||||||
local colors = {
|
|
||||||
[ colors.black ] = 0x000000,
|
|
||||||
[ colors.brown ] = 0x7F664C,
|
|
||||||
[ colors.blue ] = 0x253192,
|
|
||||||
[ colors.red ] = 0xFF0000,
|
|
||||||
[ colors.gray ] = 0x272727,
|
|
||||||
[ colors.lime ] = 0x426A0D,
|
|
||||||
[ colors.green ] = 0x2D5628,
|
|
||||||
[ colors.white ] = 0xFFFFFF
|
|
||||||
}
|
|
||||||
|
|
||||||
local function overlap(box, ax, bx)
|
|
||||||
if bx < box.ax or ax > box.bx then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,box in pairs(boxes) do
|
|
||||||
if overlap(box, ax, bx) then
|
|
||||||
if box.bgColor == bgColor then
|
|
||||||
ax = math.min(ax, box.ax)
|
|
||||||
bx = math.max(bx, box.bx)
|
|
||||||
box.ax = box.bx + 1
|
|
||||||
elseif ax == box.ax then
|
|
||||||
box.ax = bx + 1
|
|
||||||
elseif ax > box.ax then
|
|
||||||
if bx < box.bx then
|
|
||||||
table.insert(boxes, { -- split
|
|
||||||
ax = bx + 1,
|
|
||||||
bx = box.bx,
|
|
||||||
bgColor = box.bgColor
|
|
||||||
})
|
|
||||||
box.bx = ax - 1
|
|
||||||
break
|
|
||||||
else
|
|
||||||
box.ax = box.bx + 1
|
|
||||||
end
|
|
||||||
elseif ax < box.ax then
|
|
||||||
if bx > box.bx then
|
|
||||||
box.ax = box.bx + 1 -- delete
|
|
||||||
else
|
|
||||||
box.ax = bx + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if bgColor ~= colors.black then
|
|
||||||
table.insert(boxes, {
|
|
||||||
ax = ax,
|
|
||||||
bx = bx,
|
|
||||||
bgColor = bgColor
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local deleted
|
|
||||||
repeat
|
|
||||||
deleted = false
|
|
||||||
for k,box in pairs(boxes) do
|
|
||||||
if box.ax > box.bx then
|
|
||||||
if box.box then
|
|
||||||
box.box.delete()
|
|
||||||
end
|
|
||||||
table.remove(boxes, k)
|
|
||||||
deleted = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if not box.box then
|
|
||||||
box.box = self.bridge.addBox(
|
|
||||||
math.floor(self.x + (box.ax - 1) * self.multiplier),
|
|
||||||
self.y + y * 4,
|
|
||||||
math.ceil((box.bx - box.ax + 1) * self.multiplier),
|
|
||||||
4,
|
|
||||||
colors[bgColor],
|
|
||||||
self.backgroundOpacity)
|
|
||||||
else
|
|
||||||
box.box.setX(self.x + math.floor((box.ax - 1) * self.multiplier))
|
|
||||||
box.box.setWidth(math.ceil((box.bx - box.ax + 1) * self.multiplier))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
until not deleted
|
|
||||||
end
|
|
||||||
|
|
||||||
function Glasses:write(x, y, text, bg)
|
|
||||||
|
|
||||||
if x < 1 then
|
|
||||||
error(' less ', 6)
|
|
||||||
end
|
|
||||||
if y <= #self.t then
|
|
||||||
local line = self.t[y]
|
|
||||||
local str = line.text
|
|
||||||
str = str:sub(1, x-1) .. text .. str:sub(x + #text)
|
|
||||||
self.t[y].text = str
|
|
||||||
|
|
||||||
for _,tf in pairs(line.textFields) do
|
|
||||||
tf.delete()
|
|
||||||
end
|
|
||||||
line.textFields = { }
|
|
||||||
|
|
||||||
local function split(st)
|
|
||||||
local words = { }
|
|
||||||
local offset = 0
|
|
||||||
while true do
|
|
||||||
local b,e,w = st:find('(%S+)')
|
|
||||||
if not b then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
table.insert(words, {
|
|
||||||
offset = b + offset - 1,
|
|
||||||
text = w,
|
|
||||||
})
|
|
||||||
offset = offset + e
|
|
||||||
st = st:sub(e + 1)
|
|
||||||
end
|
|
||||||
return words
|
|
||||||
end
|
|
||||||
|
|
||||||
local words = split(str)
|
|
||||||
for _,word in pairs(words) do
|
|
||||||
local tf = self.bridge.addText(self.x + word.offset * self.multiplier,
|
|
||||||
self.y+y*4, '', 0xffffff)
|
|
||||||
tf.setScale(self.textScale)
|
|
||||||
tf.setZ(1)
|
|
||||||
tf.setText(word.text)
|
|
||||||
table.insert(line.textFields, tf)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:setBackgroundBox(line.bg, x, x + #text - 1, y, bg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Glasses:clear(bg)
|
|
||||||
for _,line in pairs(self.t) do
|
|
||||||
for _,tf in pairs(line.textFields) do
|
|
||||||
tf.delete()
|
|
||||||
end
|
|
||||||
line.textFields = { }
|
|
||||||
line.text = string.rep(' ', self.width+1)
|
|
||||||
-- self.t[i].text.setText('')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function Glasses:reset()
|
|
||||||
self:clear()
|
|
||||||
self.bridge.clear()
|
|
||||||
self.bridge.sync()
|
|
||||||
end
|
|
||||||
|
|
||||||
function Glasses:sync()
|
|
||||||
self.bridge.sync()
|
|
||||||
end
|
|
||||||
|
|
||||||
return Glasses
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
--[[
|
|
||||||
Breed rabbits with a rabbit.
|
|
||||||
]]
|
|
||||||
|
|
||||||
local neural = require('neural.interface')
|
|
||||||
local Point = require('point')
|
|
||||||
local Sound = require('sound')
|
|
||||||
local Util = require('util')
|
|
||||||
|
|
||||||
local os = _G.os
|
|
||||||
|
|
||||||
local BREEDING = 'Rabbit'
|
|
||||||
local WALK_SPEED = 1.3
|
|
||||||
local MAX_GROWN = 100
|
|
||||||
local BREED_DELAY = 120
|
|
||||||
|
|
||||||
neural.assertModules({
|
|
||||||
'plethora:sensor',
|
|
||||||
'plethora:scanner',
|
|
||||||
'plethora:laser',
|
|
||||||
'plethora:kinetic',
|
|
||||||
'plethora:introspection',
|
|
||||||
})
|
|
||||||
|
|
||||||
local ID = neural.getID()
|
|
||||||
local fed = { }
|
|
||||||
|
|
||||||
local function resupply()
|
|
||||||
local slot = neural.getEquipment().list()[1]
|
|
||||||
if slot and slot.count > 32 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
print('resupplying')
|
|
||||||
|
|
||||||
local dispenser = Util.find(neural.scan(), 'name', 'minecraft:wooden_pressure_plate')
|
|
||||||
if dispenser then
|
|
||||||
if math.abs(dispenser.x) > 1 or math.abs(dispenser.z) > 1 then
|
|
||||||
neural.walkTo({ x = dispenser.x, y = 0, z = dispenser.z }, WALK_SPEED)
|
|
||||||
end
|
|
||||||
neural.lookAt(dispenser)
|
|
||||||
neural.getEquipment().suck(1, 64)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function breed(entity)
|
|
||||||
print('breeding')
|
|
||||||
entity.lastFed = os.clock()
|
|
||||||
fed[entity.id] = entity
|
|
||||||
|
|
||||||
neural.walkTo(entity, WALK_SPEED, .5)
|
|
||||||
entity = neural.getMetaByID(entity.id)
|
|
||||||
if entity and not entity.isChild then
|
|
||||||
neural.lookAt(entity)
|
|
||||||
neural.use(1)
|
|
||||||
os.sleep(.1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function kill(entity)
|
|
||||||
print('killing')
|
|
||||||
neural.walkTo(entity, WALK_SPEED, 2)
|
|
||||||
entity = neural.getMetaByID(entity.id)
|
|
||||||
if entity and not entity.isChild then
|
|
||||||
neural.lookAt(entity)
|
|
||||||
neural.fireAt({ x = entity.x, y = 0, z = entity.z })
|
|
||||||
Sound.play('entity.firework.launch')
|
|
||||||
os.sleep(.2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getEntities()
|
|
||||||
return Util.filter(neural.sense(), function(entity)
|
|
||||||
if entity.name == BREEDING and entity.y > -.5 and entity.id ~= ID then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function getHungry(entities)
|
|
||||||
for _,v in pairs(entities) do
|
|
||||||
if not fed[v.id] or
|
|
||||||
os.clock() - fed[v.id].lastFed > BREED_DELAY then
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function randomEntity(entities)
|
|
||||||
local r = math.random(1, Util.size(entities))
|
|
||||||
local i = 1
|
|
||||||
for _, v in pairs(entities) do
|
|
||||||
i = i + 1
|
|
||||||
if i > r then
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function dropOff()
|
|
||||||
print('dropping')
|
|
||||||
|
|
||||||
if neural.getEquipment().list()[2] then
|
|
||||||
local b = Util.find(neural.scan(), 'name', 'minecraft:hopper')
|
|
||||||
if b then
|
|
||||||
neural.walkTo({ x = b.x, y = 0, z = b.z }, 2)
|
|
||||||
|
|
||||||
b = Util.find(neural.scan(), 'name', 'minecraft:hopper')
|
|
||||||
if b and math.abs(b.x) < 1 and math.abs(b.z) < 1 then
|
|
||||||
print('dropped')
|
|
||||||
neural.getEquipment().drop(2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pickup(id)
|
|
||||||
local b = neural.getMetaByID(id)
|
|
||||||
if b then
|
|
||||||
neural.walkTo(b, 2)
|
|
||||||
|
|
||||||
local main = neural.getEquipment().list()[1]
|
|
||||||
local amount = neural.getEquipment().suck(not main and 2 or nil)
|
|
||||||
print('sucked: ' .. amount)
|
|
||||||
if amount > 0 then
|
|
||||||
Sound.play('entity.item.pickup')
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function drops()
|
|
||||||
local sensed = Util.reduce(neural.sense(), function(acc, s)
|
|
||||||
if Util.round(s.y) == 0 and s.name == 'Item' then
|
|
||||||
acc[s.id] = s
|
|
||||||
end
|
|
||||||
return acc
|
|
||||||
end, { })
|
|
||||||
|
|
||||||
local pt = { x = 0, y = 0, z = 0 }
|
|
||||||
while true do
|
|
||||||
local b = Point.closest(pt, sensed)
|
|
||||||
if not b then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
sensed[b.id] = nil
|
|
||||||
|
|
||||||
if pickup(b.id) then
|
|
||||||
pt = b
|
|
||||||
else
|
|
||||||
dropOff()
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
while true do
|
|
||||||
resupply()
|
|
||||||
|
|
||||||
local entities = getEntities()
|
|
||||||
|
|
||||||
if Util.size(entities) > MAX_GROWN then
|
|
||||||
kill(randomEntity(entities))
|
|
||||||
else
|
|
||||||
local entity = getHungry(entities)
|
|
||||||
if entity then
|
|
||||||
breed(entity)
|
|
||||||
else
|
|
||||||
print('sleeping')
|
|
||||||
os.sleep(5)
|
|
||||||
end
|
|
||||||
drops()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Reference in New Issue
Block a user