Last active
January 2, 2020 08:55
-
-
Save LexManos/d75263abbd339c0e8d8bdfa817033b1c to your computer and use it in GitHub Desktop.
Re-worked version of Computercraft control for Compact Machines.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- APIs | |
local robot = require("robot") | |
local component = require("component") | |
local computer = require("computer") | |
local me = component.upgrade_me | |
local db = component.database | |
local event = require("event") | |
local filesystem = require("filesystem") | |
local sides = require("sides") | |
local tunnel = component.tunnel | |
local inventory = component.inventory_controller | |
local recipes = { | |
wall = { | |
name = "Wall", | |
items = { | |
catalyst = {name = "minecraft:redstone", friendly = "Redstone Dust"}, | |
top = {name = "minecraft:redstone", friendly = "Redstone Dust"}, | |
bottom = {name = "minecraft:iron_block", friendly = "Iron Block" } | |
}, | |
style = "wall" | |
}, | |
tunnel = { | |
name = "Tunnel", | |
items = { | |
catalyst = {name = "minecraft:redstone", friendly = "Redstone Dust"}, | |
top = {name = "minecraft:hopper", friendly = "Hopper" }, | |
bottom = {name = "compactmachines3:wallbreakable", friendly = "Wall" }, | |
dust = {name = "minecraft:redstone", friendly = "Redstone Dust"} | |
}, | |
style = "tunnel" | |
}, | |
redTunnel = { | |
name = "Redsone Tunnel", | |
items = { | |
catalyst = {name = "minecraft:redstone", friendly = "Redstone Dust" }, | |
top = {name = "minecraft:redstone_block", friendly = "Redstone Block"}, | |
bottom = {name = "compactmachines3:wallbreakable", friendly = "Wall" }, | |
dust = {name = "minecraft:redstone", friendly = "Redstone Dust" } | |
}, | |
style = "tunnel" | |
}, | |
machine3 = { | |
name = "3x3 Machine", | |
items = { | |
catalyst = {name = "minecraft:ender_pearl", friendly = "Ender Pearl"}, | |
wall = {name = "compactmachines3:wallbreakable", friendly = "Wall" } | |
}, | |
style = "cube3" | |
}, | |
machine5 = { | |
name = "5x5 Machine", | |
items = { | |
catalyst = {name = "minecraft:ender_pearl", friendly = "Ender Pearl"}, | |
wall = {name = "compactmachines3:wallbreakable", friendly = "Wall" }, | |
core = {name = "minecraft:iron_block", friendly = "Iron Block" } | |
}, | |
style = "cube3" | |
}, | |
machine7 = { | |
name = "7x7 Machine", | |
items = { | |
catalyst = {name = "minecraft:ender_pearl", friendly = "Ender Pearl"}, | |
wall = {name = "compactmachines3:wallbreakable", friendly = "Wall" }, | |
core = {name = "minecraft:gold_block", friendly = "Gold Block" } | |
}, | |
style = "cube3" | |
}, | |
machine9 = { | |
name = "9x9 Machine", | |
items = { | |
catalyst = {name = "minecraft:ender_pearl", friendly = "Ender Pearl"}, | |
wall = {name = "compactmachines3:wallbreakable", friendly = "Wall" } | |
}, | |
style = "cube5" | |
}, | |
machine11 = { | |
name = "11x11 Machine", | |
items = { | |
catalyst = {name = "minecraft:ender_pearl", friendly = "Ender Pearl" }, | |
wall = {name = "compactmachines3:wallbreakable", friendly = "Wall" }, | |
core = {name = "minecraft:diamond_block", friendly = "Diamond Block"} | |
}, | |
style = "cube5" | |
}, | |
machine13 = { | |
name = "13x13 Machine", | |
items = { | |
catalyst = {name = "minecraft:ender_pearl", friendly = "Ender Pearl" }, | |
wall = {name = "compactmachines3:wallbreakable", friendly = "Wall" }, | |
core = {name = "minecraft:emerald_block", friendly = "Emerald Block"} | |
}, | |
style = "cube5" | |
} | |
} | |
-- Visuals | |
function skipLine(number) | |
for i = 1, number do | |
print("") | |
end | |
end | |
function printLoad(percent) | |
if percent == "0" then | |
os.execute("cls") | |
skipLine(8) | |
print(" Loading. 0%") | |
elseif percent == "25" then | |
os.execute("cls") | |
skipLine(8) | |
print(" Loading.. 25%") | |
elseif percent == "50" then | |
os.execute("cls") | |
skipLine(8) | |
print(" Loading.. 50%") | |
elseif percent == "75" then | |
os.execute("cls") | |
skipLine(8) | |
print(" Loading. 75%") | |
elseif percent == "100" then | |
os.execute("cls") | |
skipLine(8) | |
print(" Loading.. 100%") | |
end | |
end | |
function writeTitle() | |
print(" ███████████████████████████████████████") | |
print(" █_|___|___|___|___|___|___|___|___|___█") | |
print(" █___|__██████╗███╗___███╗██████╗_|___|█") | |
print(" █_|___██╔════╝████╗ ████║╚════██╗_|___█") | |
print(" █___|_██║___|_██╔████╔██║ █████╔╝|___|█") | |
print(" █_|___██║_|___██║╚██╔╝██║ ╚═══██╗_|___█") | |
print(" █___|_╚██████╗██║_╚═╝_██║██████╔╝|___|█") | |
print(" █_|___|╚═════╝╚═╝_|___╚═╝╚═════╝__|___█") | |
print(" █___A Compact Machines 3 Autobuilder_|█") | |
print(" █_|___|___|___By: Samir___|___|___|___█") | |
print(" ███████████████████████████████████████") | |
end | |
-- Wireless Mode | |
function getWirelessVariable() | |
local file = io.open("wirelessVariable","r") | |
if file:read() == "true" then | |
modeWireless = true | |
print("modeWireless = true") | |
else | |
modeWireless = nil | |
print("modeWireless = nil") | |
file:close() | |
end | |
end | |
function activateWireless() | |
local file=io.open("wirelessVariable","w") | |
file:write("true") | |
file:close() | |
end | |
function deactivateWireless() | |
local file=io.open("wirelessVariable","w") | |
file:write("nil") | |
file:close() | |
computer.shutdown(true) | |
end | |
-- Inventory Management | |
function totalItem(name) | |
local size = 0 | |
for i = 1,16 do | |
local data=inventory.getStackInInternalSlot(i) | |
if (data and data.name == name) then | |
size = size + data.size | |
end | |
end | |
return size | |
end | |
function selectItem(item) | |
for i = 1,16 do | |
local data = inventory.getStackInInternalSlot(i) | |
if (data and data.name == item.name) then | |
robot.select(i) | |
return true | |
end | |
end | |
return false | |
end | |
function findPartial(name, skip) | |
skip = skip or -1 | |
for i = 1,16 do | |
if (i ~= skip) then | |
local data = inventory.getStackInInternalSlot(i) | |
if (data and data.name == name and data.size ~= data.maxSize) then | |
return i | |
end | |
end | |
end | |
return -1 | |
end | |
function selectEmpty() | |
for i = 1,16 do | |
local data=inventory.getStackInInternalSlot(i) | |
if data == nil then | |
robot.select(i) | |
return | |
end | |
end | |
end | |
function emptyIntoME() | |
for i = 1,16 do | |
local data = inventory.getStackInInternalSlot(i) | |
if (data ~= nil) then | |
robot.select(i) | |
me.sendItems() | |
if (inventory.getStackInInternalSlot(i) ~= nil) then | |
return "Failed to store item in slot " .. i | |
end | |
end | |
end | |
return nil | |
end | |
-- Request Items | |
function requestItem(item, count) | |
count = count or 64 | |
local have = 0 --totalItem(item.name) | |
--[[ | |
if (have == count) then | |
return nil | |
end | |
--Send any extra we have back | |
while(have > count) | |
do | |
selectItem(item.name) | |
extra = math.min(have - count, robot.count()) | |
sent = me.sendItems(extra) | |
if (sent == 0) then | |
return "Could not store excess " .. item.friendly | |
end | |
have -= sent | |
end | |
--]] | |
while (have < count) | |
do | |
local slot = findPartial(item.name) | |
local request = math.min(count - have, 64) | |
if (slot == -1) then -- No Matching partial slot, so grab an empty | |
selectEmpty() | |
else | |
robot.select(slot) | |
local stack = inventory.getStackInInternalSlot(slot) | |
request = math.min(count - have, stack.maxSize - stack.size) | |
end | |
db.clear(1) | |
me.store({name = item.name}, db.address, 1) | |
local existing = me.getItemsInNetwork({name = item.name}) | |
if (db.get(1) == nil or existing.n == 0 or existing[1].size == 0) then | |
if (not tryCraftItem(item.name, count - have)) then | |
if (item.name == "compactmachines3:wallbreakable") then -- We can craft walls, so pop up how many we need | |
return math.ceil((count - have) / 16) | |
end | |
return "Could not craft " .. item.friendly | |
end | |
me.store({name = item.name}, db.address, 1) | |
end | |
if (db.get(1) == nil) then -- Something went fucky | |
return "Crafting " .. item.friendly .. " failed.. but ME said success" | |
end | |
--print("Requesting " .. request .. " " .. item.name) | |
local fetched = math.floor(me.requestItems(db.address, 1, request)) | |
if (fetched == 0) then -- We failed, bail out | |
return "Failed to fetch " .. item.friendly | |
end | |
have = have + fetched | |
--print("Got: " .. have .. "/" .. count .. " " .. item.friendly) | |
end | |
return nil | |
end | |
function tryCraftItem(name, count) | |
local crafts = me.getCraftables({name = name}) | |
if (crafts.n == 0) then | |
return false | |
end | |
local request = crafts[1].request(count) | |
while (not request.isDone() and not request.isCanceled()) | |
do | |
os.sleep(2) | |
end | |
return not request.isCanceled() | |
end | |
function requestWall(items) | |
local ret = requestItem(items.catalyst, 1) | |
ret = ret or requestItem(items.top, 1) | |
ret = ret or requestItem(items.bottom, 1) | |
return ret | |
end | |
function requestTunnel(items) | |
local ret = requestItem(items.catalyst, 1) | |
ret = ret or requestItem(items.dust, 8) | |
ret = ret or requestItem(items.top, 1) | |
ret = ret or requestItem(items.bottom, 1) | |
return ret | |
end | |
function requestMachine3(items) | |
local ret = requestItem(items.catalyst, 1) | |
ret = ret or requestItem(items.wall, 26) | |
if (ret == nil and items.core ~= nil) then | |
ret = requestItem(items.core, 1) | |
end | |
return ret | |
end | |
function requestMachine5(items) | |
local ret = requestItem(items.catalyst, 1) | |
ret = ret or requestItem(items.wall, 98) | |
if (ret == nil and items.core ~= nil) then | |
ret = requestItem(items.core, 1) | |
end | |
return ret | |
end | |
-- Movement Functions | |
function forward(dist, place) | |
for i = 1, dist do | |
if (not robot.forward()) then | |
if (i > 1) then | |
backSimple(i - 1) | |
end | |
return "Ran into something solid" | |
end | |
if (place ~= nil) then | |
if (not selectItem(place)) then | |
backSimple(i) | |
return "Ran out of " .. place.friendly | |
end | |
if (not robot.placeDown()) then | |
return "Failed to place " .. place.friendly | |
end | |
end | |
end | |
end | |
function forwardSimple(dist) | |
for i = 1, dist do | |
robot.forward() | |
end | |
end | |
function back(dist, place) | |
for i = 1, dist do | |
if (not robot.back()) then | |
if (i > 1) then | |
forwardSimple(i - 1) | |
end | |
return "Ran into something solid" | |
end | |
if (place ~= nil) then | |
if (not selectItem(place)) then | |
forward(i) | |
return "Ran out of " .. place.friendly | |
end | |
if (not robot.placeDown()) then | |
return "Failed to place " .. place.friendly | |
end | |
end | |
end | |
end | |
function backSimple(dist) | |
for i = 1, dist do | |
robot.back() | |
end | |
end | |
function up(dist, place) | |
for i = 1, dist do | |
if (not robot.up()) then | |
if (i > 1) then | |
downSimple(i - 1) | |
end | |
return "Ran into something solid" | |
end | |
end | |
end | |
function upSimple(dist) | |
for i = 1, dist do | |
robot.up() | |
end | |
end | |
function down(dist) | |
for i = 1, dist do | |
if (not robot.down()) then | |
if (i > 1) then | |
upSimple(i - 1) | |
end | |
return "Ran into something solid" | |
end | |
end | |
end | |
function downSimple(dist) | |
for i = 1, dist do | |
robot.down() | |
end | |
end | |
function right(dist, place) | |
robot.turnRight() | |
ret = forward(dist, place) | |
if (ret ~= nil) then | |
robot.turnLeft() | |
end | |
return ret | |
end | |
function left(dist, place) | |
robot.turnLeft() | |
ret = forward(dist, place) | |
if (ret ~= nil) then | |
robot.turnRight() | |
end | |
return ret | |
end | |
-- Craft Functions | |
function place(place) | |
if (place ~= nil) then | |
if (not selectItem(place)) then | |
return "Ran out of " .. place.friendly | |
end | |
if (not robot.placeDown()) then | |
return "Failed to place " .. place.friendly | |
end | |
end | |
return nil | |
end | |
function pickupResults(delay) | |
os.sleep(delay) -- Sleep during animation | |
down(6) | |
robot.suck() | |
forward(7) | |
robot.turnRight() | |
robot.turnRight() | |
return nil | |
end | |
function craftWall(name, items, verbose) | |
local ret = requestWall(items) | |
if (ret ~= nil) then | |
return ret | |
end | |
if (verbose ~= false) then | |
display("Constructing " .. name) | |
end | |
-- Move forward 6, so we don't go over the hopper in the center, in case people build it with a auto-collector | |
forward(6) | |
up(1) | |
forward(1, items.bottom) | |
up(1) | |
place(items.top) | |
up(4) | |
selectItem(items.catalyst) | |
robot.drop(1) | |
robot.turnRight() | |
robot.turnRight() | |
return pickupResults(5) | |
end | |
function craftMachine3(name, items) | |
local ret = requestMachine3(items) | |
if (ret ~= nil) then | |
if (tonumber(ret) ~= nil) then | |
local extra = tonumber(ret) | |
for i = 1,extra do | |
emptyIntoME() | |
if (extra >= 1) then | |
display("Crafting extra walls " .. i .. "/" .. extra) | |
end | |
ret = craftWall(recipes.wall.name, recipes.wall.items, false) | |
if (ret ~= nil) then | |
return ret | |
end | |
end | |
ret = requestMachine3(items) | |
if (ret ~= nil) then | |
return ret | |
end | |
else | |
return ret | |
end | |
end | |
display("Constructing " .. name) | |
-- Move into place, bottom left just outside of range, facing up | |
forward(5) | |
left(1) | |
robot.turnRight() | |
up(1) | |
-- Layer 1, Ends center facing up | |
forward(3, items.wall) | |
right(2, items.wall) | |
right(2, items.wall) | |
right(1, items.wall) | |
right(1, items.wall) | |
-- Layer 2, Ends top left facing up | |
up(1) | |
place(items.core) | |
forward(1, items.wall) | |
right(1, items.wall) | |
right(2, items.wall) | |
right(2, items.wall) | |
right(3, items.wall) | |
-- Layer 3, Ends center, facing right | |
up(1) | |
place(items.wall) | |
right(2, items.wall) | |
right(2, items.wall) | |
right(2, items.wall) | |
right(1, items.wall) | |
right(1, items.wall) | |
-- Fly out of region | |
up(3) | |
selectItem(items.catalyst) | |
robot.drop(1) | |
robot.turnRight() | |
return pickupResults(24) | |
end | |
function craftMachine5(name, items) | |
local ret = requestMachine5(items) | |
if (ret ~= nil) then | |
if (tonumber(ret) ~= nil) then | |
local extra = tonumber(ret) | |
for i = 1,extra do | |
emptyIntoME() | |
if (extra >= 1) then | |
display("Crafting extra walls " .. i .. "/" .. extra) | |
end | |
ret = craftWall(recipes.wall.name, recipes.wall.items, false) | |
if (ret ~= nil) then | |
return ret | |
end | |
end | |
ret = requestMachine5(items) | |
if (ret ~= nil) then | |
return ret | |
end | |
else | |
return ret | |
end | |
end | |
display("Constructing " .. name) | |
-- Move into place, bottom left just outside of range, facing up | |
forward(4) | |
robot.turnLeft() | |
forward(2) | |
robot.turnRight() | |
up(1) | |
-- Layer 1, Ends top right facing up | |
forward(5, items.wall) | |
right(1, items.wall) | |
right(4, items.wall) | |
left(1, items.wall) | |
left(4, items.wall) | |
right(1, items.wall) | |
right(4, items.wall) | |
left(1, items.wall) | |
left(4, items.wall) | |
-- Layer 2, Ends top right facing up | |
up(1) | |
place(items.wall) | |
left(4, items.wall) | |
left(4, items.wall) | |
left(4, items.wall) | |
left(3, items.wall) | |
forward(1) | |
-- Layer 3, Ends top right facing up | |
up(1) | |
place(items.wall) | |
left(2, items.wall) | |
if (items.core ~= nil) then | |
left(2) | |
place(items.core) | |
robot.turnLeft() | |
robot.turnLeft() | |
forward(2) | |
robot.turnLeft() | |
end | |
forward(2, items.wall) | |
left(4, items.wall) | |
left(4, items.wall) | |
left(3, items.wall) | |
forward(1) | |
-- Layer 4, Ends top right facing up | |
up(1) | |
place(items.wall) | |
left(4, items.wall) | |
left(4, items.wall) | |
left(4, items.wall) | |
left(3, items.wall) | |
forward(1) | |
-- Layer 5, Ends center facing left | |
up(1) | |
place(items.wall) | |
left(4, items.wall) | |
left(4, items.wall) | |
left(4, items.wall) | |
left(3, items.wall) | |
left(3, items.wall) | |
left(2, items.wall) | |
left(2, items.wall) | |
left(1, items.wall) | |
left(1, items.wall) | |
-- Go out of region, and toss catalyst | |
up(1) | |
selectItem(items.catalyst) | |
robot.drop(1) | |
robot.turnLeft() | |
return pickupResults(33) | |
end | |
function craftTunnel(name, items) | |
local ret = requestTunnel(items) | |
if (ret ~= nil) then | |
if (tonumber(ret) ~= nil) then | |
local extra = tonumber(ret) | |
for i = 1,extra do | |
emptyIntoME() | |
if (extra >= 1) then | |
display("Crafting extra walls " .. i .. "/" .. extra) | |
end | |
ret = craftWall(recipes.wall.name, recipes.wall.items, false) | |
if (ret ~= nil) then | |
return ret | |
end | |
end | |
ret = requestTunnel(items) | |
if (ret ~= nil) then | |
return ret | |
end | |
else | |
return ret | |
end | |
end | |
display("Constructing " .. name) | |
--Move into place, Bottom left, just outside, facing up | |
forward(5) | |
left(1) | |
robot.turnRight() | |
up(1) | |
-- Layer 1, Center facing up | |
forward(3, items.dust) | |
right(2, items.dust) | |
right(2, items.dust) | |
right(1, items.dust) | |
right(1, items.bottom) | |
--Place Top, But can be hopper so can't move above it, as it'll steal our catalyst | |
back(1) | |
selectItem(items.top) | |
robot.place(sides.down) | |
--Fly out of region | |
up(5) | |
forward(1) | |
selectItem(items.catalyst) | |
robot.drop(1) | |
robot.turnRight() | |
robot.turnRight() | |
return pickupResults(10) | |
end | |
-- Command Line Arguments | |
function validRecipes() | |
local tmp = {} | |
local n = 0 | |
for k,v in pairs(recipes) do | |
n = n + 1 | |
tmp[n] = k | |
end | |
table.sort(tmp) | |
local ret = "" | |
for k,v in pairs(recipes) do | |
ret = ret .. k .. ", " | |
end | |
if (ret ~= "") then | |
ret = ret:sub(1, ret:len() - 2) | |
end | |
return ret | |
end | |
function commandLineArgs() | |
local continue = true | |
while(continue) do | |
skipLine(1) | |
print(" What would you like to build?") | |
print(validRecipes()) | |
continue = process(string.lower(io.read())) | |
end | |
end | |
function wirelessArgs() | |
local continue = true | |
while(continue) do | |
skipLine(1) | |
print(" Wireless Mode") | |
_, _, _, _, _, message = event.pull("modem_message") | |
continue = process(string.lower(message)) | |
end | |
end | |
function process(cmd) | |
local words = {} | |
local size = 0 | |
for word in cmd:gmatch("%S+") do | |
table.insert(words, word) | |
size = size + 1 | |
end | |
local count = 1 | |
local recipe = recipes[words[1]] | |
if (size == 2 and tonumber(words[2]) ~= nil and recipe ~= nil) then | |
count = tonumber(words[2]) | |
display("Creating " .. count .. " " .. recipe.name) | |
end | |
for i = 1,count do | |
if (count ~= 1) then | |
display("Run " .. i .. "/" .. count) | |
end | |
local ret = nil | |
if (recipe == nil) then | |
if (words[1] == "wirelesson") then | |
activateWireless() | |
elseif (words[1] == "wirelessoff") then | |
deactivateWireless() | |
end | |
elseif (recipe.style == "wall") then | |
ret = craftWall(recipe.name, recipe.items) | |
elseif (recipe.style == "tunnel") then | |
ret = craftTunnel(recipe.name, recipe.items) | |
elseif (recipe.style == "cube3") then | |
ret = craftMachine3(recipe.name, recipe.items) | |
elseif (recipe.style == "cube5") then | |
ret = craftMachine5(recipe.name, recipe.items) | |
else | |
ret = "Invalid recipe style: " .. recipe.style | |
end | |
emptyIntoME() | |
if (ret ~= nil) then | |
display(ret) | |
return false | |
end | |
end | |
return true | |
end | |
-- Start Program | |
function writeShell() | |
local shell = io.open(".shrc","w") | |
shell:write("/home/CM3.lua") | |
shell:close() | |
end | |
function createWirelessVariable() | |
if not filesystem.exists("/home/wirelessVariable") then | |
local file = io.open("wirelessVariable","w") | |
file:write("") | |
file:close() | |
end | |
end | |
function startProgram() | |
os.execute("cls") | |
local ret = emptyIntoME() | |
if (ret ~= nil) then | |
display(ret) | |
return | |
end | |
writeTitle() | |
if (modeWireless) then | |
tunnel.send("on") | |
--wirelessArgs() | |
commandLineArgs() | |
else | |
tunnel.send("off") | |
commandLineArgs() | |
end | |
end | |
function display(message) | |
print(message) | |
if (modeWireless) then | |
tunnel.send("print " .. message) | |
end | |
end | |
writeShell() | |
createWirelessVariable() | |
getWirelessVariable() | |
startProgram() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment