-- API to get information about the essentia jars you have around your infusion altar.

-- This is based on the automation Direwolf20 made in Server Play S6E21.

--

-- You need to hook up each warded jar to a Peripheral Proxy. Connect the

-- proxy to wired modem and connect it with wires to a wired modem connected

-- to your computer. Turn on all the modems.

--

-- To download this API:

--

-- > pastebin get sksenKPP essentia

--

-- Then you can load this API in other scripts. This API only gives you information

-- about what's in your jars. This API does not do the refilling for you.

--

-- Usage:

--

-- -- Load the API

-- os.loadAPI("essentia")

--

-- -- Get a list of all the jars

-- local jars = essentia.all()

--

-- -- Show the amount of terra:

-- print(jars:getAmountByName("terra"))

--

-- Most functions you can call on the jars collection are a bit functional in nature,

-- meaning you need to provide a function as parameter to another function.

--

-- Example: get all the empty jars:

--

-- jars:select(function(jar)

-- return jar:isEmpty()

-- end)

--

-- A couple of functions will return a new collection.

-- This means you can "chain" functions after eachother.

--

-- Example: get the names of the aspects with more than 10 and less then 40:

--

-- almostEmpty = function(jar) return jar:getAmount() < 10 end

-- almostFull = function(jar) return jar:getAmount() > 40 end

-- names = jars:reject(almostEmpty):reject(almostFull):collect("getName")

--

-- Important: jars do not calculate things on the fly. So if you want to

-- get the most up to date information, you need to refresh:

--

-- jars:refresh()

--

-- This will not detect new jars. To get new jars, you'll need to get a new list:

--

-- while true do

-- jars = essentia.all()

-- sleep(10)

-- end

--

-- Note: As you might have noticed, you need a colon (":") when accessing functions

-- on the jars collection or on individual jars. Don't forget them :)

function all ( )

local found = { }

local ids = peripheral . getNames ( )

for key , id in pairs ( ids ) do

local jar = Jar . new ( id )

if jar : isJar ( ) then

table.insert ( found , jar )

end

end

return Essentia . new ( found )

end

Essentia = { }

Essentia . __index = Essentia

function Essentia . new ( jars )

local self = setmetatable ( { } , Essentia )

self . jars = jars

self . type = "Essentia"

return self

end

-- Refreshes the jars, making them get new information.

function Essentia : refresh ( )

self : each ( function ( jar )

jar : refresh ( )

end )

end

-- Selects the jars that fit a certain criteria, that you'll need to provide in

-- the form of a function. The function will receive one argument: the jar.

-- When the function returns true, that jar will be part of the new collection.

--

-- Example: get all the jars that are full:

--

-- jars:select(function(jar)

-- return jar:getAmount() == 64

-- end)

function Essentia : select ( fn )

local found = { }

self : map ( function ( jar )

if fn ( jar ) then

table.insert ( found , jar )

end

end )

return self . new ( found )

end

-- Opposite of Essentia:select.

--

-- If the function returns true, it will *not* be part of the new collection.

function Essentia : reject ( fn )

return select ( function ( jar )

return not fn ( jar )

end )

end

-- Do something with each jar,

-- while still returning the original list of jars.

--

-- Example: print all aspect names with the amounts:

--

-- jars:each(function(jar)

-- print(jar:inspect())

-- end)

function Essentia : each ( fn )

self : map ( fn )

return self

end

-- Get a property of each jar. Provide the name of the function.

--

-- Example: get a list of all aspect names:

--

-- aspectNames = jars:collect("getName")

function Essentia : collect ( methodName )

local result = { }

self : map ( function ( jar )

table.insert ( result , jar [ methodName ] ( ) )

end )

return result

end

-- Finds only one jar. This means that if you have multiple jars that match the condition you provided,

-- it will just pick one (no guarantees which one) and ignore the rest.

--

-- You need to provide a function that returns true for the jar you'd wish to find.

--

-- Example: find an empty jar:

--

-- jar = jars:find(function(jar)

-- return jar:isEmpty()

-- end

-- jar:getName()

function Essentia : find ( fn )

for key , jar in pairs ( self . jars ) do

if fn ( jar ) then

return jar

end

end

end

-- Transforms the collection into a new kind of collection.

--

-- Example: get a list of aspect names with uppercase:

--

-- aspectNames = jars:map(function(jar)

-- return jar:getName():gsub("^%l", string.upper)

-- end)

--

-- Note: this example can be shortened to:

--

-- aspectNames = jars:collect("prettyName")

function Essentia : map ( fn )

local result = { }

for key , jar in pairs ( self . jars ) do

table.insert ( result , fn ( jar ) )

end

return result

end

-- Performs a reduce. Useful for summing up.

-- Provide an initial value and a function to apply.

--

-- Example: Get the sum of all amounts in jars:

--

-- total = jars:reduce(0, function(count, jar)

-- return count + jar:getAmount()

-- end)

function Essentia : reduce ( initial , fn )

local accumulator = initial

self : each ( function ( jar )

accumulator = fn ( accumulator , jar )

end )

return accumulator

end

-- Get the amount of essentia hooked up, given its name.

-- If you have multiple jars with the same aspect in them, it will sum them up.

--

-- Example:

--

-- jars:getAmountByName("terra")

function Essentia : getAmountByName ( name )

return self : selectByName ( name ) : reduce ( 0 , function ( count , jar )

return count + jar : getAmount ( )

end )

end

-- Finds only one jar by its name. This means that if you have multiple jars with the

-- same aspect in them, it will just pick one (no guarantees which one) and ignore the rest.

--

-- Example:

--

-- jar = jars:findByName("terra")

-- jar:getAmount()

function Essentia : findByName ( name )

self : find ( function ( jar )

return jar . hasName ( name )

end )

end

-- Get all the jars by their name.

--

-- Example:

--

-- terra = jars:selectByName("terra")

-- amounts = terra:collect("getAmount")

function Essentia : selectByName ( name )

return self : select ( function ( jar )

return jar : hasName ( name )

end )

end

-- Sort the jars, giving your own sort function.

--

-- Example: sort by number of aspects:

--

-- jars:sort(function(a, b)

-- return a:getAmount() < b:getAmount()

-- end)

--

-- To sort in the other direction, simply switch the comparitor.

function Essentia : sort ( fn )

table.sort ( self . jars , fn )

return self

end

-- Sort by name.

-- See Essentia:sort to sort in a different way.

-- Note: sorting is done via prettyName, so empty jars and void jars also sort properly.

function Essentia : sortByName ( )

self : sort ( function ( a , b )

return a : prettyName ( ) < b : prettyName ( )

end )

return self

end

-- class Jar

Jar = { }

Jar . __index = Jar

function Jar . new ( id )

local self = setmetatable ( { } , Jar )

self . id = id

self : refresh ( )

return self

end

-- Refresh the information. Run this whenever you

-- want to check the current situation.

function Jar : refresh ( )

self . peripheral = peripheral . wrap ( self . id )

self . type = self : fetchType ( )

if self : isJar ( ) then

self . name = self : fetchName ( )

self . amount = self : fetchAmount ( )

end

end

-- Returns the name of the aspect stored in this jar.

-- Returns nil if there is nothing in it.

function Jar : getName ( )

return self . name

end

-- The technical type of the peripheral

function Jar : getType ( )

return self . type

end

-- Returns the amount of essence in the jar.

-- Returns zero when nothing is in the jar.

function Jar : getAmount ( )

return self . amount

end

-- Helper method to check for the name.

function Jar : hasName ( name )

return self : getName ( ) == string.lower ( name )

end

-- Checks if the jar is a real jar.

function Jar : isJar ( )

return ( self : isWardedJar ( ) or self : isVoidJar ( ) )

end

-- Returns the capitalized name ("Terra" in stead of "terra")

function Jar : prettyName ( )

local name = self : getName ( )

if name then

return name : gsub ( "^%l" , string.upper )

else

return "[EMPTY]"

end

end

-- Returns true when there is 64 essence it

function Jar : isFull ( )

return self : getAmount ( ) == 64

end

-- Returns true if there is nothing in the jar.

function Jar : isEmpty ( )

return self : getAmount ( ) == 0

end

-- Returns a human readable version of what's in the jar.

function Jar : inspect ( )

return self : prettyName ( ) .. ": " .. self : getAmount ( )

end

-- Returns true if the jar is a void jar.

function Jar : isVoidJar ( )

return self : getType ( ) == "tilejarvoid"

end

-- Returns true if the jar is a normal jar, not a void jar.

function Jar : isWardedJar ( )

return self : getType ( ) == "tt_aspectContainer"

end

-- Fetches up to date name of the aspect stored

function Jar : fetchName ( )

if self : isWardedJar ( ) then

return self . peripheral . getAspects ( )

else

local aspects = self . peripheral . getAspects ( )

if aspects and aspects [ 1 ] then

return string.lower ( aspects [ 1 ] . name )

end

end

end

-- Fetches up to date type of the aspect stored

function Jar : fetchType ( )

return peripheral . getType ( self . id )

end

-- Fetches up to date amount of the aspect stored

function Jar : fetchAmount ( )

local name = self : getName ( )

if name then

local count = self . peripheral . getAspectCount ( name )

return math.floor ( count )

else

return 0

end