(LUA) ComputerCraft API ProgressBar

By Sorasyn on Jan 13, 2014

Thought I'd throw a snippet in here for those Minecrafters who like to play, and/or are familiar, with ComputerCraft. This is not actually a Bukkit platform snippet, it's just a straight Lua script to be used in game.

ComputerCraft is a mod for Minecraft which, as the name suggests, adds computers among other things to the game. All of which can be programmed using Lua. This snippet in particular acts as an API that allows for Advanced Computer objects to easily draw manageable progress bars to an external monitor.

Image

Notable Functions:
SetPeripheral(side) -> This is used to tell the API which side of the monitor the computer is attached to. This must be called, before anything is drawn, or obviously it won't show up.

SetTable(name, maxVal, curVal, xmin, xmax, y) -> Creates a Progress Bar profile, from which the actual object is drawn from. The values "maxVal", and "curVal", can be adjusted from their respective methods below to change how the object is drawn on screen. (In other words, it adds the progress bar to the two dimensional array of already present progress bars.

ClearTable() -> Clears the two dimensional array back to default, effectively erasing any progress bar profiles that were added.

DrawToPeripheral() -> This queues the API to draw the progress bars to the monitor. (Set with SetPeripheral()) Call this to update any progress bars drawn on the screen.

DrawBar() -> No need to worry about this method, as it's only used from within the API, and provides no usable functionality. It is there purely to assist the DrawToPeripheral() function to execute the drawing of the objects.

Few things to note: Colors can be adjusted via the appropriate functions below, and as per allowed by the "colors" API.

Enjoy!

local monitor
local hasMonitor = false
local ProgressBar = {}
local FillColor = colors.orange
local EmptyColor = colors.blue
local TextColor = colors.white

function SetPeripheral(side)
  if (peripheral.isPresent(side)) then
    monitor = peripheral.wrap(side)
    hasMonitor = true
  end
end

function SetTable(name, maxVal, curVal, xmin, xmax, y)
  ProgressBar[name] = {}
  ProgressBar[name]["Max"] = maxVal
  ProgressBar[name]["Current"] = curVal
  ProgressBar[name]["XMin"] = xmin
  ProgressBar[name]["XMax"] = xmax
  ProgressBar[name]["YVal"] = y
end

function ClearTable()
  if (hasMonitor) then
    ProgressBar = {}
  end
end

function SetFillColor(color)
  if (colors.combine(color,color)) then  
    FillColor = color
  end
end

function SetEmptyColor(color)
  if (colors.combine(color,color)) then
    EmptyColor = color
  end
end

function SetTextColor(color)
  if (colors.combine(color,color)) then
    TextColor = color
  end
end

function SetMaxValue(name, intVal)
  if (ProgressBar[name]) then
    ProgressBar[name]["Max"] = intVal
  end
end

function SetCurValue(name, intVal)
  if (ProgressBar[name]) then
    ProgressBar[name]["Current"] = intVal
  end
end

function DrawToPeripheral()
  if (hasMonitor) then
    for name, data in pairs(ProgressBar) do
      DrawBar(name, data)
    end
  end
end

function DrawBar(name, arr)
  local y = arr["YVal"]
  local fill = math.floor((arr["XMax"] - arr["XMin"]) * (arr["Current"] / arr["Max"]))

  monitor.setBackgroundColor(FillColor)
  monitor.setTextColor(TextColor)

  for x = arr["XMin"], arr["XMax"] do
    local num = math.floor(x - arr["XMin"])
    monitor.setCursorPos(x,y)

    if (num > fill) then
      monitor.setBackgroundColor(EmptyColor)
    end

    if (num == 0) then
      monitor.write("[")
    end
    if (x == arr["XMax"]) then
      monitor.write("]")
    else
      monitor.write(" ")
    end
  end

  monitor.setBackgroundColor(colors.black)
end

Example: The below code allows the program to: use the API, configures it to interact with the monitor (on the left), creates a progress bar, draws it to the screen, waits five seconds (sleep(5)), updates the value of the bar named "Test", and re-draws it to the monitor.

os.loadAPI("ProgressBar")
ProgressBar.SetPeripheral("left")

ProgressBar.SetTable("Test", 10, 1, 5,25,5)
ProgressBar.DrawToPeripheral()

sleep(5)

ProgressBar.SetCurValue("Test",5)
ProgressBar.DrawToPeripheral()

End Result:
Image

Comments

Sign in to comment.
DireTry20   -  Jun 16, 2015

hey sorasyn great API, but can there please be an option to make the progress bar vertical

Sorasyn  -  Jun 16, 2015

Yes, I can look at polishing up this code a bit, and adding in vertical progress bars. I believe that was something I had looked at in the past, but for whatever reason, I decided against it.

Vertical progress bars will, however, lose some visual accuracy as opposed to horizontal. This is because the cursor is twice as tall as it is wide.

Thanks for the comment. I'll see about rolling out an update this week sometime.

Sign in to comment

Alix_the_Alicorn   -  Feb 15, 2014

Could you post the code for your AE monitor? Also, nice API I am using it for a Redstone Flux monitor. It shows percentage and amount for each cell and all of them put together.

Sorasyn  -  Feb 16, 2014

Yeah, I'd be happy to upload my AE network code. I'll upload it later today when I get back home, and am able to pull the appropriate files.

I'd be curious to find out how you managed to pull information from RF battery cells. I have 4 Redstone Energy Cells (stores, and outputs RF/MJ), but I cannot seem to find the appropriate methods to pull charge information.

EDIT: This snippet is run on an independent Advanced Computer block, which is placed just underneath the ME network's controller block (in my world at least), and wraps the controller as a peripheral. It should work well enough to report basic information, with minuscule changes.

local ctrl = peripheral.wrap("top")

function ParseMsg(id, msg)
  --if (id == 4) then
    if (msg == "Query_BYTES_TOTAL") then
      rednet.send(id, ctrl.getTotalBytes())
    end
    if (msg == "Query_BYTES_FREE") then
      rednet.send(id, ctrl.getFreeBytes())
    end
    if (msg == "Query_BYTES_USED") then
      rednet.send(id, ctrl.getUnusedBytes())
    end
    if (msg == "Query_SLOTS_TOTAL") then
      rednet.send(id, ctrl.getTotalItemTypes())
    end
    if (msg == "Query_SLOTS_FREE") then
      rednet.send(id, ctrl.getRemainingItemTypes())
    end
    if (msg == "Query_SLOTS_USED") then
      rednet.send(id, ctrl.getTotalItemTypes() - ctrl.getRemainingItemTypes())
    end
  --end
end

function ReceiveAsync()
  while true do
    id, msg, time = rednet.receive()
    print(msg)
    print(id)
    ParseMsg(id, msg)
  end
end

rednet.open("left")
ReceiveAsync()
rednet.close("left")
Alix_the_Alicorn  -  Feb 27, 2014

Thanks :P btw, to read the RF you have to have OpenPeripheral installed, and I used wired modems to connect to my cells. the methods are something like getMaxEnergyStored("string") and getEnergyStored("string") and the string isn't used for anything, I usually just pass in "nil".

Alix_the_Alicorn  -  Feb 27, 2014

Sorry about the late reply

Sorasyn  -  Feb 27, 2014

Thanks, I'll give it a shot whenever I get on next. I didn't think the RF/MJ cells were even supported in the newest mod version releases (1.6.2 I believe it is).

No worries. I've been somewhat busy myself so I've not even had time to play around on Minecraft.

Sign in to comment

Hawkee   -  Jan 13, 2014

Neat, could this be wired to multiple furnaces to indicate progress of the entire contents of each furnace?

Sorasyn  -  Jan 13, 2014

I'm sure they could be. I've not tried it personally, but the capabilities of Lua, in game, are surprisingly robust. Thus far I've only used CC to emit redstone signals over small distances, and as the picture shows, item storage stats from another mod.

Sign in to comment

Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.