This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
ShadowGar's profile picture

Can you identify this API or its replacement?

Started by ShadowGar, 10 December 2013 - 10:13 PM
ShadowGar #1
Posted 10 December 2013 - 11:13 PM
I'm working on updating multiple programs and one that I am working on checks multiple MFSU's with a sensor turtle and outputs this data to a monitor. One piece of code refers to a apis/util API.


local function scanForData(newData)
	    local dataFound = false
	    local targets = sensor.getTargets()
	    local foundTarget = false
	    if targets then					   
			    for targetId, target in pairs(targets) do					 
					    local position = util.strsplit(",", targetId)
					    if target.type == "MFSU" and util.inBounds(config.volume, tonumber(position[1]), tonumber(position[2]), tonumber(position[3])) then
							    local targetStats = sensor.getTargetDetails(targetId)
							    if targetStats then
									    dataFound = true
									    table.insert(newData.mfsus, targetStats)
									    newData.capacity = newData.capacity + targetStats.Capacity
									    newData.stored = newData.stored + targetStats.Stored
									    newData.maxOutput = newData.maxOutput + targetStats.Output
							    end
					    end
			    end
	    end
	    return dataFound
end


1. util.strsplit
2.util.inbounds

Can anyone tell me the replacement for these? This same API was using utl.round which is being replaced by math.floor
Thank you :)/>
theoriginalbit #2
Posted 10 December 2013 - 11:31 PM
what is the program that you got these from? it clearly makes use of a "util" api… you can take a look in that for what each function does…

Also do note that math.floor is not the same as rounding, it will always round down to the nearest whole integer.
Grim Reaper #3
Posted 10 December 2013 - 11:43 PM
The split string utility might look something like this:

function splitString (_string, pattern)
    local occurrences = {}
          pattern     = "[^" .. pattern .. "]+"

    for occurrence in _string:gmatch (pattern) do
        occurrences[#occurrences + 1] = occurrence
    end

    return occurrences
end
, but the inBounds function needs a little more clarification if we're to recreate it.

Like theoriginalbit suggested, these functions sound defined by someone else and therefore can be definitely be found in whatever file the utils api is loaded from.
ShadowGar #4
Posted 11 December 2013 - 12:24 PM
Thank you for the reply. :)/>

Here is a little more info. I found these config files on an old YouTube video here hxxp://www.youtube.com/watch?v=sy7rtCq6Z0A

The entire file is here http://pastebin.com/MLMYLcX2

I've tried to contact the writer of this and have not received a response I've tried to hunt down this util API and after myself and three others have spent days looking through API's I'm lost.

So I figured, how about replacing the original API With something else. I will implement that splt string and see what comes of that. With inbound, I figured it was custom but was hoping he had atleast put the code somewere online.

One last piece of info, I'm updating this code to run on 1.5.2 servers with CC, openCC and miscP

I hope some of that information helps.
theoriginalbit #5
Posted 11 December 2013 - 07:29 PM
Looks like you're going to have a lot of problems modifying and removing quite a lot of those calls that he's got to all over the place, with what seems like a lot of scripts he never supplied too.

Still no clue what the actual intention of the inbounds function call is, like it seems that he's comparing the volume to its location for some reason, as to why, who knows.

is there a reason you did that with xx instead of tt?
Grim Reaper #6
Posted 11 December 2013 - 08:14 PM
If I had to guess from what he's doing in the video, the inBounds function is checking if the coordinates returned by the proximity sensor are within the bounds of a table of values. I'm not familiar with CCSensors so I don't really know how the proximity sensor works, but here is my guess according to what I saw in the video for his door code.


--[[
    Checks if the given x, y, and z coordinates are in bounds
    of the given bound box.

    Bound boxes of the format:
        {
            yStart = n, yEnd = n,
            xStart = n, xEnd = n,
            zStart = n, zEnd = n
        }
]]
function inBounds (boundBox, xPos, yPos, zPos)
    return xPos >= boundBox.xStart and xPos <= boundBox.xEnd and
           yPos >= boundBox.yStart and yPos <= boundBox.yEnd and
           zPos >= boundBox.zStart and zPos <= boundBox.zEnd
end
ShadowGar #7
Posted 11 December 2013 - 09:21 PM
With some luck I found the code. This is the Utl API

local util = {}
function util.strsplit(delimiter, text)
	local list = {}
	local pos = 1
	while true do
		local first, last = text:find(delimiter, pos)
		if first then -- found?
			table.insert(list, text:sub(pos, first-1))
			pos = last+1
		else
			table.insert(list, text:sub(pos))
			break
		end
	end
	return list
end
function util.commavalue(n)
	local left,num,right = string.match(n,'^([^%d]*%d)(%d*)(.-)$')
	return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right
end
function util.round (number, precision)
	precision = precision or 0
	local decimal = string.find(tostring(number), ".", nil, true);
  
	if ( decimal ) then
		local power = 10 ^ precision;
	  
		if ( number >= 0 ) then
			number = math.floor(number * power + 0.5) / power;
		else
			number = math.ceil(number * power - 0.5) / power;	  
		end
	  
		-- convert number to string for formatting
		number = tostring(number);		
	  
		-- set cutoff
		local cutoff = number:sub(decimal + 1 + precision);
		  
		-- delete everything after the cutoff
		number = number:gsub(cutoff, "");
	else
		-- number is an integer
		if ( precision > 0 ) then
			number = tostring(number);
		  
			number = number .. ".";
		  
			for i = 1,precision
			do
				number = number .. "0";
			end
		end
	end	
	return number;
end
function util.inBounds(volume, x, y, z)
	return (x <= volume.xEnd and x >= volume.xStart and y <= volume.yEnd and y >= volume.yStart and z <= volume.zEnd and z >= volume.zStart)
end
return util

So Now I got two of the programs working. The reactor turtle and the Monitor.
Now I'm on to the Cooling Turtle.

So my next question is, he used Item Analyzer addon which is no longer used. Is it possible to use the inventory Sensor card to look into chests and reactors and check metadata and then pull and push into those slots?

This is the code for the cooling turtle. I cant find much code for using the inventory sensor.

ocal util = api.require("util")
local analyzer = peripheral.wrap("left")
rednet.open("right")

local reactorSize = 54
local condensatorBlockId = 30083
local condensatorBlocks = {}
local reactorMonitorId = nil
local reactorStatus = "OFFLINE"
local coolingStatus = "OFFLINE"
local condensatorsReplaced = 0
local statsSystemId = nil

local function sendStatus()
		if reactorMonitorId then
				rednet.send(reactorMonitorId, textutils.serialize{type="reactor", sender="cooling", command="status", status=coolingStatus})
		end
end

local function stopSystem()
		if reactorMonitorId then
				coolingStatus = "OFFLINE"
				rednet.send(reactorMonitorId, textutils.serialize{type="reactor", sender="cooling", command="stop"})
				sendStatus()
		end
end

local function startSystem()
		if reactorMonitorId then
				coolingStatus = "ONLINE"
				rednet.send(reactorMonitorId, textutils.serialize{type="reactor", sender="cooling", command="start"})
				sendStatus()
		end
end

local function handleReactorMonitor(senderId, message)
		if message.command == "announce" then
				reactorMonitorId = senderId
				rednet.send(senderId, textutils.serialize{type="reactor", sender="cooling", command="ack"})
				sendStatus()
		elseif message.command == "ack" then
				reactorMonitorId = senderId		  
				sendStatus()
		elseif message.command == "status" then
				reactorStatus = message.status
		end
end

local function handleStatsSystem(senderId, message)
		if message.command == "announce" then
				statsSystemId = senderId
				rednet.send(storageSystemId, textutils.serialize{type="reactor", sender="cooling", command="ack"})
		elseif message.command == "ack" then
				statsSystemId = senderId
		end
end

local function doNetwork()
		print("Starting network...")
		rednet.broadcast(textutils.serialize{type="reactor", sender="cooling", command="announce"})
		while true do
				local event, senderId, data, distance = os.pullEvent("rednet_message")
				local message = textutils.unserialize(data)
				if message and message.type == "reactor" then
						if message.sender == "monitor" then
								handleReactorMonitor(senderId, message)
						elseif message.sender == "stats" then
								handleStatsSystem(senderId, message)
						end
				end
		end

end

local function fastSleep()
		sleep(.3)
end

local function getLZHDurability(lzhSlot)
		if lzhSlot then
				local damVal = analyzer.getBlockMetadataAt(lzhSlot)
				return (10000 - damVal)
		end
end

local function dropOld(slot)
		turtle.select(slot)
		while not turtle.dropDown() do
				print("Old condensator chest is full, waiting...")
				sleep(1)
		end
end

local function doCondensatorStocking()
		for i = 1, 8 do
				if turtle.getItemCount(i) < 1 then
						turtle.select(i)
						if not turtle.suckUp() then break end
				end
		end
end

local function placeCondensator(block)
		while true do
				for i = 1, 8 do
						if turtle.getItemCount(i) > 0 then
								turtle.select(i)
								analyzer.placeAt(block)
								return
						end
				end
				turtle.select(1)
				while not turtle.suckUp() do
						print("Waiting for new condensator...")
						sleep(1)
				end
		end
end

local function doCooling()
		print("Starting cooling system...")
		while true do
				local needToReplace = false
				for _, block in ipairs(condensatorBlocks) do
						local durability = getLZHDurability(block)
						if durability <= 1000 then
								stopSystem()
								needToReplace = true
								break
						end
				end		  
				if needToReplace then
						while reactorStatus == "ONLINE" do
								coroutine.yield()
						end
						local badIndex = 9
						for _, block in ipairs(condensatorBlocks) do
								local durability = getLZHDurability(block)
								if durability <= 2000 then
										turtle.select(badIndex)
										analyzer.takeAt(block)
										placeCondensator(block)
										badIndex = badIndex + 1
										condensatorsReplaced = condensatorsReplaced + 1
								end
						end				  
				else
						doCondensatorStocking()
				end
				if reactorStatus == "OFFLINE" and reactorMonitorId then
						startSystem()
				end
				if needToReplace then
						for i = 9, 16 do
								if turtle.getItemCount(i) > 0 then
										dropOld(i)
								end
						end
				end

				fastSleep()
		end
end

local lzhTable = {}
local function drawLZH()	  
		lzhTable = {}
		print("LZH Durability:")
		print("-------------------------------------")
		for i = 1, #condensatorBlocks, 4 do
				local blockOneDura = getLZHDurability(condensatorBlocks[i])
				local blockTwoDura = getLZHDurability(condensatorBlocks[i+1])
				local blockThreeDura = getLZHDurability(condensatorBlocks[i+2])
				local blockFourDura = getLZHDurability(condensatorBlocks[i+3])
				if blockOneDura then table.insert(lzhTable, blockOneDura) end
				if blockTwoDura then table.insert(lzhTable, blockTwoDura) end
				if blockThreeDura then table.insert(lzhTable, blockThreeDura) end
				if blockFourDura then table.insert(lzhTable, blockFourDura) end
				local blockOneOutput = blockOneDura and string.format("%3d%%", blockOneDura/100) or "	"
				local blockTwoOutput = blockTwoDura and string.format("%3d%%", blockTwoDura/100) or "	"
				local blockThreeOutput = blockThreeDura and string.format("%3d%%", blockThreeDura/100) or "	"
				local blockFourOutput = blockFourDura and string.format("%3d%%", blockFourDura/100) or "	"
				print(string.format("|  %s  |  %s  |  %s  |  %s  |", blockOneOutput, blockTwoOutput, blockThreeOutput, blockFourOutput))
		end
		print("-------------------------------------")
end

local function doMenu()
		print("Displaying menu...")
		while true do
				sleep(1)
				term.clear()
				term.setCursorPos(1,1)
				print(string.format("Cooling System Status: %s", coolingStatus))
				print(string.format("Reactor Monitor Id:	%s", reactorMonitorId and tostring(reactorMonitorId) or "Unknown"))
				print(string.format("Reactor Status:		%s", reactorStatus))
				print(string.format("Condensators Replaced: %s", util.commavalue(condensatorsReplaced)))
				drawLZH()
				if statsSystemId then
						stats = { coolingStatus = coolingStatus, condensatorsReplaced = condensatorsReplaced, condensators = lzhTable }
						rednet.send(statsSystemId, textutils.serialize{type="reactor", sender="cooling", command="stats", stats=stats})
				end
				print("Press Q to exit")
		end
end

local function doKeyboard()
		print("Starting keyboard handler...")
		while true do
				local event, key = os.pullEvent("char")
				if string.lower(key) == "q" then
						break
				end
		end
end

local function startup()
		term.clear()
		term.setCursorPos(1,1)
		io.write("Building condensator pattern...")
		for i = 1, reactorSize do			
				if analyzer.getBlockIdAt(i) == condensatorBlockId then
						table.insert(condensatorBlocks, i)			
				end
		end

		if #condensatorBlocks > 0 then
				io.write("DONE")
				print()
				parallel.waitForAny(doNetwork, doCooling, doKeyboard, doMenu)
		else
				error("Could not find LZH-Condensators in reactor")
		end  

end


local rtn, error = pcall(startup)
if not rtn then
		print("Cooling failed: " .. error)
end
print("Telling reactor to go OFFLINE.")
print("Exiting.")
stopSystem()

The problem with this code is that its calling (getBlockIdAt,getLZHDurability,takeAt,getBlockMetadataAt(lzhSlot)) etc…
Reading around I see that a few members here claimed that the sensor card can do more then item analyzer but I cant find any code to show it can take items.

for example item analyzer has analyzer.placeAt(slot),analyzer.placeAtUp(slot), analyzer.placeAtDown(slot).
Is there an OpenCC alternative ?
And thanks all for responding. Everything has been a huge help. :)/>
Edited on 12 December 2013 - 12:08 AM