Posted 29 April 2015 - 04:30 PM
This API can be used to craft items. It automatically learns recipes when you craft a new item using turtle.craft, and also has functions for crafting items and acting as an automatic crafting table.
download now! Run "pastebin get hyTQn7Rj api".
Here is the script source:
download now! Run "pastebin get hyTQn7Rj api".
Here is the script source:
----------------------------
-- Crafting API by Tag365 --
----------------------------
tCraftingTable = {1, 2, 3, 5, 6, 7, 9, 10, 11} -- This is the slots used for crafting.
local tItemSlotsToDrop = {} -- This is used to determine which slots are not part of the crafting table to prevent other items from interfering from the list.
local tCraftingRecipes = {} -- The table holds recipes for items.
nOutputSlot = 8 -- The final location of the crafted item.
local loops = 0 -- This is used to determine when to print that the turtle is missing an item.
local firstSlotEmpty = 0
local currentRecipe = {}
local tCraftCompletion = {}
local turtleCraft = turtle.craft
recipes = tCraftingRecipes
saveLocation = "recipes.list" -- This is the path where the recipe table will be stored.
-- Functions --
-- Downloads the recipes from the server.
function updateRecipesFromServer()
local url = "http://pastebin.com/raw.php?i=6gCgiaPg"
if http then
local hRecipes = http.get(url)
local str = hRecipes.readAll()
hRecipes.close()
ok, tCraftingRecipes = pcall(textutils.unserialize, str)
end
end
-- Saves the recipe list.
function saveRecipeList()
local ok, str = pcall(textutils.serialize, tCraftingRecipes)
if not ok then
return false, str
end
local hFile = fs.open(saveLocation, "w")
if hFile then
hFile.write(str)
hFile.close()
return true
end
return false
end
-- Loads the recipe list.
function loadRecipeList()
local hFile, ok = fs.open(saveLocation, "r")
if hFile then
local str = hFile.readAll()
hFile.close()
ok, tCraftingRecipes = pcall(textutils.unserialize, str)
if type(tCraftingRecipes) ~= "table" then
tCraftingRecipes = {}
end
return ok
end
return false
end
-- Adds a new recipe to the table.
function addNewRecipe(sItemName, nItemsGenerated, bIsShapeless, tResources)
if type(bIsShapeless) == "nil" and type(tResources) == "nil" then
tResources = nItemsGenerated
bIsShapeless = false
nItemsGenerated = 1
elseif type(tResources) == "nil" then
tResources = bIsShapeless
bIsShapeless = false
nItemsGenerated = 1
end
if type(sItemName) ~= "string" then
error("bad argument #1 for addNewRecipe: string expected, got "..type(sItemName), 2)
end
if type(nItemsGenerated) ~= "number" then
local newItemsGenerated = tonumber(nItemsGenerated)
if type(nItemsGenerated) ~= "number" then
error("bad argument #2 for addNewRecipe: number expected, got "..type(nItemsGenerated), 2)
end
nItemsGenerated = newItemsGenerated
end
if not tCraftingRecipes[sItemName] then
tCraftingRecipes[sItemName] = {}
end
tCraftingRecipes[sItemName][#tCraftingRecipes[sItemName] + 1] = {}
local tRecipe = tCraftingRecipes[sItemName][#tCraftingRecipes[sItemName]]
tRecipe["ItemsGenerated"] = nItemsGenerated
tRecipe["IsShapeless"] = bIsShapeless
for k, v in pairs(tResources) do
if not type(v) == "table" then
error("bad argument #4 for addNewRecipe: multidimensional table expected, got "..type(v).." in item #"..k, 2)
end
tRecipe[k] = v
end
saveRecipeList()
end
function updateFirstSlotEmpty()
firstSlotEmpty = false
for k, v in ipairs(tItemSlotsToDrop) do
if turtle.getItemCount(v) == 0 then
firstSlotEmpty = k
break
end
end
if not firstSlotEmpty then
if not turtle.detectUp() then
print("Warning: The turtle's inventory has filled up and the script has dropped items in the air. Items may be lost if left unattended.")
end
for k, v in ipairs(tItemSlotsToDrop) do
selectSlot(v)
turtle.dropUp(64)
end
slotsFilled = 0
end
end
-- Selects a slot if it is not the selected slot.
function selectSlot(slot)
if turtle.getSelectedSlot() ~= slot then
turtle.select(slot)
end
end
-- Moves an item from the crafting grid to the inventory.
function moveToInventory(slot, amount)
updateFirstSlotEmpty()
local remAmount = amount or turtle.getItemCount(slot) - 1
selectSlot(slot)
for k, v in ipairs(tItemSlotsToDrop) do
if turtle.compareTo(v) then
local added = math.min(turtle.getItemSpace(v) or 4, remAmount)
turtle.transferTo(v, added)
remAmount = remAmount - added
if remAmount <= 0 then
return
end
end
end
if tItemSlotsToDrop[firstSlotEmpty] then
turtle.transferTo(tItemSlotsToDrop[firstSlotEmpty], math.min(turtle.getItemSpace(v), remAmount))
end
end
-- Moves an item from the inventory to the crafting grid.
function moveFromInventory(slot, item, amount)
local remAmount = amount or 1
item = item or turtle.getItemDetail(slot)
for k, v in ipairs(tItemSlotsToDrop) do
local tCurrentItem = turtle.getItemDetail(v)
if tCurrentItem then
if tCurrentItem["name"] ~= item["name"] and tCurrentItem["name"] ~= item[1] then
elseif tCurrentItem["damage"] ~= item["damage"] and tCurrentItem["damage"] ~= item[2] then
else
selectSlot(v)
local added = math.min(turtle.getItemSpace(slot) or 1, remAmount)
turtle.transferTo(slot, added)
remAmount = remAmount - added
if remAmount <= 0 then
return true, 0
end
end
end
end
return false, remAmount
end
-- Checks if an item is the correct item.
function checkCraftingSlot(k, v)
loops = loops + 1
if loops == 100 then
print("Waiting for item #"..k.." to be given...")
end
if turtle.getItemCount(v) == 0 then
if currentRecipe[k][1] == "" then
return true
else
selectSlot(v)
if not moveFromInventory(v, currentRecipe[k], 1) then
turtle.suck(1)
end
end
elseif turtle.getItemCount(v) > 1 then
moveToInventory(v)
end
if currentRecipe[k][1] == "" then
moveToInventory(v, 64)
return true
end
local tCurrentItem = turtle.getItemDetail(v)
if tCurrentItem then
if currentRecipe[k][1] == "" then
moveToInventory(v, 64)
return true
elseif tCurrentItem["name"] ~= currentRecipe[k][1] then
elseif currentRecipe[k][2] and tCurrentItem["damage"] ~= currentRecipe[k][2] then
else
return true
end
end
moveToInventory(v, 64)
turtle.suck(64)
return false
end
-- When all items are available this function will break the while loop in craftItems.
function craftingNotComplete()
for k, v in ipairs(tCraftCompletion) do
if v ~= true then
return true
end
end
return false
end
-- When called this turtle will craft a recipe
function craftItems(sItemName, nRecipeUsed, nItemsToCraft, nTurnTimes)
nRecipeUsed = nRecipeUsed or 1
nItemsToCraft = nItemsToCraft or 1
nTurnTimes = nTurnTimes or 0
local errLevel = 2
if nItemsToCraft == -1 then errLevel = 3 end
if not tCraftingRecipes[sItemName] then
error("to craft '"..sItemName.."' you must first craft it using turtle.craft, or use crafting.addNewRecipe to add a recipe to the table.", errLevel)
elseif not tCraftingRecipes[sItemName][nRecipeUsed] then
nRecipeUsed = 1
end
currentRecipe = tCraftingRecipes[sItemName][nRecipeUsed]
for k=1, 9 do
tCraftCompletion[k] = false
end
if #tItemSlotsToDrop == 0 then
local addToTable = true
for k=1, 16 do
addToTable = true
for k2, v in pairs(tCraftingTable) do
if k == v then
addToTable = false
break
end
end
if addToTable then
tItemSlotsToDrop[#tItemSlotsToDrop + 1] = k
end
end
end
local advance = false
local loops = 0
local firstSlotEmpty = 0
while nItemsToCraft > 0 do
loops = 0
while craftingNotComplete() do
for k, v in ipairs(tCraftingTable) do
if not currentRecipe[k] then
currentRecipe[k] = {""}
end
tCraftCompletion[k] = checkCraftingSlot(k, v)
sleep()
end
end
for k, v in ipairs(tItemSlotsToDrop) do
if turtle.getItemCount(v) > 0 then -- This doesn't belong here according to ComputerCraft, so it needs to go.
turtle.select(v)
turtle.drop(64)
end
end
turtle.select(nOutputSlot)
local itemsGenerated = currentRecipe["ItemsGenerated"] or 1
if turtle.craft(nItemsToCraft) then
if nTurnTimes > 0 then
for k=1, nTurnTimes do
turtle.turnRight()
end
else
for k=1, nTurnTimes do
turtle.turnLeft()
end
end
nItemsToCraft = nItemsToCraft - turtle.getItemCount(nOutputSlot)
turtle.drop(64)
if nTurnTimes > 0 then
for k=1, nTurnTimes do
turtle.turnLeft()
end
else
for k=1, nTurnTimes do
turtle.turnRight()
end
end
end
sleep()
while turtle.suckUp(64) do
turtle.drop(64)
end
end
end
-- When called the turtle turns into an automatic crafting table that crafts the item you want.
function autoCraftingTable(sItemName, nRecipeUsed, nTurnTimes)
local advance = false
while true do
craftItems(sItemName, nRecipeUsed, -1, nTurnTimes)
end
end
-- Returns the full item name of an already available item.
function getFullItemName(sItemNameSub)
for k, v in pairs(tCraftingRecipes) do
if string.find(string.lower(k), string.lower(sItemNameSub)) then
return k
end
end
return false
end
-- Override the turtle.craft function with one that teaches the turtle a recipe.
function turtle.craft(amount)
amount = amount or 64
local tItemsInCraftingGrid = {}
for k, v in ipairs(tCraftingTable) do
local item = turtle.getItemDetail(v)
if item then
tItemsInCraftingGrid[k] = {[1] = item["name"], [2] = item["damage"]}
else
tItemsInCraftingGrid[k] = {""}
end
end
if turtleCraft(math.min(amount, 64)) then
if turtle.getItemDetail(turtle.getSelectedSlot()) then
local item = turtle.getItemDetail(turtle.getSelectedSlot())
if not tCraftingRecipes[item["name"]] then
addNewRecipe(item["name"], 1, false, tItemsInCraftingGrid)
end
end
end
end
-- Load the local recipes from the hard disk, or download the recipes from the server if possible.
if not loadRecipeList() then
updateRecipesFromServer()
end
Edited on 01 May 2015 - 10:44 PM